diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 150eec1..0239d01 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -44,10 +44,17 @@ interface ApiQueryResult { } function getApiBaseUrl() { + // Priority 1: NEXT_PUBLIC_API_BASE_URL if (process.env.NEXT_PUBLIC_API_BASE_URL) { return process.env.NEXT_PUBLIC_API_BASE_URL; } + // Priority 2: NEXT_PUBLIC_API_URL + if (process.env.NEXT_PUBLIC_API_URL) { + return process.env.NEXT_PUBLIC_API_URL; + } + + // Priority 3: localhost for development if (typeof window !== "undefined") { return `${window.location.protocol}//${window.location.hostname}:8000`; } diff --git a/frontend/src/lib/intelligence/client.ts b/frontend/src/lib/intelligence/client.ts index 41fee44..0409ff8 100644 --- a/frontend/src/lib/intelligence/client.ts +++ b/frontend/src/lib/intelligence/client.ts @@ -86,15 +86,43 @@ function resolveBaseUrl(explicit: string | undefined): string { if (explicit) { return explicit.replace(/\/$/, ""); } + + // Priority 1: NEXT_PUBLIC_API_BASE_URL if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_API_BASE_URL) { return process.env.NEXT_PUBLIC_API_BASE_URL.replace(/\/$/, ""); } + + // Priority 2: NEXT_PUBLIC_API_URL + if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_API_URL) { + return process.env.NEXT_PUBLIC_API_URL.replace(/\/$/, ""); + } + + // Priority 3: localhost for development if (typeof window !== "undefined") { return `${window.location.protocol}//${window.location.hostname}:8000`; } + return "http://localhost:8000"; } +function getWebSocketUrl(): string { + // Priority 1: NEXT_PUBLIC_WS_URL + if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_WS_URL) { + return process.env.NEXT_PUBLIC_WS_URL; + } + + // Priority 2: Derive from API URL + const apiUrl = resolveBaseUrl(undefined); + if (apiUrl.startsWith("https://")) { + return apiUrl.replace("https://", "wss://"); + } + if (apiUrl.startsWith("http://")) { + return apiUrl.replace("http://", "ws://"); + } + + return "ws://localhost:8000"; +} + async function request( path: string, params: Record = {}, diff --git a/infra/docker/frontend.Dockerfile b/infra/docker/frontend.Dockerfile index d886163..249f2b8 100644 --- a/infra/docker/frontend.Dockerfile +++ b/infra/docker/frontend.Dockerfile @@ -7,12 +7,16 @@ WORKDIR /app/frontend # Build-time args (public env vars baked into the Next.js build). # These are visible in the browser bundle — never put secrets here. -ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000 -ARG NEXT_PUBLIC_WS_BASE_URL=ws://localhost:8000 +# No defaults: the app falls back to localhost:8000 at runtime when unset, +# so omitting defaults here ensures Railway-injected values are always used. +ARG NEXT_PUBLIC_API_BASE_URL +ARG NEXT_PUBLIC_API_URL +ARG NEXT_PUBLIC_WS_URL ARG NEXT_PUBLIC_CESIUM_ION_TOKEN ENV NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL} -ENV NEXT_PUBLIC_WS_BASE_URL=${NEXT_PUBLIC_WS_BASE_URL} +ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL} +ENV NEXT_PUBLIC_WS_URL=${NEXT_PUBLIC_WS_URL} ENV NEXT_PUBLIC_CESIUM_ION_TOKEN=${NEXT_PUBLIC_CESIUM_ION_TOKEN} ENV NEXT_TELEMETRY_DISABLED=1