Skip to main content
Playground (apps/playground) runs on TanStack Start, Vite+ and Void through the start bridge. It is a staff-only surface; the behaviour it must keep is recorded in the isolation contract. The emitted Worker builds and passes its workerd suite, so source needs no change to publish. Routes are never attached from config.

Worker identity

cloudflare/startup.mjs refuses to serve when a secret is empty or when the coordination secret is the development value.

Build

playground-cloudflare.yaml runs the same steps and seals the output with scripts/ci/playground-native-artifact.py in its cutover-artifact job. Run the build on a CI or remote runner, not a developer machine.

Acceptance covered by test:runtime

  • the emitted Worker verifies a staff session before it renders any private page
  • AI routes answer 401 signed out and 403 for non-staff or non-root members
  • every response carries X-Robots-Tag; robots.txt disallows all crawling
  • no execution, iframe or sandbox surface exists in the app
The root layout loads Geist through next/font/google; the RSC plugin resolver handles it and the build succeeds. Compare rendered fonts on the staging host before the switch, since that is a visual check the suite does not cover.

Rollback

Capture the current Vercel deployment ID before the switch. Remove or repoint the prepared Worker route, or restore the captured DNS, to that deployment. Route rollback does not touch data.

Smoke checks

Pages are staff-only, so an anonymous 200 is not expected on /.
  • signed-out GET / redirects to the Web sign-in page with a return URL
  • /api/build-info answers 200 JSON
  • /api/ai/object-generation answers 401 signed out
  • /robots.txt disallows all crawling
  • no 5xx across the above