docs(deploy): stop documenting API_ORIGIN as required

The swarm stack still hard-failed on an unset API_ORIGIN, and both the env
template and the README told the reader to pin it — the exact habit the derived
origin was meant to end. Make it an optional override everywhere, and say that
WEB_ORIGIN is now a list.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 12:56:50 -07:00
co-authored by Claude Opus 5
parent 14c6183aa2
commit 683fd37b08
3 changed files with 29 additions and 7 deletions
+8 -1
View File
@@ -96,7 +96,14 @@ NEXT_PUBLIC_API_ORIGIN=http://localhost:3001
``` ```
The API loads `DATABASE_URL`, `SESSION_SECRET`, `WEB_ORIGIN`, and optional The API loads `DATABASE_URL`, `SESSION_SECRET`, `WEB_ORIGIN`, and optional
`PORT` (default `3001`). The web app only needs `NEXT_PUBLIC_API_ORIGIN`. `PORT` (default `3001`). `WEB_ORIGIN` is comma-separated — list every origin the
app is reached under, or credentialed fetches from the missing ones fail CORS.
The web app needs no API URL of its own: the browser derives it from the page it
loaded (same host on port `3001` over plain HTTP, or the same-origin `/api` path
behind a TLS proxy). Set `NEXT_PUBLIC_API_ORIGIN` (dev) or `API_ORIGIN` (deploy,
read at request time) only to override that — for instance when running the API
on a non-default port.
### 3. Start MySQL ### 3. Start MySQL
+15 -4
View File
@@ -8,10 +8,21 @@
APP_TAG=latest APP_TAG=latest
# --- Public URLs (what the end user's BROWSER hits) --------------------------- # --- Public URLs (what the end user's BROWSER hits) ---------------------------
# API_ORIGIN is injected into the web app at runtime and used for browser fetches # API_ORIGIN is OPTIONAL and normally left unset. The browser derives the API
# + document download links, so it must be browser-reachable (not swarm-internal). # origin from the page it loaded (apps/web/src/lib/api.ts): same host on port
# WEB_ORIGIN is the web app's own public origin; the API allows it via CORS. # 3001 over plain HTTP, or the same-origin /api path when the page is served
API_ORIGIN=http://192.168.4.212:3001 # over https by a TLS-terminating proxy that maps /api to the API. That is what
# lets the same deployment move — tailnet, office LAN, demo domain — untouched.
# Set it only when the API genuinely lives on a different host than the web app;
# it is used for browser fetches AND document download links, so it must be
# browser-reachable (never a swarm-internal name).
#API_ORIGIN=http://192.168.4.212:3001
#
# WEB_ORIGIN is the list of public origins the web app is reached under; the API
# allows them via CORS. COMMA-SEPARATED — one deployment is reachable under
# several origins (LAN IP, tailnet name, demo domain) and a credentialed fetch
# from an origin missing here gets no CORS headers and fails. A same-origin
# setup (web + API behind one proxy) never hits CORS at all.
WEB_ORIGIN=http://192.168.4.212:3000 WEB_ORIGIN=http://192.168.4.212:3000
# Published ports on the swarm host. # Published ports on the swarm host.
+6 -2
View File
@@ -92,8 +92,12 @@ services:
labels: labels:
io.jorgecuadros.role: "web" io.jorgecuadros.role: "web"
environment: environment:
# Public API URL the browser calls (injected at runtime, see layout.tsx). # OPTIONAL override of the API URL the browser calls (injected at runtime,
API_ORIGIN: ${API_ORIGIN:?API_ORIGIN must be set} # see layout.tsx). Leave it unset: the browser then derives the origin
# from the page it loaded — same host on port 3001 over plain HTTP, or
# /api behind a TLS-terminating proxy. Set it only when the API really
# lives on a different host than the web app.
API_ORIGIN: ${API_ORIGIN:-}
ports: ports:
- target: 3000 - target: 3000
published: ${WEB_PORT:-3000} published: ${WEB_PORT:-3000}