Two last pieces of setup, both in the web app's config: an address of your own, and a Preview for each pull request, so you can look at a change before it ships. The Preview is where it's easy to get wrong, because by default it would talk to your real agent.
Verified wrangler 4.157.0
Start from f-06 on GitHub. Starting here, or behind? Get the code at that tag:
git clone https://github.com/ryanyogan/klippy cd klippy git checkout f-06
1. Your own domain
A custom domain is one route in the web app's config:
It's commented out because the hostname must be on a zone in your Cloudflare account. Uncomment it with yours and Cloudflare creates the DNS record and the certificate. Three things change with it:
APP_ORIGINbecomeshttps://<your hostname>.Your GitHub OAuth app gets
https://<your hostname>/auth/github/callback.workers.devturns off for the web app on the next deploy, unless you set"workers_dev": true. Then your domain is the only address.
Your CI token also needs Workers Routes edit on that zone. This is optional: the checkpoint works with the workers.dev address too.
2. Previews see pages, never data
wrangler preview uploads a branch as a separate Preview with its own URL. Cloudflare's docs say Previews don't inherit production settings: a Preview gets only what's in the previews block. And one line matters most: a service binding from a Preview calls the bound Worker's production deployment. Give the Preview AGENT, and a pull request's code would talk to your real Klippy. So it gets no agent and no database:
No AGENT and no DB. A Preview is for reviewing pages: sign-in, layout, styles.
Nobody signs in:
ALLOWED_GITHUB_IDSis empty. (GitHub sign-in can't work on apr-<n>URL anyway: an OAuth app's callback host is fixed.)Its own rate-limit namespaces (3002, 3003), so Previews never share production's counts.
Its own secrets, set once with
wrangler preview base-config secret put <NAME>, each a new value, never production's. (Wrangler 4.157.0 listssecretsunderpreviewsin its schema but warns that it's an unexpected field there, so base-config secrets are the way.)
Without the binding, the web app answers plainly instead of crashing:
Preview URLs are public unless you put Cloudflare Access in front. That's fine here, because there's nothing behind them.
3. A Preview for each pull request
The workflow gets a third job, with the same secret gate:
Pull requests from forks never get your secrets, so their Preview job always skips. Copy ci.yml, apps/web/wrangler.jsonc and agent.ts. Ours: 111 agent tests passed, and the web app's dry run had no warnings.
For a full staging copy, with chat and data, you'd deploy a second pair of Workers with Wrangler environments, each with its own D1, Vectorize index and OAuth app. That's more than Klippy needs.
What we didn't run: wrangler preview and the custom domain. Both create live deployments, and Wrangler 4.157.0 has no dry run for wrangler preview.
Your code matches tag f-07 (changes from f-06).