what the scribe is
an ai writing assistant for ministry authors. it interviews you, works out how you actually talk, then drafts your book in that voice. at the end it reads the chapter back to you out loud in a clone of your own voice, because your ear catches things your eye will not.
the interview is eight questions and you can just talk your way through it instead of typing. those answers get turned into a structured profile of your voice: the phrases you repeat, the scriptures you keep going back to, the stories you tell, the convictions sitting under all of it. after that, nothing calls a model without that profile in the request.
the problem
ministry authors have a problem that has nothing to do with writing. they can preach for forty minutes without notes, no script, no teleprompter, completely at home. then you sit them in front of a blank page and it dies.
so they hire a ghostwriter, and the book comes back correct, theologically sound, and not theirs. everybody can feel it and nobody can point at the sentence where it went wrong.
generic ai makes this worse rather than better, which surprised me less the longer i worked on it. ask any model for a chapter on grace and you get something competent and weightless that could have been written by anyone, about anything, at any point in the last ten years.
because a preacher’s voice was never the grammar. it’s the phrases they repeat without noticing they’re repeating them, the four scriptures they circle back to no matter where the sermon started, the story about their father they’ve told nine times and will tell again on sunday. that’s the whole thing, and it’s the first thing a general-purpose model throws away, because to a model that’s just redundancy.
the shape of it, and the one rule it won’t break
three subsystems, and honestly the interesting part isn’t any of them on their own, it’s the rule binding them together.
capture. an interview state machine that survives you closing your laptop halfway through an answer. every response persists, so you come back to the exact question you left. you can speak instead of type, in which case the recording goes out for transcription and comes back as text you edit before it counts for anything, because i didn’t want a bad transcript quietly becoming somebody’s voice.
extraction. a background pipeline that turns those raw answers into structured fields instead of a blob of text. it upserts in place, keyed on the author, so redoing your interview overwrites your voice rather than quietly forking it into two profiles that the rest of the system then has to pick between, badly.
grounding. the rule, and it’s the only one that really matters: no ai call happens without the voice profile inside it.
so scripture suggestions come from your anchors, not from the model’s general sense of what a verse about grace might be. phrase recall surfaces your lines. it can’t reach for a verse you’ve never preached in your life. that constraint is basically the product, and everything else is plumbing i built around it.
the scar: the refresh token i threw away
for a few weeks, sessions just died at thirty minutes. hard logout, mid-sentence, no warning.
the backend had been issuing a refresh token since day one. the frontend took the access token, stored it, and dropped the refresh token on the floor like it was packaging. so the moment the access token expired there was nothing left to refresh with, and the only way back in was the login screen.
the fix is boring, it’s the fix everybody already knows: keep both tokens, catch the 401, refresh once, replay the original request, single-flight it so ten calls firing at once don’t stampede the endpoint. what actually bothers me is that it shipped like that and i didn’t notice for weeks, because the auth worked perfectly in every session short enough to demo. i’d been testing it exclusively in the one condition where it couldn’t fail.
decisions i’d defend
a plain textarea, not a rich editor. every instinct i had said wysiwyg. but the whole stack leans on plain text: generation streams into it, version history snapshots it, refine slices it, read-back speaks it. migrating the core writing surface days before a deadline is how you lose the deadline, so i left it alone, and honestly the ruled paper and the serif did more for how it feels than a toolbar ever would have.
one vendor for transcription, not two. gemini was already in the stack, so before writing any ui i made a sample in each container a browser would actually hand me, webm and mp4 and ogg, and pushed all of them through to see what came back. clean every time, biblical vocabulary intact. ten minutes of checking, and it killed a whole class of bug i’d otherwise have found the hard way, in front of people.
a reactive waveform on the mic, an animated one on playback. tapping the microphone analyser is free, it never touches the output. capturing an audio element into web audio can mute the thing entirely if the context starts suspended, and read-back is the whole payoff, so that isn’t a risk worth taking for a nicer animation. real where it’s safe, faked where it isn’t. nobody can tell.
voice input, because someone told me the interview felt long. they were right, though not for the reason they gave. these are oratory people, and i’d built them an interview about how they speak and then made them type it. that contradiction sat in the product for weeks and i walked past it every single day.
what it taught me
the model is the easy part. it always is, and i keep re-learning that from a slightly different angle every time.
it wrote usable prose on day one. the rest of the time went into the interview that survives a closed laptop, the extraction that doesn’t fork, the version history that means nothing the ai wrote can eat what you wrote, the refresh that replays your request instead of dumping you at a login screen. none of that is fun to talk about and none of it compresses into a screenshot. it’s also the entire difference between a demo and something a person can actually use.
the other half of it: personalisation isn’t a feature you bolt on at the end. either it’s the spine every single request hangs off, or it’s decoration.