Detach and verify your standalone site
Detachment stops CMS-managed updates. It is not deleting the CMS or its data. Keep the original installation until the owner accepts the standalone result. The detachment contract defines what is exported, and the standalone backend API reference is the only generated-backend API reference.
Preconditions
Section titled “Preconditions”Use a reviewed source snapshot and identify the intended site, repository, published snapshot and destination database. Read the GitHub authentication matrix. Managed delivery of a locally generated commit uses a configured App, npm run backend:deliver uses device flow, and the admin cannot generate source (source_build_runtime_unavailable). npm run backend:generate does not need GitHub credentials and does not deploy.
Before any deployment, address the known standalone boundaries. Every deployment, managed or repository-only, writes ACCESS_CONFIG as the union of the CMS-issued read-token digests committed in access/read-tokens.json and vars.ACCESS_CONFIG in your wrangler.jsonc. When there are none, it writes a valid empty list ({ version: 1, siteId, tokens: [] }). Routes that require a read token refuse until one is delivered, and the deploy refuses a value the Worker could not boot with. A revoked CMS token stays accepted until you regenerate and deploy. Detaching does not remove the committed digests: see Stop the CMS connection. The emitted README can describe an older one-model/read-only contract. Edge compatibility is not a blanket guarantee for added Prisma extensions or generated routes. Follow the current API reference, not the stale emitted README, and retain a verified backup.
Generate and review
Section titled “Generate and review”For the integrated CLI, the source repository’s invocation shape is:
npm run backend:deliver -- --site <site-id> --repo <owner/name> --source <cms.db> --dest <output-directory> --db <target.db>This is an operator-authorized write/deploy operation, not a verification-only command. Supply its required environment and confirm repository ownership before running. Review generated, owned and shared files, model coverage, translations, relations and the published snapshot. Preserve src/owned/ and shared dependency configuration. Media transfer is a separate explicitly selected operation requiring source and destination access. A site that references private files also needs a private source group and a private destination bucket of its own (the EXIT_MEDIA_SOURCE_PRIVATE_ and EXIT_MEDIA_DESTINATION_PRIVATE_ names in exit --help); without them the run is refused before anything is copied, and a private file is never written to the public bucket. Bind that bucket to the Worker as PRIVATE_FILES. To serve with npm run serve:local instead, set EXIT_MEDIA_DESTINATION_PRIVATE_DIRECTORY (an existing absolute directory, used instead of the bucket) and start the server with PRIVATE_FILES_DIRECTORY pointing at it; the server answers 503 private_files_unavailable while that is unset. Generation alone does not move media into your custody.
Verify the exact generated commit
Section titled “Verify the exact generated commit”From the generated repository, use its verified dependency installer and existing checks. After an authorized deployment, keep API_BEARER_TOKEN in the environment and run:
node scripts/install-dependencies.mjsnpm run typechecknpm run buildnpm run verify:medianpm run verify:deployment -- --origin 'https://site.example.com' --expect-commit <full-commit-sha>verify:media checks committed snapshot/page projections for CMS-owned media references. It is not a remote byte-availability test. verify:deployment uses the bearer token and compares the deployed content with the committed snapshot across routed tables, including the expected commit. It must pass for the repository revision you intend to own, not merely return a healthy status.
For an emitted apps/site, also use node scripts/install-dependencies.mjs apps/site, npm run --prefix apps/site check and npm run --prefix apps/site build. Open representative deployed pages in each required locale and verify media availability separately. A passed backend check does not verify the website visually.
Site Worker compatibility flag
Section titled “Site Worker compatibility flag”Blog routes, search pages, and pages with a Latest entries section, a Site search section or visitor comments read published content from /v1 on the site’s own host at request time. Cloudflare sends that same-host request to the Dee Wan public Worker only when the site Worker enables global_fetch_strictly_public. New projects get it in apps/site/wrangler.jsonc. That file is yours: Dee Wan writes it only when it is absent and never rewrites it. Latest entries in a shared section shown in a region are pinned at generation and read nothing at request time. They read public models only: a private model shows collection_model_missing. Their summaries frame the embed origins accepted at generation. Changing a model’s visibility or an embed origin needs a new generation.
When the generated site performs these reads (recorded in the generated apps/site/public-reads.json), generation and deployment check your existing apps/site/wrangler.jsonc. If compatibility_flags is missing the flag, or is not a list of strings, both refuse with public_fetch_compatibility_flag_required, name the file and the flag, and change nothing. Add "global_fetch_strictly_public" to compatibility_flags yourself and run again. Generation in the CMS and the deployment both read this file as JSONC, so comments and trailing commas are accepted. A file that is not valid JSONC refuses the same way. A site with no Blog, site search turned off and no page served at request time has no such requirement.
Stop the CMS connection
Section titled “Stop the CMS connection”Only after acceptance, remove the CMS build webhook and stop requesting CMS-managed deployments. Review or disable the repository workflow that fetches CMS definitions so it cannot regenerate unexpectedly. Set the generated site’s previewApiOrigin to null when no longer using CMS draft preview. The standalone API and statically built pages should continue with the CMS unavailable. The routes in What still depends on Dee Wan do not. Without the Dee Wan public Worker, Blog routes and search pages answer 503 and a Latest entries section shows its error. Without the intake Worker, comments and forms cannot be sent.
CMS-issued read tokens survive detachment. Their digests stay in the committed access/read-tokens.json, and every repository-only deployment still adds them to ACCESS_CONFIG. Revoking a token in the CMS no longer reaches this repository. Review the file after detaching. To stop accepting a token, delete its entry, or the whole file, then commit and deploy. Without the file, deployment uses only vars.ACCESS_CONFIG, or the empty list. The file is in the generated zone, so while you are still connected, revoke in the CMS and regenerate instead.
npm run backend:deliver offers the detachment plan after verification. It does not perform this final disconnection automatically. Do not delete source data, buckets or credentials as part of this runbook. For rollback, retain the previous accepted commit and matching database/media state. An old code commit alone does not reconstruct later data changes.
Authorities: scripts/exit-start.ts, backend/src/lib/graduate/regenerate-template.ts, backend/src/lib/graduate/deployment-files.ts and backend/src/lib/graduate/media-custody.ts. Real deployment and visual acceptance remain the operator’s responsibility.
Before you retire the CMS
Section titled “Before you retire the CMS”Detaching keeps the Dee Wan installation running. Retiring it is a separate step. Check each item first:
- Generated API.
npm run verify:deploymentpasses for the commit you will keep. The API reads only its own D1 database. - Static pages. They are built from the committed
pages.jsonand read nothing at request time. - Blog, site search, Latest entries and comments. When the site has any of them,
apps/site/public-reads.jsonholds"requestTimePublicReads": true. They read/v1from the Dee Wan public Worker on every request and stop working when it is gone. - Forms and comment submissions. They post to
/v1/interactions/*on your host, which the Dee Wan intake Worker answers. The Dee Wan admin Worker delivers form submissions. - Preview.
previewApiOriginisnull, or you accept that/previewstops. - Managed renderer. If you deployed
managed-renderer/, it reads/v1on every request. - Public and intake Workers. Know which routes on your host point at Dee Wan Workers:
/v1/*and/v1/interactions/*. - Media custody.
npm run verify:mediapasses, so no committed projection still points at Dee Wan media. Without a--mediatransfer, Dee Wan still serves the media. - Plugins. The generated backend has no plugin host. Plugin rich blocks on request-time routes read their definitions from
/v1/_rich-blocks. - Read tokens. You reviewed
access/read-tokens.json, as above. - Definitions. To regenerate later, pull and keep a
definitions.jsonwhile the CMS still runs. See Regenerate locally.
Artifact authentication during delivery
Section titled “Artifact authentication during delivery”Before delivery, review backend-wide Better Auth methods and exact access policies. A missing model policy is service. Supply selected provider inputs through target secret storage or local ARTIFACT_* environment variables. Delivery creates a fresh BETTER_AUTH_SECRET for the artifact and seals repository values with the ARTIFACT_ prefix. Existing target secrets are preserved. Unselected providers require no credentials. The reviewed target hostname determines OAuth and magic-link callbacks. Never copy CMS credentials or accounts.
Keep the artifact auth tables and their migration history with its database backup. They have no generated CRUD API. Disabling auth requires a new destination. Regenerate for dependency or method-binding changes. Public reads are verified anonymously. Session-only reads require a real target session supplied as ARTIFACT_VERIFY_SESSION_COOKIE. A missing session produces verify_session_required, not successful verification. On first deployment, initialize the target, sign up through its auth routes and rerun verification with that session. Do not save session values in source, reports or ledgers. Provider callbacks, email and live deployment acceptance require the adopter’s own authorized environment.
Next step
Section titled “Next step”Plan how to restore the database and media with standalone recovery.
Unreleased / pre-MVP; no stable version
Source revision: fe23db481c422b40e317b92fc98116b4c0c26a87 (modified checkout)
Build date (UTC): 2026-10-18T09:22:34.630Z
Upgrade target: unavailable: modified checkout. Release notes