Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions frontend/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`;
}
Expand Down
28 changes: 28 additions & 0 deletions frontend/src/lib/intelligence/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>(
path: string,
params: Record<string, string | number | undefined> = {},
Expand Down
10 changes: 7 additions & 3 deletions infra/docker/frontend.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down