Capsa builds to a static site, so it runs on Cloudflare Pages and the global edge for free. Two ways: the dashboard (Git integration) or the Wrangler CLI.
package.json "packageManager" field, so
Cloudflare uses the right pnpm version automatically.| Setting | Value |
|---|---|
| Framework preset | None |
| Root directory | / (repo root) |
| Build command | pnpm install && pnpm build |
| Build output directory | dist |
| Variable | Example |
|---|---|
NODE_VERSION | 20 |
VITE_SITE_NAME | Acme Docs |
VITE_SITE_URL | https://docs.acme.com |
Tip
Set VITE_SITE_URL to your final domain so sitemap.xml and llms.txt get
absolute URLs.
Capsa is a single-page app, so deep links like /docs/guides/intro must serve
index.html and let the client router take over. This repo ships
public/_redirects:
Real files (/assets/*, /openapi/*, /llms.txt) still take precedence — only
unmatched paths fall through to the app. Without this file, direct loads and
refreshes of doc URLs return 404 on Pages.
Note
This is the Cloudflare Pages approach. If you deploy as a Worker instead
(wrangler deploy), drop _redirects and set
"assets": { "not_found_handling": "single-page-application" } in wrangler.jsonc
— Workers Assets rejects the /* redirect rule as a loop.
Vite inlines VITE_* variables at build time, so set them as Pages build
variables before the build — changing one requires a redeploy.
Warning
VITE_* values are compiled into the public bundle. Never put a secret
(API key, token) in one. The included WorkOS auth uses a public client id, which
is fine; anything truly secret belongs in a server/Function, not a VITE_ var.
Production and Preview environments can hold different values — e.g. point
preview deploys at a staging VITE_SITE_URL.
Set variables in the dashboard, or per deploy with --var:
In your Pages project: Custom domains → Set up a domain, point DNS at Cloudflare, and you're live on HTTPS in a minute or two.
| Symptom | Fix |
|---|---|
| Doc URLs 404 on refresh / direct load | Ensure public/_redirects exists (see above). |
Build fails: pnpm: not found | Keep the "packageManager" field in root package.json; Cloudflare reads it. |
| Build fails on an old Node | Set the NODE_VERSION build variable (e.g. 20). |
| Blank page, console errors about a base path | Don't set a Vite base unless serving from a subpath. |
| Config change didn't apply | VITE_* vars are build-time — redeploy after changing them. |
A Dockerfile (nginx, with SPA fallback built in) is included if you'd rather
run it yourself: