Wizard Redirect (Cloudflare Pages)
Problem
The remediate app (apps/remediate) uses Next.js with output: 'export' (static export) and deploys to Cloudflare Pages. The Fix Wizard lives at /audit/[id]/wizard/, where [id] is a dynamic UUID per audit job.
Static export requires generateStaticParams() to enumerate every possible route at build time. Since audit IDs are created dynamically by users, we canβt know them ahead of time. The build generates a single placeholder page at /audit/_/wizard/index.html β any real audit ID (e.g., /audit/227091f9-.../wizard/) has no matching file and returns a 404.
Solution
A _redirects file in public/ tells Cloudflare Pages to rewrite dynamic wizard paths to the placeholder page:
/audit/*/wizard/ /audit/_/wizard/index.html 200/audit/*/wizard /audit/_/wizard/index.html 200- The
*is a Cloudflare Pages splat that matches any single path segment (the audit UUID). - The
200status code makes this a rewrite (serves the target content at the original URL), not a redirect (which would change the URL in the browser). - Two rules cover both trailing-slash and non-trailing-slash requests.
Once the placeholder HTML loads, WizardClient.tsx calls useParams() from Next.js to read the real audit ID from the browser URL. All data fetching uses this client-side ID, so the page works correctly regardless of which static file was served.
Key Files
| File | Purpose |
|---|---|
apps/remediate/public/_redirects | Cloudflare Pages rewrite rules |
apps/remediate/src/app/audit/[id]/wizard/page.tsx | Static page with generateStaticParams() returning placeholder _ |
apps/remediate/src/app/audit/[id]/wizard/WizardClient.tsx | Client component that reads useParams() and fetches wizard data |
apps/remediate/next.config.mjs | output: 'export' and trailingSlash: true |
apps/remediate/wrangler.toml | Cloudflare Pages project config (pages_build_output_dir: "out") |
Limits
Cloudflare Pages allows 100 dynamic redirects (rules with splats) and 2,000 static redirects per _redirects file, across all plans. We currently use 2 dynamic rules.
Adding More Dynamic Routes
If new dynamic routes are added to the remediate app (e.g., /audit/[id]/report/):
- Create the page under
src/app/audit/[id]/report/page.tsxwith a placeholdergenerateStaticParams(). - Add corresponding rewrite rules to
public/_redirects:/audit/*/report/ /audit/_/report/index.html 200/audit/*/report /audit/_/report/index.html 200 - Rebuild and redeploy.
Deployment
The _redirects file is copied into out/ during next build. Cloudflare Pages reads it automatically on deploy. To apply changes:
cd apps/remediatenpm run deploy