Skip to content

frontend: support serving the app under a sub-path - #20

Open
albertotb wants to merge 1 commit into
mainfrom
claude/frontend-base-path
Open

frontend: support serving the app under a sub-path#20
albertotb wants to merge 1 commit into
mainfrom
claude/frontend-base-path

Conversation

@albertotb

Copy link
Copy Markdown
Member

The blank-page bug I hit building the CI preview artifact, fixed properly.

The bug

The build is root-only: no base in vite.config.ts, a bare <BrowserRouter>, and an API base hardcoded to /api. Served from anything but the domain root, index.html asks for /assets/index-*.js, which isn't there — blank page, two 404s in the console. That's why the preview artifact needed a history.replaceState shim to render at all.

The fix

One variable, threaded through: VITE_BASE_PATH → Vite's baseimport.meta.env.BASE_URL → the router's basename and the default API base. The dev proxy keys off the same value, so npm run dev under a prefix proxies <prefix>/api correctly too. Unset, everything resolves to / and nothing changes.

VITE_BASE_PATH=/myapp/ npm run build
# or: docker build --build-arg VITE_BASE_PATH=/myapp/ .

A trailing slash is added if you leave it off, matching how Vite normalises base.

Verified in a real browser

Both builds served from the same nginx, headless Chromium, /about loaded directly:

root build under /old/ (today's behaviour) VITE_BASE_PATH=/myapp/ build under /myapp/
rendered heading none About
body text empty React Template HOME ABOUT About This page exists…
console 2 × 404 (Not Found) clean
bundle request /assets/index-*.js404 /myapp/assets/index-*.js → 200

Also checked: clicking ABOUT from /myapp/ client-side navigates to /myapp/about and renders, and the home page's version chip requests /myapp/api/ rather than /api/.

Root build output is byte-identical in its asset URLs (src="/assets/index-DvrTU-L4.js" before and after), so the default path is untouched. npm run lint, format:check, test and build all pass.

Notes

  • vite.config.ts becomes the function form so it can call loadEnv — that's what lets VITE_BASE_PATH come from an .env file, the shell, or a Docker build arg, the same three ways as VITE_API_URL. The proxy block itself is unchanged apart from the base-aware key.
  • The API base now defaults to `${BASE_URL}api`. At the root that is /api, exactly as before; VITE_API_URL still overrides it entirely.
  • Serving under a prefix still needs the proxy in front to route the files and the API prefix there — documented in frontend/README.md. No nginx change here: docker/nginx.conf serves the root case, which is the template's default.
  • No new test: the useful assertion is over built output and a browser, which is what I did by hand above rather than adding a browser dependency to the suite.

Independent of #16 and #19 — no overlapping files.

🤖 Generated with Claude Code

https://claude.ai/code/session_011texLkDBELWbXsBf6San3M


Generated by Claude Code

A root-only build: no Vite `base`, no router `basename`, and an API base
hardcoded to /api. Served from anything other than the domain root the
bundle requests /assets/... instead of <prefix>/assets/..., so the page
renders blank — the reason the CI preview artifact needed a history-rewrite
shim to show anything.

Thread one variable through instead. VITE_BASE_PATH sets Vite's `base`,
which becomes import.meta.env.BASE_URL, which the router's basename and the
default API base both read; the dev proxy keys off the same value. Unset it
and everything resolves to '/' exactly as before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011texLkDBELWbXsBf6San3M
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants