Client ·Jul 2026 → ongoing ·gated
NMLS Document Repository
A law school's archive of fifteen thousand judgments, statutes and past papers, rebuilt by AI coding agents under a written governance model. It was in production twenty-three days after the first commit, with the whole archive published five days later. The old site keeps the record until the school signs a cutover, and a weekly sync keeps the two level.
- Timeframe
- Jul 2026 → ongoing
- Tags
- Enterprise · django · migration · governance
- Credits
- Xern Mottley — Engineer
- The kind of build
- Venture Build one like it →
Where it started
Norman Manley Law School's document repository holds about fifteen thousand judgments, statutes and past examination papers, the reference collection a law student works from. It ran on Drupal 7, a platform whose support ended years ago, with a taxonomy people navigate by habit and no safe way to move any of it.
The brief did not arrive as a tender. The person who ran the old system, and had meant to replace it for years, had watched the work on another project and asked. The brief they handed over became the authority for every decision that followed, cited by section.
Two conditions shaped the build. The new site had to be fully deployed by 17 August, ten days before term, on hosting that cost under forty dollars a month. And the old site would stay open, keeping the record until the school signs a cutover.
What was done
A replacement, and a way to prove at every step that it was safe to switch to.
The shape is a set of decisions, each recorded with its reasons. Records live in PostgreSQL and nothing else owns them. The search index is a projection of those records, fed through an outbox and rebuildable from scratch, so a search failure cannot corrupt a record and the index can be thrown away and remade.
The data path, drawn as the decisions that shaped it. PostgreSQL alone holds authority; the search index is a rebuildable projection, so a search failure cannot corrupt a record. Publication is a capability of its own. The legacy system stays the source of record until a signed cutover.
A document enters private storage, is quarantined and scanned, and only then promoted to an immutable copy. Its text is extracted, with optical character recognition only where a file has none, and a scan with no readable text is marked as having none. Publication is its own capability, distinct from editing, and gates everything the reader and the search can show.
Every source term, spelling and variant was carried across without silent merging; canonical names come only through a reviewed editorial process. That is why a 1970 judgment arrives with its court, its parties and its pagination intact, beside the scan it came from.
A 1970 Court of Appeal judgment, a public record, with its court, parties and pagination intact beside the original scan. The panel states that the text came from optical character recognition and may misread words, and says to check quotations against the original before citing.
Every document passes the same gate before anyone can read it. The administration surface counts what is available, what has a processing issue and what is not published, and shows the one record that is not.
The whole stack also runs on one machine with no cloud account, so a reviewer can run the thing they are reviewing.
Moving the archive was treated as six rules rather than one task: discover read-only, extract with provenance, transform deterministically, load idempotently, reconcile counts and hashes, and move authority only on a signed cutover.
The first trial, two hundred rows from the old site's public export, wrote fifty and published none: three rows in four lacked a field the new site required. The source moved to the old site's own weekly database dump, which also records when each document last changed. On 17 August the whole archive loaded, 15,156 documents and 15,147 files with no load failures, and two days later all but one were published.
Six rules, one at a time. The first trial of the public export hit two walls at the load step on its first day, and the old site's own weekly dump replaced the export as the source. Authority moves only on a signed approval.
It runs in containers on one cloud host, live behind a sign-in since 14 August. Each week a job restores the old site's dump, loads what changed and publishes what the old site published; on 12 October both held the same 15,167 documents.
The decision that mattered
The hard part was being reviewed, and what that turned into.
This was the first time working under someone more senior, and they had corrections: small, specific ones, from the shape of the reader's toolbar to what the search box did on the third character of a case name, returned until they were right. The habit that came out of it is the part of this project most worth copying: stop reading the code to decide whether it works, and measure the running system.
The build's first six weeks, from its milestone log. The marks in red found something broken, and each carried its root cause the same day. The first production deployment found three defects that reading the code had missed.
Every PDF failed to open on the live site from the day the viewer shipped, and no test caught it, because the reader fell back to the extracted text without a word. Opening a judgment on production found it on 25 August. The cause was one line of the security policy, which never allowed the viewer's own file links, and it was fixed that day.
Search was measured against the old site on the live archive. A named case returned 439 results where the old site returns 2, and the empty search screen's sort order carried silently into a reader's first query. Both were fixed, and the named case now returns 8.
The search surface mid-query, measured against the old site with both live. Under relevance the ranking agreed with the old site's; the fault was a default sort that carried silently into a reader's first search.
A guess that the two sites had drifted was settled by counting both: on 11 October the old site held 15,167 documents and the new one 15,156. The weekly job meant to keep them level had never been switched on and could not have run. It was fixed and run that night, and now publishes on its own.
The reviewing taught money too. Hosting was first priced at $88.87 a month, against a ceiling of forty. A cost study priced each step down to a floor of $23.85, every rate pulled from the pricing API and every memory figure read from the running containers, and beside its largest saving it notes that this could not be verified and must not be presented as settled. The host was sized from it, inside the ceiling.
The cost study's six rungs, from the first price of $88.87 a month to a floor of $23.85, ordered by dollars saved per hour of work. The first three need four hours and no code change. The note at the foot is the study capping its own largest number.
The product carries the same habit. The reader warns that its text came from OCR and may misread words, an undated judgment reads year not recorded, and the publish surface shows the one record that is not published.
Where it stands
Live behind a sign-in since 14 August, with the whole archive loaded and all but one of its 15,167 documents published.
The publish gate on 9 September: 15,156 records available, none with a processing issue, and the single record that is not published shown rather than left out. Every document is managed from source file to publication.
In September the school's Librarian reviewed it and asked for seven things, from exports and backups to examination papers sorted by course. All seven were built and accepted on the live site on 11 October, and a full backup package was built and verified.
No student has been invited yet. Inviting 1,824 waits on two decisions, where the list of who may join comes from and how many join at a time, and the site has no domain of its own to send mail from, so for now an invitation is a link given to the person directly. The old site keeps the record until a cutover is signed, the arrangement the whole build was designed around.
It was built with AI coding agents, under the governance described above, and that is what the governance is for: the brief as the only authority, every decision recorded with its reasons, and the work checked on the running system. A plan scoped in months reached production in just over three weeks.
Timelines are shortening and expectations rising. The standard can rise with them when it is written down and enforced, and the written record leaves with the work, so an institution that has to answer for its archive can show how it was moved.
Everything shown on this page is public. The documents are published court judgments and legislation, the public records of a public institution, and nothing here identifies a student, an account or a host.
- 15,167
- Documents loaded, all but one published, kept level with the old site each week
- 23 days
- From the first commit to production
- 7 of 7
- The school's review asks, built and accepted on the live site
- 26
- Decisions recorded with their reasons; a changed decision gets a new record
Next — Vanrox Group →