Back to blog
·5 min read·Cell Webb

Why KittyLog Has a Worker Behind Its Pages Domain

A look at the OpenNext migration, the Pages compatibility proxy, and the deployment checks that keep the front door stable.

The frontend used to have one obvious answer to the question, “Where does the site run?” The recent deployment work made the answer more useful: the application runtime and the public front door are separate pieces.

The OpenNext migration merged at 01:58:37 UTC on August 1, 2026. A Pages proxy compatibility fix followed at 02:04:46 UTC. The existing Pages project stayed in place as a small service-binding proxy. It keeps the established pages.dev links and customer custom-domain certificates and DNS targets while the Worker runs the application.

That arrangement sounds more complicated than “deploy the site.” It is also a more honest description: a runtime migration has to preserve the addresses people already use while changing what serves the request behind those addresses.

Keep the front door stable

The Pages project no longer contains the Next.js application bundle. Its job is to receive the request, retain the original hostname, and forward the request through a service binding to the OpenNext Worker. The Worker has the application assets and runtime.

The hostname is not just decoration for a public changelog. Custom domains can be part of the link a customer has already given to users. The proxy signs the original hostname before calling the Worker, and the backend can use that signed context when it handles a public changelog request. The shared secret does not cross the service binding.

This is the kind of migration detail that disappears from a diagram with one box labeled “Cloudflare.” It is also the detail that makes a cutover safe. The new runtime can change while the addresses people recognize stay attached to the compatibility layer.

The build had a budget

The migration also forced a less glamorous decision about the Worker bundle. The OpenNext pull request recorded a compressed Worker size of 1,934.14 KiB. Cloudflare documents a 3 MB compressed limit on the Workers Free plan. Because Wrangler reports KiB, the repository converts the units explicitly and now enforces a 1,905 KiB CI budget, leaving at least 1,024 KiB of real headroom.

That budget is checked by a script that runs Wrangler's dry-run deploy, reads the gzip size, and fails when the reserved headroom is gone. A build that works on a laptop is not enough if the artifact cannot fit the platform it is meant to run on.

A later bundle audit recovered roughly 420 KiB more by dropping an observability SDK from builds that configure no reporting destination, a trade that deserves its own write-up.

The migration replaced dynamic Open Graph image routes with a checked-in 1200×630 PNG as part of keeping the Worker smaller. That is a real compromise. Dynamic images are convenient, but a fixed asset was the right choice for this rollout's size and runtime constraints. It is better to name the trade-off than to leave a future deploy to discover it.

The proxy had to understand the Worker

The first migration pull request passed local and preview checks, but the compatibility proxy still had a separate concern. A follow-up change enabled nodejs_compat in the Pages Wrangler configuration so Pages validation could resolve the bound Worker's Node.js module imports.

The follow-up's own notes are worth reading: a production validation attempt had failed, and production remained on the previous canonical Pages deployment. That sentence is more informative than a claim that the migration was simply “done.” It records both the change and the part that had not moved yet.

Deployment status needs that kind of precision. A preview URL proves that a preview can serve a request. A green build proves that an artifact was produced. Production still needs its own request through the public domain.

Two pieces mean two checks

The current setup has two deployment surfaces. The Workers Builds connection tracked by #1359 was verified on August 2, 2026. The application Worker is connected to the KittyLog repository with main as its production branch and frontend as its build root. A change on a configured watch path now builds and deploys that Worker automatically. Pull request CI already runs the full Worker build and runtime smoke gates, so non-production branch builds are disabled.

The manual commands remain useful as a break-glass path:

cd frontend
pnpm run build:cloudflare
pnpm run check:worker-size
pnpm exec wrangler deploy

The Pages compatibility proxy follows a separate path. When the proxy changes, pnpm run deploy:pages-proxy deploys just that surface. A production check should cover both paths, along with a request through a custom hostname and a request to the API rewrite.

That is more work than the old single-bundle mental model, but it is the work the architecture has chosen. The useful response is to make the boundaries explicit in configuration, scripts, and runbooks, then test the handoff instead of hoping the service binding behaves like an ordinary internal function.

The migration is a reminder that infrastructure prose should be as careful as product prose. “The site runs on a Worker” is incomplete if an existing Pages project still owns the public address. “The deploy passed” is incomplete until the resulting Worker version is active and the public routes answer. The less exciting version tells the truth people need when they are debugging a real request.

Source records

  • PR #1352, the KittyLog repository record for the OpenNext migration.
  • PR #1358, the KittyLog repository record for Pages proxy compatibility.
  • PR #1362, the deployment runbook correction for the temporary manual Worker state.
  • PR #1371 and PR #1383, the Worker size budget changes behind the current 1,905 KiB CI ceiling and 1,024 KiB headroom.
  • Issue #1359 and PR #1483, the records for connecting and verifying Workers Builds.
  • frontend/scripts/worker-size-budget.mjs and frontend/scripts/check-worker-size.mjs, the enforced budget.
  • OpenNext on Cloudflare
  • Cloudflare Workers service bindings
  • Cloudflare Pages custom domains
  • Cloudflare Workers limits

Ready to automate your changelogs?

Try KittyLog free - no credit card required.

Get Started Free