Prompts to Try
Voice Rules: The Prompt That Keeps AI Copy On-Brand
Result:
docs/VOICE.md shipped with 14 vocabulary rules + 18 style rules, now gating every recipe and page written for this site — including this one.
Shortcut
Paste this once the template below is filled in.
Requires manual input
Your own filled-in copy of the blank voice-rules template; no account or credential needed beyond that.
I have a voice/vocabulary doc for [site or brand]. Turn it into an
enforcement check I can use going forward. Ask me whether I want it as:
(a) a Claude Skill: a self-contained SKILL.md at
~/.claude/skills/voice-rules/SKILL.md (personal, every project) or
.claude/skills/voice-rules/SKILL.md (this repo only), that loads
itself whenever I'm drafting or editing copy;
(b) wired into this repo's shared agent instructions
(AGENTS.md/CLAUDE.md/GEMINI.md) so every agent working here applies it
without being asked; or
(c) an MCP server exposing the doc as a resource, the enforcement prompt
as a callable prompt, and a deterministic lint tool for the vocabulary
table.
Whichever I pick, apply this logic: treat every CRITICAL rule as a hard
constraint and rewrite instead of shipping a violation; treat every
PREFERRED rule as a default, breakable with a stated reason; check every
draft against the Vocabulary table and all four Style sections before
returning it; and say so explicitly if a rule and the content genuinely
conflict, instead of silently picking one.
Here's my doc:
[paste your filled-in voice-rules-template.md here]Problem#
A publication drafts copy across many separate sessions, and if it’s AI-assisted, many separate context windows. Without a written rule set, “brand voice” lives only in the author’s head — every new draft re-derives it from vibes, drifts a little further each time, and there’s no way to check whether a paragraph is on- or off-voice except a gut read. The fix used in production systems that publish at real volume isn’t a style guide nobody rereads — it’s a small, structured rule set a model is required to check a draft against every time it writes, edits, or rewrites something.
Pattern#
Two pieces: a source-of-truth voice doc, and a prompt that enforces it.
-
Split the doc into two layers. Vocabulary — approved term ↔ forbidden synonyms, scoped by audience, ranked by severity. Style — off-brand behaviors (never), avoid-lists with the exact trigger words (default to break), cadence patterns to watch (not banned, just monitored), and tone principles. Word-level rules and sentence-shape rules get violated differently; conflating them into one flat list makes the doc unreadable and unenforceable.
-
Rank severity, don’t just list rules. Two tiers: CRITICAL (never break) and PREFERRED (holds by default, breakable with a stated reason). A flat “don’t use these words” list degrades into being ignored the first time a real sentence needs an exception; a severity split tells the drafting model which violations to refuse outright versus flag and explain.
-
Ground every rule in real copy, not taste. Mine the site’s own published pages for what’s already working — recurring phrases, sentence shapes, register splits — instead of inventing rules from scratch. A voice doc that contradicts the copy already live is worse than no doc at all. This site’s own
/vibe-checkpage (a field guide to AI-slop design tells) turned out to already contain a full specimen of AI-slop copy too — “Unlock Your Next-Level Growth Journey,” “seamlessly delivers real results,” “Game changer!” — which became the forbidden-word list directly, instead of a guessed one. -
Write the enforcement prompt. The doc is inert until a model is told to load and apply it on every call:
You are drafting or editing copy for [site]. Before writing anything, read [path to VOICE.md] in full. - Treat every CRITICAL rule as a hard constraint — if a draft would violate one, don't write that version; find the compliant phrasing instead. - Treat every PREFERRED rule as a default — hold it unless there's a specific reason to break it, and say what the reason is if you do. - Check the draft against the Vocabulary table (approved vs. forbidden terms, scoped by audience) and the four Style sections (off-brand, avoid, patterns, tone principles) before returning it. - If a rule and the immediate content genuinely conflict, say so explicitly rather than silently picking one. -
Wire it into the repo, not just the session. This site is built by more than one agent across sessions (
AGENTS.md’s handoff protocol), so the pointer to the voice doc has to live where every agent already looks first — added to the “read before you write” list at the top ofAGENTS.md/CLAUDE.md, next to the existing pointers toSPEC.mdandBUILDLOG.md. -
Render it, don’t just describe it. A markdown doc is easy to skim past. Pull the same rules into a small typed data file (
src/data/voiceRules.ts— the same interfaces as the table below) and a plain component that renders them as an inspectable table, not another markdown wall. Two constraints kept it from turning into its own mini design project: no new colors (severity reuses the site’s existing mono.telem/.telem-accentreadout labels instead of a colored pill) and no client framework (the tabs below are two radio inputs and a CSS sibling selector — no<script>).docs/VOICE.mdstays the source of truth; this table is generated from data that mirrors it, not the other way around, so update both together.
| Approved | Forbidden | Severity | Notes |
|---|---|---|---|
| recipe | post, article, blog entry | critical | The unit of content — the collection is literally named "recipes" (src/content/recipes/). |
| pattern | framework, strategy, playbook (generic) | critical | The reusable technique behind a recipe. Exception: fine as a proper noun naming an actual shipped system ("an AEO framework"). |
| result | outcome, impact, takeaway | critical | Frontmatter field + section header (## Output) — always paired with the actual number. |
| Exit Velocities | EV, "Exit Velocity" (as the site name) | critical | Proper noun. Always both words, always capitalized, never abbreviated. |
| exit velocity | — | preferred | Lowercase, singular — reserved for the dictionary-style device. Not a stand-in for the site name. |
| channel | pillar (in reader-facing copy) | preferred | "Pillar" is the internal/schema word. Readers see "channel" (CH.01–CH.03). |
| pillar | channel (in code/docs) | preferred | Mirror of the row above — the internal term stays internal. |
| shipped in production | launched, released, live (as the credibility claim), actually shipped | preferred | The recurring credibility anchor: ties a recipe to a real system that ran, not a demo. Used to be "actually shipped" — "actually" is now a banned word, so drop it. |
| Claude, Claude Code, Claude Opus (name the model) | AI, the AI, a bot, an assistant | critical | Name the specific model that did the work. Generic "AI" only for the industry/category in the abstract. |
| Tools used | tech stack, stack | preferred | Matches the "tools" frontmatter field and the ToolsUsed component name. |
| Cloudflare Workers (static assets) | Cloudflare Pages (for hosting, going forward) | critical | Hosting migrated off classic Pages 2026-07-19. Two older recipes still say "Pages" — known debt, not a model to copy. |
| the author | — | preferred | Reserve for link/nav labels only. Prose bylines use "Nathaniel Stich" or "Nathaniel" by name. |
| — | actually | critical | Banned outright in recipe/site-chrome copy: it's a hedge, not a claim. Exception: the author's own first-person writing (the /blog section and any future blog post). That's unedited voice, so don't strip it there. |
| — | exactly | critical | Banned outright: an intensifier standing in for evidence ("that's exactly the result," "not exactly") instead of the number itself — same hedge pattern as "actually," same exemption. |
Off-brand — never do this
critical| Rule | Guidance | Watch for |
|---|---|---|
| Adjective-only claims | Every claim needs a number behind it, or it gets cut. Don't describe a result as impressive: say what it was. | significant, massive, huge, incredible, game-changing |
| Hype-cycle urgency / fear-mongering | Never argue from "you'll be left behind." The case is proof, not pressure — show the number, let the reader draw the conclusion. | — |
| Mockery of a named tool or competitor | Factual, evidence-based comparisons with real numbers are fine. Sarcasm or trash talk about a named competitor is not. | — |
| Hiding the seams | Never present a page as if written by one uniform hand when it wasn't. Every substantive block gets a data-prov attribution. | — |
| ## Output restates the top callout | The page already states the headline result once, in the "Result:" readout at the top. ## Output exists to add what that single line can't — proof, specifics, numbers, caveats — not the same claim paraphrased. | An ## Output opening sentence that just rewords the frontmatter result string |
| Em dashes | Never use an em dash. Rewrite as two sentences, or use a comma or colon for the pause instead. | — |
Avoid — defaults to break, not absolute bans
preferred| Rule | Guidance | Watch for |
|---|---|---|
| Ad-tech / SaaS marketing filler | Cut it; use the plain verb or the real noun instead. | unlock, empower, revolutionary, seamless(ly), game-changing/changer, next-level, cutting-edge, robust, leverage (verb), AI-powered, transform(ed), holistic, synergy, journey |
| Permission-seeking / hedging filler | Cut phrases that stall or ask permission instead of stating the point. | would love to, we hope to, does this resonate?, it's worth noting that, needless to say |
| Vanity stat pills / emoji-as-punctuation | Numbers carry the proof; don't decorate them with fire emoji or exclamation points. | 🔥, 🚀, 🙌, "Happy Users", "5-Star Rated" |
| Testimonial-speak | Quotes and claims read like evidence, not ad copy. | "10/10, would recommend!", "Game changer!" |
Patterns — watch the cadence
preferred| Rule | Guidance | Watch for |
|---|---|---|
| Numbered build sequences | The default shape for a recipe's Pattern section when it's procedural. Prose pages stay in paragraphs. | — |
| Stat-first proof lists | Lead each proof-point line with the number, not the adjective in front of it. | — |
| Contrast structures ("not X, but Y") | Fine when the contrast is the point. Becomes a tic once it's the default sentence shape. | — |
| Parallel construction ("as X, not Y") | Repeating the same grammatical shape to set up a contrast reads sharp once, gimmicky the second time on a page. State the thing directly instead of defining it against what it isn't. | — |
Tone principles
preferred| Rule | Guidance | Watch for |
|---|---|---|
| Evidence over adjective | Replace abstract claims with the specific number — every claim defensible in an interview. | — |
| Direct address, third-person byline | Recipe/chrome prose speaks to "you." Authorship is credited in third person. First-person is reserved for op-eds. | — |
| Confident, not hyped | State the system and the result plainly. Let the number carry the weight. | — |
| Procedural inside a recipe, reflective outside one | A recipe's build steps are numbered and imperative; About/Manifesto stay narrative. | — |
| Show the work | Name the specific tool/model that did something and label every block's provenance. | — |
Turn this into a standalone skill
The prompt above works once you paste it into a session. A skill makes it load itself: one file that Claude reads automatically whenever the trigger condition in its own description matches, no copy-paste required.
- Create the file.
~/.claude/skills/voice-rules/SKILL.mdfor a personal skill available in every project on your machine, or.claude/skills/voice-rules/SKILL.mdinside one repo if the check should only fire there. - Phrase the frontmatter’s
descriptionas a trigger condition.name: voice-rulesplus adescriptionwritten as “use this skill whenever drafting or editing copy for [site/brand]” — so the skill loads itself the moment a matching request comes in, instead of waiting to be invoked by name. - Put the enforcement prompt and both rule tables in the body. A skill has no guaranteed access to a separate file elsewhere on disk, so make it self-contained: paste the instructions from Pattern step 4 above, followed by the Vocabulary and Style tables directly. (Skills can also bundle extra reference files in the same folder if the rule set outgrows one prompt.)
- Test it cold. Start a fresh session, ask for a draft, and confirm the skill triggers on its own — the check should apply without anyone pasting a prompt or naming the file.
No install step, no server, no repo required — it’s the fastest way to carry the check into a session, and the first thing to reach for before wiring it into anything bigger.
Skip the manual write-up. Download the blank template below, fill in your own vocabulary and
style rows, then paste the prompt underneath it — along with your completed doc — into a Claude
session. It writes the SKILL.md (frontmatter, enforcement instructions, and your tables) for you.
Download the blank voice-rules template (.md)
I've filled in the voice-rules template. Turn it into a Claude Skill:
1. Create SKILL.md at ~/.claude/skills/voice-rules/SKILL.md for a personal skill available in
every project on this machine, or .claude/skills/voice-rules/SKILL.md inside this repo if the
check should only fire here.
2. Write the frontmatter as a trigger condition: name: voice-rules plus a description phrased as
"use this skill whenever drafting or editing copy for [site/brand]" — not a title, so the
skill loads itself the moment a matching request comes in.
3. In the body, paste this enforcement instruction, followed by the Vocabulary and Style tables
from my filled-in doc below, verbatim:
- Treat every CRITICAL rule as a hard constraint — if a draft would violate one, don't write
that version; find the compliant phrasing instead.
- Treat every PREFERRED rule as a default — hold it unless there's a specific reason to break
it, and say what the reason is if you do.
- Check the draft against the Vocabulary table and every Style section before returning it.
- If a rule and the immediate content genuinely conflict, say so explicitly rather than
silently picking one.
Here's my filled-in doc:
[paste your completed voice-rules-template.md here]Wire it into a repo
A skill has to be installed on each person’s machine (or each agent’s config) to take effect. Wiring the same check into a repo instead means it comes with the codebase — anyone, or any agent, who clones it and reads its instructions inherits the check for free.
- Commit the rule doc. Keep the vocabulary and style tables in the repo itself — this site
uses
docs/VOICE.md— so it version-controls alongside the copy it governs. - Point the repo’s shared instructions file at it. Most coding agents read one file at the
start of a session (
AGENTS.md/CLAUDE.md/GEMINI.mdhere — often the same file, symlinked, so every tool reads the same source). Add a line like “Drafting or editing any site copy? Also readdocs/VOICE.md” to the section an agent already reads first. - Stop invoking it manually. Because that instructions file loads automatically, not by opt-in, the check now rides along on every future session in that repo — nobody has to remember the prompt, only that the doc exists.
- Optional — render it for humans too. If the rules should be browsable, not just
agent-readable, mirror them into a typed data file and a small component (this site’s
VoiceRulesPanel, rendered above) instead of leaving them only in markdown.
This is one step up from a skill: it doesn’t travel with you across repos, but it does mean every
agent working in this one applies the check without being asked, the same way
AGENTS.md/CLAUDE.md already does for this site today.
Turn this into an MCP server
The prompt above works inside one repo, for one agent that already has file access to
docs/VOICE.md. Wiring the same rule doc into an MCP server makes the check portable — any MCP
client (Claude Desktop, a different agent, a CI job) can call it without cloning the repo first.
- Keep the source-of-truth format the team already edits. Markdown works, or a typed export
like
voiceRules.ts. The server should read this file at request time, not embed a copy — that’s what keeps a check from drifting out of sync with a doc someone edited by hand. - Scaffold the server.
npm install @modelcontextprotocol/sdk zod, then start one file withMcpServerfrom the SDK. - Expose the doc as a resource —
voice://rules— that reads and returns the file live, so any client can pull the current rules without hardcoding them into a prompt. - Expose the enforcement prompt. Register a
check-voiceprompt that takes a draft string and returns the same instructions from Pattern step 4, filled in. This is the reusable skill: a client calls the prompt and gets back a ready-to-run check, instead of a human copy-pasting one. - Add a deterministic lint tool for the flat word list. Skip the model call for anything that’s
a straight forbidden-term match: a
lint-vocabularytool that string-matches a draft against the table and returns hits directly. Fast, and it catches word-swap violations the prompt-only path would otherwise spend a model call on — keep both, since tone and cadence still need the prompt. - Test with the inspector before wiring the server into anything:
npx @modelcontextprotocol/inspector node index.ts, then call the resource, the prompt, and the tool from its UI. - Register it with a client —
claude_desktop_config.json’smcpServersentry for Claude Desktop, or.mcp.jsonfor Claude Code — pointed at the same stdio command either way.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import fs from "node:fs/promises";
server.resource("rules", "voice://rules", async () => ({
contents: [{ uri: "voice://rules", text: await fs.readFile("./VOICE.md", "utf-8") }],
}));
server.prompt("check-voice", { draft: z.string() }, ({ draft }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `Before revising, read the voice://rules resource in full. Treat CRITICAL rules as ` +
`hard constraints; PREFERRED rules as defaults, breakable with a stated reason. Check this ` +
`draft against it and return violations plus a compliant rewrite:\n\n${draft}`,
},
}],
}));The prompt still does the actual judgment call; the server just makes it callable by any agent, not only one already working inside this repo. The same resource/prompt/tool shape generalizes to any severity-tiered rule set — swap the file the resource reads and the term table the tool checks.
Output#
This pattern is adapted from a 35-rule voice-rules system running in production against a real company’s blog studio, gating every Ideate/Create/Edit/Rewrite call. It’s not just a description of that system — this site runs a scaled-down version of it on itself, checked before this recipe went up. The table above is that same doc, rendered — not a screenshot of it.
Variations#
- Multi-author sites should keep the two-layer split the production version uses: company-wide CRITICAL/PREFERRED rules plus a per-author layer that only applies to that author’s own drafts — worth adding the moment more than one byline exists here.
- Publishing at higher volume? Move the check from a manual prompt into CI: a pre-commit or PR
check that diffs new/changed
.mdxagainst the forbidden-word list and fails the build on a CRITICAL hit, instead of relying on the model to remember to self-check. - The severity-tiered structure generalizes past prose — apply the same shape (approved/forbidden vocabulary, off-brand/avoid/pattern/tone-principle style) to PR titles, social copy, or release notes with a different vocabulary table and the same enforcement prompt.
- Want it in a single session with nothing to install first? Package it as a Claude Skill — see “Turn this into a standalone skill” above for the one-file version that loads itself on a matching request.
- Want every agent working in one repo checking automatically, with no prompt to remember? Wire
the doc into that repo’s shared instructions file — see “Wire it into a repo” above for how
AGENTS.md/CLAUDE.mdalready does this on this site. - Want it callable outside a coding agent entirely — from Claude Desktop, a different agent, or a CI job? Turn it into an MCP server — see “Turn this into an MCP server” above for exposing the rules doc as a resource, the prompt as a callable primitive, and the vocabulary table as a deterministic lint tool.
- Don’t want to write the style rules from scratch? The voice-rules cheat sheet is this same template with three CRITICAL rows already filled in (no parallel construction, one em dash per unit of content, no “not X, but Y”) — extend it with a site’s own vocabulary instead of starting from a blank table.