diff --git a/next.config.ts b/next.config.ts index ca61882..8b59fee 100644 --- a/next.config.ts +++ b/next.config.ts @@ -4,6 +4,20 @@ import type { NextConfig } from "next"; // client-reference manifests and route transitions. See docs: // https://nextjs.org/docs/app/building-your-application/configuring const nextConfig: NextConfig = { + async rewrites() { + const rawApiUrl = process.env.NEXT_PUBLIC_API_URL; + if (!rawApiUrl || !/^https?:\/\//i.test(rawApiUrl)) { + return []; + } + + const normalized = rawApiUrl.replace(/\/$/, ''); + return [ + { + source: '/api/:path*', + destination: `${normalized}/:path*`, + }, + ]; + }, async headers() { return [ { diff --git a/package.json b/package.json index 998cc52..9e3a856 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "node": ">=20 <21" }, "scripts": { - "dev": "next dev", + "dev": "next dev --webpack", "build": "next build --webpack", "start": "next start", "lint": "next lint" diff --git a/src/components/auth/SignInForm.tsx b/src/components/auth/SignInForm.tsx index f5e70db..717e86e 100644 --- a/src/components/auth/SignInForm.tsx +++ b/src/components/auth/SignInForm.tsx @@ -7,6 +7,7 @@ import { ChevronLeftIcon, EyeCloseIcon, EyeIcon } from "@/icons"; import Link from "next/link"; import React, { useState, useEffect } from "react"; import { apiClient } from "@/lib/api-client"; +import { getApiBaseUrl } from "@/lib/api"; import { useRouter, useSearchParams } from "next/navigation"; export default function SignInForm() { @@ -60,7 +61,8 @@ export default function SignInForm() { try { // Redirect to backend Google OAuth endpoint const redirectUrl = `${window.location.origin}/auth/callback`; - window.location.href = `${process.env.NEXT_PUBLIC_API_URL}/auth/google?redirect_uri=${encodeURIComponent(redirectUrl)}&next=${encodeURIComponent(nextDest)}`; + const apiBaseUrl = getApiBaseUrl(); + window.location.href = `${apiBaseUrl}/auth/google?redirect_uri=${encodeURIComponent(redirectUrl)}&next=${encodeURIComponent(nextDest)}`; } catch (err) { const error = err as { message?: string }; setError(error?.message || "Google sign-in failed. Please try again."); diff --git a/src/lib/api-client.ts b/src/lib/api-client.ts index 990a488..601a32a 100644 --- a/src/lib/api-client.ts +++ b/src/lib/api-client.ts @@ -3,7 +3,9 @@ * Replaces Supabase client for authentication and data operations */ -const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001/api'; +import { getApiBaseUrl } from "@/lib/api"; + +const API_URL = getApiBaseUrl(); export interface AuthResponse { token: string; diff --git a/src/lib/api.ts b/src/lib/api.ts index 17f3011..1129991 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -14,7 +14,11 @@ const RESOURCE_PATH_MAP: Record = { const normalizePath = (path: string) => RESOURCE_PATH_MAP[path] || path; export const getApiBaseUrl = (): string => { - return (process.env.NEXT_PUBLIC_API_URL || DEFAULT_API_BASE_URL).replace(/\/$/, ''); + const rawBaseUrl = (process.env.NEXT_PUBLIC_API_URL || DEFAULT_API_BASE_URL).replace(/\/$/, ''); + if (typeof window !== 'undefined' && /^https?:\/\//i.test(rawBaseUrl)) { + return '/api'; + } + return rawBaseUrl; }; export const toApiUrl = (pathOrUrl: string): string => {