Blog

Moving a production stack from Azure to Google Cloud

Two years of production on Azure, then a platform built on Google Cloud from its first commit. The vendor-specific layer takes weeks to learn and the instincts underneath it took years. Capability is a tie. What differs is who each cloud assumes you are, and what each service puts a meter on.

Permissions borrowed from Amazon and Google

A permission model that is almost right is wrong, so this one is borrowed from the giants. Action grammar from Amazon, resource hierarchy from Google, declared once in the spec and generated to both the backend and the console.

Tokens as a currency

Tokens as a currency

Every tracked event gained a trace id and a token count, which answers why a request was slow and what it cost from one row. The larger consequence is that tokens can become the unit everything else is measured in, including the costs billed in gigabytes and instance hours. If software keeps getting easier to build, the durable position is the one closest to the infrastructure, and a currency pegged to infrastructure cost is what that looks like on an invoice.

Rolling out Google Identity Platform

Authentication was the first thing the platform needed and the first thing I decided not to write. What rolling out Google Identity Platform actually involved: a configuration screen, their client SDK, one verification middleware, and the translation from their id to mine. Plus the two things a provider will never do for you, and why roles do not belong in the token.

No test, no endpoint

An API endpoint with no test beside it does not exist, as far as the platform is concerned. The generator that builds the route tables looks for a sibling test file and skips any route without one, so the API never registers it and nothing downstream is generated for it. Plus, seven months on, what happened to the surface that never got the same gate.

Generating code from the API spec

Most of the code in this codebase was not written. It was produced. The generation apparatus, ten small programs reading a self-describing API, and why what you write by hand should shrink to what carries judgment.

I rolled my own Next

The console's router is a system I own outright, and there was never a bake-off. Next got the best idea in front-end routing right, that a folder tree can be the route table, and I took that part. What I left was a rendering server at the centre of a system whose centre is an OpenAPI schema, because that schema has to keep driving an SDK, an MCP server and a desktop shell as well as a browser.

Form validation generated from the server schema

Every form in the console validates against a schema no one wrote on the client. A route declares its shape once, and the operation id on that route becomes the zod schema, the client method, the hook and the cache key, so the four cannot disagree. Drift is the default condition of web forms, and it is gone here for structural reasons rather than disciplined ones.

Everything the page editor also builds

The tree under the page editor is not a page. A page is one way of rendering it. Which means headers, footers, sidebars, templates, dialogs, forms and email are all the same tree in a different table, edited in the same canvas with a different palette. Three kinds of tree, one editor, and a block whose only job is to mark where the body goes.

Building the page editor first

Giant Context is being built as an AI that makes websites, and none of that comes first. What comes first is a page editor a person uses with no model in the room. A page is a typed tree of sections, columns and blocks, addressed by id and never by position, and the editing canvas renders it with the same components the public site uses, so there is nowhere for the two to disagree. Including why it is typed blocks and not an HTML editor, which is a bet rather than a settled question.