Summary
apps/admin/src/lib/api-client.ts was changed this session to add server-vs-client URL resolution. The new code reads typeof window === 'undefined' at module load time:
```ts
export const apiBaseUrl: string = resolveApiBaseUrl();
```
In Next.js, Client Components are bundled at build time. During webpack analysis, typeof window === 'undefined' evaluates to TRUE → server branch wins → process.env.GONEXT_API_URL (`http://api:8080\`) is the value the bundler tries to inline.
NEXT_PUBLIC_API_URL is also inlined; if it's \"\" (the docker default) the client branch's pub === undefined ? DEFAULT : pub evaluates to \"\" — which is what we want for same-origin/rewrites. But the module-load constant in apps/admin/src/lib/api-client.ts:54 is the hazard: Client Components that import api see the resolved value at module evaluation time, and the type system can't distinguish "this is a Client Component" from "this is a Server Component" at the module level.
Reproduction (suspected — needs verification)
- Rebuild admin image (
docker compose build admin).
- Visit any page that uses a Client Component reading
/api/v1/* (e.g. /posts infinite-scroll, /users filter).
- Open DevTools → Network. Check the request URL.
Expected: same-origin /api/v1/... (handled by Next.js rewrites).
Suspected actual: http://api:8080/api/v1/... (DNS failure in browser).
Recommended fix
Convert apiBaseUrl from a module-load constant to a runtime getter:
```ts
function apiBaseUrl(): string { /* current resolveApiBaseUrl logic */ }
```
Update apiRequest and any direct consumers to call the function at request time, so the typeof window check evaluates in the browser's actual runtime.
Files to touch
apps/admin/src/lib/api-client.ts
- Any consumer that destructures
apiBaseUrl (search for the import)
Related
Summary
apps/admin/src/lib/api-client.tswas changed this session to add server-vs-client URL resolution. The new code readstypeof window === 'undefined'at module load time:```ts
export const apiBaseUrl: string = resolveApiBaseUrl();
```
In Next.js, Client Components are bundled at build time. During webpack analysis,
typeof window === 'undefined'evaluates to TRUE → server branch wins →process.env.GONEXT_API_URL(`http://api:8080\`) is the value the bundler tries to inline.NEXT_PUBLIC_API_URL is also inlined; if it's
\"\"(the docker default) the client branch'spub === undefined ? DEFAULT : pubevaluates to\"\"— which is what we want for same-origin/rewrites. But the module-load constant inapps/admin/src/lib/api-client.ts:54is the hazard: Client Components that importapisee the resolved value at module evaluation time, and the type system can't distinguish "this is a Client Component" from "this is a Server Component" at the module level.Reproduction (suspected — needs verification)
docker compose build admin)./api/v1/*(e.g./postsinfinite-scroll,/usersfilter).Expected: same-origin
/api/v1/...(handled by Next.js rewrites).Suspected actual:
http://api:8080/api/v1/...(DNS failure in browser).Recommended fix
Convert
apiBaseUrlfrom a module-load constant to a runtime getter:```ts
function apiBaseUrl(): string { /* current resolveApiBaseUrl logic */ }
```
Update
apiRequestand any direct consumers to call the function at request time, so thetypeof windowcheck evaluates in the browser's actual runtime.Files to touch
apps/admin/src/lib/api-client.tsapiBaseUrl(search for the import)Related