Skip to content

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 200 status 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

FilePurpose
apps/remediate/public/_redirectsCloudflare Pages rewrite rules
apps/remediate/src/app/audit/[id]/wizard/page.tsxStatic page with generateStaticParams() returning placeholder _
apps/remediate/src/app/audit/[id]/wizard/WizardClient.tsxClient component that reads useParams() and fetches wizard data
apps/remediate/next.config.mjsoutput: 'export' and trailingSlash: true
apps/remediate/wrangler.tomlCloudflare 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/):

  1. Create the page under src/app/audit/[id]/report/page.tsx with a placeholder generateStaticParams().
  2. Add corresponding rewrite rules to public/_redirects:
    /audit/*/report/ /audit/_/report/index.html 200
    /audit/*/report /audit/_/report/index.html 200
  3. Rebuild and redeploy.

Deployment

The _redirects file is copied into out/ during next build. Cloudflare Pages reads it automatically on deploy. To apply changes:

Terminal window
cd apps/remediate
npm run deploy