Aligning Next.js with FastAPI: Two Proxy Prefixes, One API
Why the web app exposes both /api/backend and /api/autonomy, how rewrites map to /api/v1, and how to verify wiring without guessing.
Same origin, two prefixes
In a typical setup, the browser only talks to the web origin. The Next.js app then forwards selected paths to internal services. In this repository, two prefixes reach the same FastAPI service with slightly different path mapping:
- /api/backend/ — rewritten to /api/v1/ on the API host. Use this for general v1 routes, including many paths under /api/v1/autonomy/... when the client already includes autonomy after backend.
- /api/autonomy/ — rewritten directly to /api/v1/autonomy/ on the API host. Useful for older or shorter client paths that assume an /api/autonomy/... shape.
The important idea is not memorizing every URL by heart. It is knowing that both are server-side rewrites driven by environment variables such as API_INTERNAL_URL, so you can change where the API lives without rebuilding client bundles for that detail.
Environment variables that matter
API_INTERNAL_URL (or a public fallback where configured) tells Next.js where to send /api/backend and /api/autonomy traffic. In Docker Compose, that is usually an internal hostname like http://api:8000, not localhost.
AUTH_INTERNAL_URL is separate: /auth/ routes go to your auth service. If login fails in a container deployment, the first thing to check is often "can the web container reach the auth hostname on the internal network?"
How to verify
1. Hit the API directly. From any host that can reach the API process, call /health and /openapi.json. If those fail, proxies will not fix the problem.
2. Hit the web origin. Use the same paths the browser uses (for example /api/autonomy/...) and inspect HTTP status codes. A 502 often means the rewrite target is wrong or unreachable.
3. Read the spec. openapi.json lists the real operations your deployment exposes. Treat it as the contract—not blog posts or stale examples.
No magic in the browser
Nothing in this pattern relies on hidden client-side routing secrets. The browser sees normal same-origin fetch calls; the server applies the rewrite table. That keeps deployment-specific hostnames out of public JavaScript while still allowing a single web entry point for users.
Build with proof, not promises
Join the developers compiling intent into deployable software with deterministic gates.