Jake Lawrence

I make software work inside real organizations.

Ten years in and around local government: two village halls, then court and payments systems deployed into 100+ Illinois municipalities, from legacy data conversion to go-live. This site is where I build in public.

Hear The Theses on Radio

AI voice and music by ElevenLabs. Photographic scenes are AI-generated. Stamped page shots are recorded from jakelawrence.xyz.

The homepage cover: records crossing a review gate, with Jake Lawrence's name in the corner.

AI voice and music by ElevenLabs. Photographic scenes are AI-generated. Stamped page shots are recorded from jakelawrence.xyz.

Three things I built

All work
A drawing of the review gate: flagged cases wait for a reviewer, and only the cleared cases go on to the agency.

Client work
CourtCollect
A review console for a Texas municipal court sending cases to a collections agency: a reviewer clears each flagged case and the agency gets only the cleared ones. Legacy court data mapping, magic-link sign-in, and a PII boundary the tests enforce.

How I decide

The constraint
The reviewer is a clerk with a browser, not an engineer. Real client data can never sit in git, and the application tier can never hold the identifiers that make a court export sensitive.
What I chose
Redact at the boundary and build the console for the reviewer: a pass that blanks SSN, date of birth, license number, address, ZIP, phone, and email while keeping names; an auth-gated review console behind a court-branded magic-link login; a plain-language guided wizard with a finish flow; document serving with an in-app reader and PDF download; an onboarding email that carries the end-to-end instructions; and an admin runbook.
Cited pull requests
#570, #571, #573, #574, #579, #581, #1918
Case study: 7 cited pull requests

Eight cases with receipts

All eight cases

In the order I would show a hiring manager for:

Old records in, a gate in the middle, a running system out. Two wait for a person.
Proof one, on your device

Run it yourself

The full profiler

The frequency list in the first proof exists so a learner can tell whether a Ukrainian text is within reach. This is the profiler built on it. Pick a reader's level and every word above it gets marked.

Я живу в невеликій квартирі. У квартирі є кухня, спальня і вітальня. У вітальні стоїть диван, а біля дивана є маленький стіл. На стіні висить картина від друзів. У спальні стоять ліжко і шафа. Балкона немає, але в кабінеті є полиця для книжок. У будні я встаю о сьомій. Іду у ванну кімнату, потім снідаю з родиною. На роботу їду автобусом. Увечері вечеряю на кухні і читаю книжку перед сном.

Excerpt from Мій дім, мій день (A2), learn-ukrainian (Krisztian Koos and contributors), the open A1 to C2 Ukrainian course. CC BY-SA 4.0. One of the profiler's validation texts.

Reader's levelFrozen run, lexicon v1.2.0, 2026-10-01

The share of running words a reader at each level already knows. The dashed line marks 95 percent, the usual target for reading with support (Laufer 1989; Hu and Nation 2000).

Run downloads the lexicon once, about 600 KB. The measuring happens on your device.

At A1, 70 running words
  • known60
  • above the level8висить, Балкона, кабінеті, полиця, будні, родиною, перед, сном
  • not matched to a lemma2снідаю, вечеряю

Unmatched means the profiler could not reach a lemma. The list carries the nouns сніданок and вечеря, both A1, and lacks the verbs снідати and вечеряти, so снідаю and вечеряю stay unmatched at every level.

Nothing you paste leaves your browser: the lexicon is downloaded once and the analysis runs on your device. No text is stored, logged, or sent anywhere. An analytics ping records that Run was pressed. It never carries the text.

Now

Taking the Ukrainian Frequency study from dataset to product: a hosted lemmatizer, a Python package, and a free course built on the same data. Also reading about how public records systems decide what counts.

Selected writing

All writing