A close-up portrait of a man with a salt-and-pepper beard wearing a white collared shirt against a textured beige background.
A close-up portrait of a man with a salt-and-pepper beard wearing a white collared shirt against a textured beige background.

No test, no endpoint

Jesse James Richard
|
Jan 27, 2026
|
5 min read
#Testing
#Architecture

An API endpoint with no test beside it does not exist, as far as the rest of the platform is concerned. No frontend can be built against it. Nothing downstream of it will materialize. In Giant Context, a test is what an endpoint needs before anything is allowed to consume it, and that condition sits inside the build rather than in a document about how we work.

Nobody writes the client

When the console calls an endpoint, it does not call it with code I wrote. A route declares its contract, the running API publishes that declaration as a spec, and a set of generators reads the spec and produces everything the call needs: the typed method, the data hook, the cache key, the form validation, the mocks and factories its tests run on. Around twenty families of files exist purely as outputs of that description.

So the way to reach an endpoint is produced rather than written, and anything that gates production gates existence. A route that does not make it into the generated tables has no client method, no hook, no validation, and no way for a frontend to call it. It is in the source tree and nowhere else.

One condition in one generator

The generator that builds the route tables walks the route directories. For each route file it looks for a sibling test beside it, in a __tests__ folder, named after the route. If that file is not there, the route is skipped.

That is the entire gate. One condition, in one generator, and everything else follows from it. The route does not go into the tables, so the API never registers it, so the spec never mentions it, so no client method, hook, cache key or validation is produced for it.

The result is absence rather than a warning. You can write the handler, save the file, and watch the console fail to find a client method for it, because as far as every generated artifact is concerned the endpoint was never declared. The generators run in watch mode during development, so this happens seconds after saving, not in a CI run twenty minutes later.

Write the test and the chain runs. The route enters the tables, the API registers it, the spec includes it, the client materializes, and the suite at the far end, much of it generated, checks that the whole assembly still holds.

All of that is sequencing. Classic TDD asks you to hold a discipline: test first, every time, forever. Put the test inside the dependency graph and the discipline stops being required, because the consumers of an endpoint are produced only after its test exists. The test comes first by construction. Nothing downstream can exist otherwise.

What one test buys

The strict typing does most of the daily assurance. When the schema, the client, the validation and the cache keys all come from one description, entire categories of integration bug cannot form, and the suite's job narrows to the one question types cannot answer: whether the endpoint does the right thing.

So the toll at the gate is small. One honest test per endpoint, and the machinery amplifies it, because the generated mocks and factories mean the tests exercising that endpoint's surfaces cost almost nothing to add. The suite is already a few hundred files and I wrote only the core of them.

Working alone, that sequencing does a job I cannot otherwise fill. There is no second engineer to catch a mistake before it reaches a customer, and care is not a substitute for one. A build step applies the same condition on a Friday afternoon as on a Monday morning, and applies it to a one-line change as readily as a large one. That is why a platform this size can deploy several times a day with nobody watching but me.

I am a testing evangelist, and this would work for someone who is not. Put the tests inside the dependency graph, where something downstream cannot exist until they pass, and running them stops being a choice anyone makes.

Client routes

Added August 2026.

The console's pages are generated from a folder tree, by a generator built on the same idea as the one above. It turned out never to have had the test condition.

The effect showed up in the coverage. Where the gate existed, almost every route had a test. Where it did not, coverage tracked nothing but whether I had felt like writing tests that week. Some apps were complete. Others had none at all, including the core package that holds most of the console. Same codebase, same person, same habits, and the only variable was whether the build enforced anything.

The client generator now refuses a route with no test beside it, exactly as the server one does. Switching it on outright would have deleted most of the console from the router, so the routes that predate the gate are listed by name and exempted, anything new is refused, and entries can leave the list but never join it. The exemptions are filenames rather than a tolerance, because a tolerance only ever rises.

The rule is the same on both surfaces. A test file has to sit beside the thing it tests before that thing will build, and it has to pass before anything commits. On the server that decides whether an endpoint exists. On the client it decides whether a page does.

Generating code from the API spec

#Architecture
#APIs & MCP

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 wh...

Jesse James Richard

|

Jan 24, 2026
Read previous

Building something like this

I'm Jesse. I build platforms end to end, and I'm open to work. If this is the kind of engineering you need, get in touch.

Contact Jesse
Home
About
Contact
Sitemap
Privacy Policy
Terms of Service
Cookie Policy
No test, no endpoint | Jesse James Richard