Context
Style guides only work if people can apply them
Every team I've worked with has a content style guide, and every team has interface text that breaks it. The rules aren't the problem. Applying them consistently, string by string, under deadline, is.
AI rewriting tools look like the answer, but most of them rewrite by the model's taste rather than the team's rules, they don't explain what they changed, and they'll confidently invent details that aren't in the original. In an error message, an invented fix is worse than no fix: it ships false information to users.
So I set three requirements: apply my rules and only my rules, explain every change by citing the rule behind it, and flag missing information instead of making it up.
A payment error alert rewritten against the style guide, with the changes and the rules behind them.
Rules as the product
Turning a style guide into rules a model can follow
The most important work wasn't code. It was rewriting my style guide as 19 numbered rules, each with an ID, the components it applies to, and a do/don't example. I kept the rules in their own folder, separate from the app, because the rules are the product; the interface is replaceable.
{
"id": "ERR-03",
"rule": "If the user isn't allowed to solve the issue, start with the
word Couldn't followed by the incomplete action. This
overrides ERR-01.",
"appliesTo": ["error"],
"do": "Title: Couldn't access that page / Description: Please
contact your system administrator for permissions.",
"dont": "Invalid input! You can't get in."
}
Writing rules for a model exposed gaps a human writer would also stumble on:
- One lesson per example. "Save Changes" → "Save" fixes capitalization and length, so the model learns both. Each example now shows exactly one change.
- Say which rule wins. When two rules conflict, the one that takes priority says so ("This overrides ERR-01"). Without that, the model picks one at random.
- Titles and descriptions follow different punctuation rules. No period on titles, buttons, and badges; full sentences in descriptions; no period on status text like "Optional".
- Rules target real component parts. I used shadcn/ui's names (AlertTitle, FieldError, EmptyDescription) so the vocabulary matches the components the tool is built with.
When the model kept getting a rule wrong, the rule was usually ambiguous to people too. "Keep buttons short" didn't say whether "Run query" or "Run" was right. Clarifying it fixed the model and the style guide.
Designing the output
An answer a writer can trust at a glance
The first working version returned raw JSON. Designing what writers actually see meant deciding what each part of the answer is for:
- Rule badges on every rewrite, listing only the rules that caused a change. Listing every rule that could apply made explanations noisy.
- Flags instead of guesses. When text doesn't say what failed, the rewrite uses a placeholder like
Couldn't [failed action]and a flag says what's missing. - A suggested component when the style guide calls for one, such as turning an error toast into an alert.
- Three honest states: "Follows the style guide" when nothing needs to change, "No rewrite yet" when it can't fix the text without more information, and rewrite cards otherwise. Early on, the page showed "Follows the style guide" next to flags saying it didn't. Separating those states fixed the contradiction.
- Whole components. A field's label, help text, and error text are reviewed together, the way they appear in the interface, and the form's fields change with the component you choose.
Before: the first working version, showing raw JSON.
An error toast: the tool suggests an alert and offers two structures, depending on whether the user can fix the problem.
Accessibility decisions came from using it, not just from the numbers. The before-and-after view marks changes with strikethrough and underline, not color alone, and adds hidden "removed" and "added" text for screen readers. The amber warning text passed WCAG AA at 6.95:1 but was hard to read on its tinted background, so I switched alert text to the standard dark text at 17.9:1. I also raised secondary grey text from 4.74:1 to 7.46:1. A contrast ratio is a minimum, not a guarantee of comfortable reading.
Testing it like a product
30 test cases, three runs each
Before writing any code, I wrote a test set: 30 real interface strings with my ideal rewrite, the rules each rewrite should cite, and the flags it should raise. It includes text that's already correct, because rewriting good text is a common failure of AI writing tools.
A test runner sends every case to the app three times, because the same input can produce different answers. A case only counts as passing if it passes every run. It checks the rules cited, that correct text is left alone, that flags are raised, and that the right component is suggested. A report puts my ideal rewrite next to Claude's for the judgment calls a script can't make.
| Run | What changed |
|---|---|
| 22 of 30 | The first full run. |
| 28 of 30 | Updated tests written before later decisions, and clarified ambiguous guidance in the prompt. |
| 29 of 30 | Made the schema require a rule for every rewrite, and clarified two rules. The last case passed after clarifying what counts as blaming the user. |
Most failures weren't the model being wrong. They fell into four kinds:
- Outdated tests. Six cases expected behavior I'd changed my mind about later. The test set records decisions, so it has to change with them.
- Examples outweighing instructions. Twice, an example in the prompt changed the model's behavior more than the instructions around it. One outdated example ("such as how short a button label should be") kept the model offering "Save changes" after I'd ruled it out.
- Genuinely ambiguous rules. When the model flipped between answers across runs, the rule usually didn't say what I meant. Clarifying it helped writers as much as the model.
- Guarantees that need code, not prompts. A prompt made "a rewrite with no rule behind it" unlikely, but it still happened. Requiring at least one rule in the output schema made it impossible.
The first full run: 22 of 30 cases passing every time.
Sometimes the test was wrong. I expected "URL" to become "web address", and the model kept "URL" in every run. I agreed with it, and changed the test, not the rule.
Shipping it
Live, public, and protected
The tool runs on Vercel and calls Claude through the Anthropic API. Because every request costs money, putting it on a public portfolio needed the same care as the content:
- An access code on the live site, a monthly spend limit on the API account, and a separate API key for the live site that can be replaced without touching development.
- Prompt caching. The rules and prompt are identical on every request, so they're cached, which cut the cost per request from about 2.6¢ to about 1¢. A full 90-request test run costs under a dollar.
- A public repository with the rules, prompt, test set, test reports, and a decision log of every choice and why.
The README covers how it works and how to run it, and the decision log has the full reasoning behind everything on this page.
Working with AI
I made the calls; AI helped me build them
I built this with Claude Code as a collaborator. Claude wrote most of the code, and I reviewed and revised it. I ran the build myself, from the first terminal command to deploying it. I wrote the style guide rules and made the calls on what the tool should and shouldn't do. I wrote the first draft of the prompt and the first test cases. Claude drafted the rest, and I reviewed and rewrote them, deciding what every ideal answer should be. Claude Code also explained each step and pushed back when something I'd written was ambiguous.
The tool itself works the same way. The model doesn't decide what good microcopy is; the team's rules do. The model's job is to apply them consistently, explain itself, and say when it doesn't know enough.
Outcomes
A working tool, and a better style guide
The assistant is live, tested against 30 cases, and documented in public. Building it also made the style guide itself clearer: almost every rule I clarified for the model was a rule a human writer could have misread.
Outcomes
Rules a model can follow
Turned a prose style guide into 19 testable rules with IDs, scopes, and examples, and clarified the ones that were ambiguous to people too.
Evaluation, not vibes
Measured the tool against 30 cases, three runs each, and took it from 22 to 29 passing by fixing tests, prompts, rules, and code.
Trust built into the design
Every change cites a rule, missing information is flagged instead of invented, and changes are shown without relying on color.