Skip to content

website: prerender to static HTML for no-JS crawlers/agents - #31

Merged
okcodes merged 2 commits into
mainfrom
website-prerender-static-html
Sep 6, 2026
Merged

okcodes merged 2 commits into
mainfrom
website-prerender-static-html

Conversation

@okcodes

@okcodes okcodes commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Adds a build-time prerender step so dist/index.html's #root contains real markup instead of shipping empty for client React to fill in — fixes crawlers/AI agents that don't execute JS getting no content.
  • Chose this over migrating to Next.js: the site deploys to GitHub Pages (static hosting only, actions/deploy-pages), so Next's actual SSR/ISR advantages need a Node/edge runtime that isn't available here — it would run in output: 'export' mode anyway, i.e. the same static HTML Vite already produces, for a single-page site with no router.
  • website/src/entry-server.tsx (renderToString(<App/>)) is built with a separate vite.ssr.config.ts (only the react() plugin — virtualConsoleVitePlugin assumes an HTML build target and breaks otherwise), then website/scripts/prerender.mjs inlines the output into dist/index.html and deletes the intermediate dist-ssr/.
  • website/src/main.tsx now hydrates when #root already has content (build/preview) and falls back to a normal client render when empty (vite dev, unprerendered).
  • No changes needed to release-website.yml — pnpm run build still ends with static files in website/dist.
  • Full reasoning recorded in DECISIONS.md.

Test plan

  • pnpm run build in website/ succeeds; dist-ssr/ is created then removed.
  • curl of the built dist/ output (via a plain static file server, no JS execution) shows real page copy ("Drop it in", "Try it live", hero text) inside #root.
  • pnpm run typecheck and pnpm run lint (oxlint) pass with no new warnings.
  • Loaded the built site in a browser — no console errors, no hydration mismatch warnings.
  • Reviewer: run pnpm run dev locally and confirm normal client-render still works (unprerendered #root in dev is expected/by design).

🤖 Generated with Claude Code

okcodes and others added 2 commits September 6, 2026 06:42
Renders the app to a string at build time via a separate SSR entry and
inlines it into dist/index.html's #root, instead of shipping an empty
div for client-side React to fill in. Lets crawlers and AI agents that
don't execute JS see the actual page content. Chose this over migrating
to Next.js since the site deploys to GitHub Pages (static hosting only),
where Next's SSR/ISR advantages aren't available anyway. See
DECISIONS.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@okcodes
okcodes merged commit ace0d7a into main Sep 6, 2026
2 checks passed
@okcodes
okcodes deleted the website-prerender-static-html branch September 6, 2026 12:51

This branch was previously deployed

1 inactive deployment
github-pages — 242ea519 Deployed Sep 6, 2026 by okcodes via deploy-website #3
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.

1 participant