feat: prerender public site pages

This commit is contained in:
2026-05-04 16:29:50 -04:00
parent 55d8acef4c
commit 4fba72e99c
14 changed files with 380 additions and 5 deletions

132
docs/SEO.md Normal file
View File

@@ -0,0 +1,132 @@
# SEO And Public Page Prerendering
Socialize is primarily a client-side app, but the public marketing pages are prerendered during the frontend build so crawlers can index static HTML.
## Public Indexed Routes
These routes are treated as public site pages:
- `/`
- `/product`
- `/pricing`
- `/blogs`
- `/guides`
Authenticated app routes under `/app/*` and auth utility routes such as `/login`, `/register`, `/forgot-password`, `/reset-password`, and `/verify-email` are excluded from indexing in `robots.txt`.
## Build Flow
The frontend build runs:
```bash
vite build
vite build --ssr src/entry-public-ssr.js --outDir dist-ssr
node scripts/prerender-public.mjs
node scripts/write-public-seo.mjs
```
This is wired into:
```bash
cd frontend
npm run build
```
The prerender step writes static HTML files such as:
```txt
frontend/dist/index.html
frontend/dist/product/index.html
frontend/dist/pricing/index.html
frontend/dist/blogs/index.html
frontend/dist/guides/index.html
```
The SEO generator writes:
```txt
frontend/dist/robots.txt
frontend/dist/sitemap.xml
```
## Production Domain
Set the public site URL when building for production:
```bash
cd frontend
VITE_PUBLIC_SITE_URL=https://your-domain.com npm run build
```
This value is used for:
- canonical URLs
- sitemap URLs
- the sitemap reference in `robots.txt`
If `VITE_PUBLIC_SITE_URL` is not set, the build falls back to `SITE_URL`, then `http://localhost:5173`.
## Files To Update
When adding, removing, or renaming public indexed pages, update all of these:
- `frontend/src/router/router.js`
- `frontend/src/entry-public-ssr.js`
- `frontend/scripts/prerender-public.mjs`
- `frontend/scripts/write-public-seo.mjs`
- page metadata in the public page component via `usePublicPageMeta`
Public page metadata helper:
```txt
frontend/src/features/landing/publicPageMeta.js
```
## Server Routing
Caddy is configured to serve prerendered directory indexes before falling back to the SPA:
```txt
try_files {path} {path}/index.html /index.html
```
Config file:
```txt
deploy/caddy/Caddyfile
```
This matters because `/product` should serve `dist/product/index.html`, not the SPA fallback `dist/index.html`.
## Validation
After changes:
```bash
cd frontend
VITE_PUBLIC_SITE_URL=https://your-domain.com npm run build
```
Check generated HTML:
```bash
grep -n "<title>" dist/product/index.html
grep -n "canonical" dist/product/index.html
grep -n "Social media content approval" dist/product/index.html
```
Check crawler files:
```bash
cat dist/robots.txt
cat dist/sitemap.xml
```
## Search Engine Setup
After deployment:
1. Confirm public routes return `200`.
2. Confirm `/robots.txt` and `/sitemap.xml` are served.
3. Submit the sitemap in Google Search Console.
4. Keep auth and app routes out of the sitemap unless they become public content.