diff --git a/frontend/app/api/auth/google/token/route.ts b/frontend/app/api/auth/google/token/route.ts index cf8b66c1..fd39c0ca 100644 --- a/frontend/app/api/auth/google/token/route.ts +++ b/frontend/app/api/auth/google/token/route.ts @@ -3,14 +3,11 @@ * This proxies the token exchange to the backend */ import { NextRequest, NextResponse } from "next/server"; - -// Use backend internal URL if available (Railway), fallback to public URL -const BACKEND_URL = process.env.BACKEND_URL || - process.env.NEXT_PUBLIC_API_URL || - "http://localhost:8000"; +import { getBackendUrl } from "@/lib/backend-url"; export async function POST(request: NextRequest) { try { + const backendUrl = getBackendUrl(); const body = await request.json(); const { code, redirect_uri } = body; @@ -22,7 +19,7 @@ export async function POST(request: NextRequest) { } // Forward to backend - const backendResponse = await fetch(`${BACKEND_URL}/api/auth/google/token`, { + const backendResponse = await fetch(`${backendUrl}/api/auth/google/token`, { method: "POST", headers: { "Content-Type": "application/json", diff --git a/frontend/app/api/chat/route.ts b/frontend/app/api/chat/route.ts index 9f6b1794..f55b469c 100644 --- a/frontend/app/api/chat/route.ts +++ b/frontend/app/api/chat/route.ts @@ -1,11 +1,9 @@ import { NextResponse } from "next/server"; +import { getBackendUrl } from "@/lib/backend-url"; export async function POST(req: Request) { try { - const isDev = process.env.NODE_ENV === "development"; - const backendUrl = - process.env.BACKEND_URL || - (isDev ? "http://localhost:8000" : "http://backend:8000"); + const backendUrl = getBackendUrl(); // Read the complete body from the request const bodyText = await req.text(); diff --git a/frontend/lib/backend-url.ts b/frontend/lib/backend-url.ts new file mode 100644 index 00000000..e0478007 --- /dev/null +++ b/frontend/lib/backend-url.ts @@ -0,0 +1,27 @@ +/** + * Unified backend URL resolution for server-side proxying. + * + * Priority: + * 1. BACKEND_URL – explicit override (Railway / custom deployment) + * 2. Development mode – http://localhost:8000 + * 3. NEXT_PUBLIC_API_URL – fallback (often set in Railway for client-side too) + * 4. Docker Compose default – http://backend:8000 + * + * Used by next.config.ts rewrites and Next.js API route handlers. + */ +export function getBackendUrl(): string { + if (process.env.BACKEND_URL) { + return process.env.BACKEND_URL; + } + + if (process.env.NODE_ENV === "development") { + return "http://localhost:8000"; + } + + if (process.env.NEXT_PUBLIC_API_URL) { + return process.env.NEXT_PUBLIC_API_URL; + } + + // Docker Compose internal hostname (only works when both services share a Docker network) + return "http://backend:8000"; +} diff --git a/frontend/next.config.ts b/frontend/next.config.ts index 97e29448..34a20338 100644 --- a/frontend/next.config.ts +++ b/frontend/next.config.ts @@ -1,4 +1,5 @@ import type { NextConfig } from "next"; +import { getBackendUrl } from "./lib/backend-url"; const nextConfig: NextConfig = { output: 'standalone', @@ -56,13 +57,7 @@ const nextConfig: NextConfig = { }, async rewrites() { - // In development: use localhost backend - // In production (Railway): use BACKEND_URL env var or fallback to Railway URL - const isDev = process.env.NODE_ENV === 'development'; - // Default to http://backend:8000 in production (Docker) if not set - const backendUrl = process.env.BACKEND_URL || - (isDev ? "http://localhost:8000" : "http://backend:8000"); - + const backendUrl = getBackendUrl(); console.log(`[Next.js] Rewriting API requests to: ${backendUrl}`); return [