Deploy the project site

Build the allowlisted marketing site, docs, and observe-only console into site/dist/, then publish only that directory. This Pages project is not the v2 admission Worker.

Deploy

# From the private repository root
npm ci
npm run check
git status --short
git push origin main

COMMIT="$(git rev-parse HEAD)"
npm run site:deploy -- --origin https://x429.dev --confirm "$COMMIT"

site:deploy is the only production upload path. It requires a clean, governed commit already present at origin/main, rebuilds the allowlisted site, runs the release and vendor audits, uploads only site/dist/, and verifies the exact Pages deployment plus the custom-domain proof. Never call raw wrangler pages deploy, use drag-and-drop, or deploy the site/ source directory.

Verify

# From the private repository root
npm run site:verify -- https://x429.dev

The verifier uses non-following HEAD requests, validates the root security-header contract, and refuses a redirect that merely hides an exposed source file. Retain its JSON output with the deployment evidence.

Expected status codes:

URLExpected
/200
/docs/200
/llms.txt200 text with explicit pre-release boundaries
/wrangler.jsonc, /README.md, /SECURITY.md404; retain these negative checks with deployment evidence
The marketing Pages deployment intentionally exposes neither a fake /429 offer nor public /.well-known/x429.json discovery. V2 discovery belongs on the separately deployed admission Worker, not the marketing hostname.

Custom domain

Cloudflare Pages should have both custom domains attached:

x429.dev
www.x429.dev

DNS should be configured using the records or nameservers shown in the Cloudflare dashboard for this Pages project. Keep registrar-specific or account-specific values out of the public repository.

Production headers

The site includes a Pages _headers file. Keep public responses conservative: clear content types, restrictive security headers, and cache rules appropriate to each asset.

RouteHeader goal
/llms.txtReturn concise text instructions for agent builders and crawlers.
/docs/*Return normal static HTML; cache immutable assets such as fonts and images where safe.
/api/*Return no-store authenticated telemetry responses; never grant admission or payment authority.

Observe-console data boundary

  • Ingest accepts at most 100 schema-validated events and 256 KiB per request. Query strings, arbitrary fields, raw address fields, secret fields, and legacy truncated client hashes are dropped.
  • Accepted KV batches have a fixed 30-day expiry. The default schema still stores a bounded route path, truncated user-agent, status, latency, and protocol flags, so use route templates and complete legal/privacy and retention review before beta.
  • Per-client bucketing is disabled by default. An approved deployment must change the non-secret Pages variable X429_OBSERVE_CLIENT_HASHES from disabled to the exact value enabled. The observed server must separately set collectClient: true, an exact clientHashDomain, and a dedicated X429_OBSERVE_CLIENT_HMAC_SECRET generated from at least 32 random bytes. Without both opt-ins, identifiers are dropped and hidden.
  • The dedicated HMAC secret belongs in the observed application's secret manager—not Pages, Wrangler variables, browser code, or the project credential. The middleware creates a full project/origin/UTC-day-scoped HMAC before sending telemetry. Missing or syntactically weak configuration emits no identifier; raw addresses and the secret never enter the telemetry payload.
These technical controls are not legal or privacy approval. The owner must approve fields, notice/lawful basis, retention, deletion handling, and jurisdiction-specific obligations before collecting beta traffic.

Repo workflow

  1. Edit the public site files in site/.
  2. Run npm run check from the repo root; the guarded deploy rebuilds site/dist/.
  3. Commit changes.
  4. Push to GitHub.
  5. Run npm run site:deploy -- --origin https://x429.dev --confirm "$(git rev-parse HEAD)"; never bypass the gate or deploy the source directory.

Read next