Context
We added build-time prerendering using a Playwright postbuild script (scripts/prerender.ts) to solve the CSR-only SEO problem (bots see empty <div id="root"></div>). This works but is a workaround, not a native solution.
Current approach
- Playwright (already a dev dep for e2e tests) visits each static route after
vite build
- Captures fully-rendered HTML and saves it to
dist/<route>/index.html
- nginx's
try_files serves pre-rendered HTML when available, falls back to SPA
Why migrate
- Playwright adds ~400MB to the Docker builder stage (Chromium install)
- Build times increase by 30-60s for the prerender step
- The script is custom code we maintain vs. a framework feature
- React Router 7 has built-in prerendering in Framework Mode
Options to evaluate
- React Router Framework Mode - migrate from
createBrowserRouter (Declarative Mode) to Framework Mode with react-router.config.ts. Gets native prerender: true support. Biggest migration but most "correct" path.
- Astro - the nimblebrain marketing site already uses Astro. Could migrate mpak-web to Astro with React islands for interactive parts.
- Keep Playwright - if the above are too costly, the current approach works fine.
Acceptance criteria
- Pre-rendered HTML for all static routes (/, /security, /about, /contact, etc.)
- Browse pages (/bundles, /skills) include initial API data in HTML
- No custom prerender script needed
- Chromium not required in Docker build