// packages/core/src/web-urls.ts // 공개 웹 주소 SSOT — 결제·법률·다운로드·초대 링크는 모두 여기서 만든다. // // 한 도메인 아래 세 서비스가 있다. // / 랜딩 사이트(site/, Cloudflare Pages) — 다운로드, 법률 문서, 초대 수락 // /app/... 웹앱(apps/web, Next basePath '/app') — 로그인, 결제, 대시보드 // /api, /health API 서버(apps/api-server) — 관리자 인증, STT 중계 // 사이트 브리지 워커(server/cloudflare-site-bridge)가 /app·/api 요청을 도메인 원본 // (Cloudflare Tunnel kd-nas → NAS)으로 흘려보내고, 나머지는 Pages로 보낸다. // 터널 ingress: d3ro.chanpaca.net path ^/app → NAS 3002, 그 밖 → NAS 5050. // Deno 쪽 사본은 plan-catalog.ts 와 같은 방식으로 생성된다. 이 파일도 순수 값만 둔다. import type { PaidPlanTier } from './plan-catalog' export const PUBLIC_SITE_ORIGIN = 'https://d3ro.chanpaca.net' /** apps/web 의 Next basePath. next.config 와 브리지 워커 라우팅이 이 값을 따른다. */ export const WEB_APP_BASE_PATH = '/app' export const WEB_APP_URL = `${PUBLIC_SITE_ORIGIN}${WEB_APP_BASE_PATH}` /** API 서버(apps/api-server)가 받는 경로. 관리자 로그인·stt-proxy가 이 도메인으로 부른다. */ export const API_PATH_PREFIXES = ['/api', '/health'] as const export const SITE_URLS = { home: `${PUBLIC_SITE_ORIGIN}/`, download: `${PUBLIC_SITE_ORIGIN}/#download`, privacy: `${PUBLIC_SITE_ORIGIN}/privacy/`, terms: `${PUBLIC_SITE_ORIGIN}/terms/`, deleteAccount: `${PUBLIC_SITE_ORIGIN}/delete-account/`, acceptInvite: `${PUBLIC_SITE_ORIGIN}/accept-invite/`, } as const /** * 웹 결제 페이지 URL. 결제는 이 페이지 안의 Payple 창에서 끝나므로 복귀 쿼리가 없다. * - `tier`: 고를 요금제를 미리 선택한다. */ export function billingUrl(options: { tier?: PaidPlanTier } = {}): string { const params = new URLSearchParams() if (options.tier) params.set('tier', options.tier) const query = params.toString() return `${WEB_APP_URL}/billing${query ? `?${query}` : ''}` }