Open source / MIT
Your React app,
visible to search engines.
Search engines crawl HTML. SPAs serve an empty shell. prestruct fixes that -- rendering each route to static HTML at build time with correct title, description, Open Graph, schema.org, and cache headers. No framework migration. No edge runtime. Just a smarter build step.
Build pipeline
vite build
Hashed JS + CSS bundles to dist/
inject-brand.js
Global SEO meta into index.html
prerender.js
Each route rendered to static HTML
CF Pages deploy
Globally cached, correct HTTP status
The SPA SEO problem
What you gain
↑ rank
Crawlable content
Every route serves its full HTML to bots. No JavaScript execution required. Googlebot, Bingbot, and social crawlers see exactly what a user sees.
↑ CTR
Rich search previews
Per-route title and description baked into HTML. Your search result shows the right snippet for each page, not a generic site-wide fallback.
↑ share
Social cards that work
og:title, og:description, og:url, og:image correct on every route. When someone shares your /pricing page, the card shows pricing content, not your homepage.
↑ trust
Schema.org structured data
JSON-LD injected from your config into every page head. Organization, WebSite, Product, Article -- whatever your app needs to earn rich results.
↑ speed
Correct cache headers
Hashed JS/CSS assets cached immutably. HTML revalidates on every request. Users always get fresh content, browsers never re-download unchanged bundles.
0 cost
No infrastructure change
Still deploying to Cloudflare Pages as static files. No server, no edge worker, no new dependencies at runtime. Build time goes up by ~2 seconds.
This page, right now
<!-- injected by inject-brand.js from ssr.config.js -->
<title>prestruct | SEO prerendering for Vite + React on Cloudflare Pages</title>
<meta name="description" content="Make your Vite + React app visible to search engines..." />
<link rel="canonical" href="https://prestruct.creadev.org/" />
<meta property="og:url" content="https://prestruct.creadev.org/" />
<script type="application/ld+json">{ "@type": "SoftwareApplication", ... }</script>
<!-- then the full rendered HTML of this route, no JS needed -->
<div id="root" data-server-rendered="true">...full HTML...</div>