www/SSG_README.md
This website uses Static Site Generation (SSG) to pre-render all routes at build time. This solves the SEO issue where Google's searchbot was seeing 404 status codes from the SPA hack and refusing to index pages.
src/entry-server.tsxsrc/entry-server.tsx - SSR entry point that exports render() and getAllRoutes()scripts/prerender.tsx - Script that orchestrates the pre-rendering processscripts/postprocess-sitemap.tsx - Adds trailing slashes and creates URL alternates using SAX parserscripts/validate-sitemap.tsx - Validates sitemap structure and consistency with HTML files using SAX parserscripts/vite-plugin-prerender.ts - (Optional, not currently used) Vite plugin approachsrc/views/ExamplesIndexView.tsx - Landing page for examples with category gridsrc/views/ExamplesIndexView.css - Styling for examples index pagesrc/app.tsx - Changed from createRoot().render() to hydrateRoot() for proper hydrationpackage.json - Added prerender, postprocess-sitemap, and validate-sitemap scripts; updated build to run allvite.config.ts - Removed defaultLanguage from sitemap config to generate explicit locale URLssrc/routes/index.tsx - Removed redirects, added examples index page routenpm run build
This runs:
npm run build:client - Builds the client application to /docs and generates sitemap.xmlnpm run prerender - Pre-renders all routes to HTML files with trailing slashes in URLsnpm run postprocess-sitemap - Updates sitemap to include both trailing-slash and non-trailing-slash URL formatsnpm run validate-sitemap - Validates sitemap structure and file consistencyThe sitemap follows a specific structure to support both trailing-slash and non-trailing-slash URLs:
<loc> tags have trailing slashes: /guide/, /api/, /examples/docs/guide/index.html, docs/api/index.html/ remains as-isEach canonical URL has multiple alternates:
x-default alternate (without trailing slash): /guide, /api, /examples
Locale alternates (with trailing slash): /en-US/guide/, /zh-CN/api/
<url>
<loc>https://recharts.github.io/guide/</loc>
<lastmod>2025-10-27T14:04:30.193Z</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
<xhtml:link rel="alternate" hreflang="x-default" href="https://recharts.github.io/guide"/>
<xhtml:link rel="alternate" hreflang="zh-CN" href="https://recharts.github.io/zh-CN/guide/"/>
<xhtml:link rel="alternate" hreflang="en-US" href="https://recharts.github.io/en-US/guide/"/>
</url>
The scripts/postprocess-sitemap.tsx script:
The scripts/validate-sitemap.tsx script validates:
URL Structure
/)zh-CN, en-US)File Consistency
Implementation
src/locale/index.tsThe solution pre-renders:
/)/en-US, /zh-CN)/examples, /en-US/examples, /zh-CN/examples)Total: 378 HTML files across 2 locales (en-US, zh-CN) plus default unprefixed routes
The sitemap contains 503 total URLs (126 canonical + 125 x-default alternates + 252 locale alternates)
✅ SEO-Friendly: Each route has proper HTML with content, no 404 status ✅ URL Flexibility: Supports both trailing-slash and non-trailing-slash formats ✅ Fast First Paint: Users see content immediately without waiting for JS ✅ GitHub Pages Compatible: Works perfectly with static hosting ✅ No Server Required: Still a static site, no Node.js server needed ✅ Progressive Enhancement: Works even if JavaScript fails to load ✅ Automated Validation: Ensures sitemap and HTML files stay in sync ✅ Proper XML Parsing: Uses SAX parser for robust, maintainable code ✅ Locale Support: Proper hreflang alternates for internationalization
renderToString for SSRStaticRouter from react-router for server-side routinghydrateRoot for client-side hydrationnoExternal: true)During development, the site works as a normal SPA (no pre-rendering). Pre-rendering only happens during production builds.
npm start # Development mode - no pre-rendering
npm run build # Production build - with pre-rendering and validation
sax - SAX parser for XML processing in postprocess and validation scripts@types/sax - TypeScript types for SAX parser404.html is now a proper, clean 404 page (not a redirect hack)xhtml:link tags for alternates with hreflang attributes/en-US/404) are skipped during validation