Docket
PrivateRebuilding the same engine for a business — a demo they'd recognise, and a test of the architecture
Role
- Solo, during a FORGE internship — schema layering, verification, work-domain tooling
Timeline
- 2026
Built with
- TypeScript, Postgres + pgvector, Supabase, Deno, MCP
Links
- Private repository

The problem
Carrel is a student's term: twelve weeks, six syllabi, a problem set that is eight days late. Nobody running a landscaping company sees themselves in that, and a demo a prospect cannot see themselves in is not a demo. The pitch needed the same system speaking a language a business already uses — late commitments, people who owe you an answer, margin against plan.
Building it also settled something I could not otherwise check. I had designed Carrel's schema in layers — a universal baseline with at most one domain layer on top, dependencies pointing downward only, so a domain layer is droppable. That is an easy thing to assert and an easy thing to be wrong about, because nothing inside a single install ever exercises it. The only honest test was to build the second install and find out what broke.
What I built
The same baseline and the same MCP server, carrying company records and plan-versus-actual financials in place of courses and assignments. It opens on what is late and who owes you an answer rather than on a list of everything.
The structural break was that there is no term. A student year has a shape — twelve weeks, a start, an end — and half of Carrel's surfaces are built on that shape. A business does not have one. So the week-and-term framing could not be carried across, and the work version had to be organised around commitments and how old they are instead.
What that leaves: Today, split into what you owe and what you are owed; Projects as threads rather than tasks, each carrying the people, documents and next action that belong to it; a Pulse page putting every metric that has a plan against its actual, sorted by how far off it is; and the same Library and Schedule underneath.
Every screenshot here is fabricated demo data for an invented landscaping company, built so the product can be shown without showing anyone's real business.


What it changed
Each figure below was read out of the repository, not estimated.
- 87 / 7 / 0
- structural assertions passing, correctly skipped, and failingschema verification across 18 migrations, 2026-08-19
- 2
- interchangeable domain layers on one shared baselinework and student layers, same core schema
Decisions worth explaining
01
An architecture claim you cannot test is a preference
I had designed the schema in layers — a universal baseline plus at most one domain layer on top, with dependencies pointing downward only, so a domain layer is droppable. That is easy to assert and easy to be wrong about, because nothing inside a single install ever exercises it. Building a second install carrying the other layer is what turned it into a fact: same baseline, same MCP server, different domain, and no change required below the layer boundary.
02
One table filed in the wrong layer took the whole install down
The layering rule is easy to state and easy to violate by accident, and `materials` — the document corpus — was violating it. It had been classified as student, because the first documents to go in were course readings. A document corpus is not academic, it is universal, and the misfiling broke two things at once. The migration declared its course reference inline and unguarded, so on a work install, where no courses table exists, the file errored and the push stopped dead — taking the chunk table, the lexical search pass, the recording patch and the storage bucket down with it. Then the verification, which derives which layers are present from which expected tables it finds, saw one student-classified table and concluded the student layer was supposed to be there: every student assertion flipped from a correct skip to a false failure. Moving one table down a layer fixed both. The lesson I actually took is that a layering rule with nothing enforcing it is a comment, and the thing that caught this was the checker disagreeing with itself.
03
The verification skips rather than fails, and that distinction is the feature
A schema check that fails on an absent table cannot serve two different installs — you end up maintaining two checkers, which drift. This one is layer-aware: a missing student table on a work install reports a skip, not a failure, so a green run means the same thing in both trees. Seven of the assertions skip here, and they are exactly the student layer being correctly absent.
What’s next
Deploying it for a real business against their own credentials, which is a different problem from building it and mostly an operations one.
The launch page
Docket has its own launch page, written and built alongside the product and deployed at docket.ajstefely.com. It is set on paper rather than in the dark, because the app is, and the screenshots on it are the app rather than illustrations of it.

Built with
- TypeScript·
- Postgres + pgvector·
- Supabase·
- Deno·
- MCP