Editorial style guide
A public reference for the voice, structure, and editorial standards used across this site. Useful for contributors, AI assistants, and future me.
Voice and tone#
This site writes like a practitioner talking to other practitioners — friendly, specific, and generous with examples.
Core principles:
- Approachable but confident — conversational without being performative. Contractions are fine. Hedging ("sort of", "basically") is not.
- Show first, tell second — lead with code, visuals, or examples before explaining. The reader should see the thing before reading about it.
- Evidence over hype — be concrete. Avoid superlatives ("best", "always", "never") unless backed by evidence. Prefer specific numbers and named tools.
- Generous with links — link to sources, related posts, and external references using descriptive anchor text. Never "click here."
- Lightly self-deprecating — humor is welcome, but sparingly (0 – 1 per post). Never as a substitute for clarity.
Perspective and tense:
- First-person singular ("I") for personal experience. "We" only when describing genuinely collaborative work.
- Impact stories always use "I" — they're portfolio pieces showcasing personal contribution.
- Default to present tense. Past tense for specific events or chronology.
What this voice is not#
To clarify boundaries — if output sounds like any of these, revise:
- Not academic or formal — no hedging for politeness ("It could be argued that…"), no passive constructions to sound objective, no jargon without explanation.
- Not marketing or promotional — no superlatives about own work ("revolutionary," "game-changing"), no hiding tradeoffs to make an approach look perfect.
- Not tech swagger — no dismissive certainty ("Obviously," "Clearly," "It's simple"), no gatekeeping ("Any competent dev knows…").
- Not bureaucratic or evasive — no euphemisms ("rightsizing," "unlocking synergies"), no hiding problems in neutral language.
- Not soulless documentation — not just "what" and "how" without "why." Not reference material without narrative or motivation.
Tone by content mode#
The core voice stays consistent, but tone shifts by purpose:
| Mode | Tone | Markers |
|---|---|---|
| Instructional | Direct, procedural | Second-person imperative, numbered steps, code snippets, minimal commentary |
| Conceptual | Reflective, explanatory | Metaphors to anchor abstractions, rhetorical questions, longer sentences, diagrams |
| Impact story | Results-focused, evidence-backed | Problem → fix → outcome structure, metrics and comparisons, credits collaborators |
| Digesting | Crisp, curatorial | Source attribution up front, 3 – 5 key points, minimal editorializing, brief connection to own work |
| Analysis/opinion | Analytical, candid | Opens with a provocative claim, builds argument across sections, balances critique with alternatives |
Content types#
Blog posts#
Focused technical or observational writing. Tutorials, implementation guides, discoveries, opinions.
- Length: 600 – 1,200 words
- Title: Concise, no trailing punctuation, sentence case
- Teaser: One sentence, persuasive, 25 words or fewer
- Opening: Crisp value statement — what the reader gets or why it matters
- tl;dr block: Add one near the top for posts over 700 words
- Structure: H2/H3 sections, bullets and steps over dense paragraphs, code before explanation
- Closing: Restate the main point, invite feedback, link to related content
Impact stories#
Portfolio case studies demonstrating measurable outcomes through narrative.
- Length: 600 – 1,200 words (shorter and scannable beats exhaustive)
- Title format: Gerund phrase preferred ("Reclaiming three weeks of editorial time every month")
- Teaser: Sets up challenge/tension, not metrics
- Result themes: Three bold phrases near the top (
**Efficiency** | **Reliability** | **Consistency**) - Section headers: Use questions for narrative momentum ("What was actually breaking?")
- Perspective: Always "I" — even for collaborative work, use "I led the team to..." not "we." Reserve "we" only when the team's collective action is genuinely the point
- Metrics: Specific numbers with baselines ("0.88s → 0.45s", not "50% faster"), plus human-impact framing ("equivalent to 3 full work weeks")
- Tone: Show process, tradeoffs, and strategic vulnerability. Acknowledge what almost didn't work.
Digesting posts#
Short-form commentary on things I've read or discovered. The key principle: never reuse the source article's title. Rewrite in your own voice to reflect what you found valuable.
Title patterns:
- Focus on what you learned: "Why I should have been using the output tag all along"
- Make it specific: "Engineers need 45 minutes to hit peak focus"
- State a clear takeaway: "Context engineering beats prompt tricks for AI agents"
- Use conversational language: "Thoughtful AI integration beats bolted-on Clippy"
Bad titles (just restating the source):
- "HTML's Best-Kept Secret: the output tag"
- "Distracting software engineers is way more harmful than most managers think"
Guidelines:
- Link back to the source prominently (via
digest_linkin frontmatter) - Keep commentary brief — this is a reaction, not a rewrite
- No trailing punctuation on titles
- Use first-person perspective when natural
Structure templates#
Blog post skeleton#
Opening value statement (1 – 2 sentences)
tl;dr or "You'll learn" block (if > 700 words)
---
## Section heading
Body content with bullets, code, visuals
## Section heading
More content
---
Closing: restate main point, invite feedback, related links
Impact story skeleton#
**Result theme 1** | **Result theme 2** | **Result theme 3**
Organization context box (orgIntro macro)
---
Opening (2 – 3 short paragraphs: stakes, challenge, your role)
## What was the problem? (question header)
Challenge details
## How did you approach it? (question header)
Solution with constraints and tradeoffs
## What were the outcomes? (question header)
Metrics with human-impact framing
## Why did this work? (question header)
Reflection — specific factors, not generic lessons
---
Related links
Formatting rules#
Headlines#
- Sentence case unless a proper noun is involved
- No trailing punctuation
- Heading hierarchy must be sequential: H2 → H3 → H4 (never skip levels)
Teasers#
- One sentence, 25 words or fewer
- Persuasive — sell the value, not the topic
- Avoid links unless essential
Em dashes#
Use spaced em dashes for readability: word — word (space, em dash, space). In source, write -- and the build converts to —.
Links#
- Embed on descriptive nouns or phrases — describe where the link goes
- Use absolute URLs for external links, relative for internal (
/work/2025/slug/) - Verify all links resolve before publishing
Images#
- Place files in
src/site/images/blog/ - Reference in frontmatter as
/blog/filename.jpg(the build adds/images/automatically) - Always include
image_meta.altext(screen readers) andimage_meta.text(visible caption) - For your own photos: use "Own work." as attribution, not "Photo by Ken Hawkins"
Code blocks#
- Use fenced code blocks with language identifiers inside
{% markdown %}sections - Show code or visuals before explaining them in prose
- Keep inline comments minimal — let the code speak
- For Nunjucks templates in code fences, wrap in
{% raw %}…{% endraw %}to prevent the template engine from evaluating your example code - Use standard
figure/figcaptionfor images that carry meaning
Lists#
- Convert dense prose into bullets or numbered steps
- Prefer bullets for unordered information, numbers for sequential steps
- Keep list items parallel in structure
Paragraphs#
- Blog posts: 2 – 4 sentences
- Impact stories: 2 – 3 sentences (tighter for scannability)
- Single-sentence paragraphs are fine for emphasis
Rhythm and pacing#
Good writing has varied rhythm. A few principles:
- Vary sentence length — alternate short declarative (5 – 10 words), medium explanatory (15 – 25 words), and occasional longer sentences. Never write three sentences of similar length in a row.
- Fragments for emphasis — sentence fragments create pauses ("Exactly as you manage any capable collaborator."). Use sparingly — once every 2 – 3 paragraphs at most. They work because they're rare.
- Lists as breathing room — after 2 – 3 dense paragraphs, introduce a list, table, or code block. Let the reader's eye rest before continuing.
- Em dashes control pace — use them when you want the reader to slow down and process layers of meaning. Omit them when you want urgency or directness.
- Section transitions should feel inevitable — avoid explicit transitions ("Now let's move on to…"). Structure sections so each one naturally prompts the question answered by the next. Test by removing all transition sentences — the headers alone should create flow.
Frontmatter reference#
Blog post#
---
title: 'Concise, clear headline'
layout: layouts/post.njk
teaser: 'One-sentence persuasive summary (≤ 25 words).'
image: '/blog/example.jpg'
image_meta:
text: 'Attribution or context.'
altext: 'Accurate alt text for screen readers.'
date: YYYY-MM-DD
tags:
- posts
topics:
- keyword one
- keyword two
via: 'https://example.com/source' # optional: source attribution
kens_status: draft # draft | final_draft | ready_for_publication
---
Impact story#
---
title: '[Gerund phrase describing the work]'
layout: layouts/post.njk
teaser: 'Narrative hook — tension/challenge, not metrics.'
date: YYYY-MM-DD
tags:
- posts
- impact-stories
topics:
- keyword one
- keyword two
org: Organization Name
permalink: /work/YYYY/impact-story-slug/
image: '/blog/example.jpg'
image_meta:
altext: 'Descriptive alt text.'
text: 'Attribution or context.'
kens_status: draft
---
Digesting post#
---
title: 'Your rewritten title in your voice'
layout: layouts/digesting.njk
teaser: 'Brief description of what the source covers.'
date: YYYY-MM-DD
digest_link: 'https://example.com/source-article'
tags:
- digesting
topics:
- keyword one
- keyword two
---
Status tracking (kens_status)#
Track content readiness with the kens_status frontmatter field:
draft— initial draft, work in progressfinal_draft— content complete, ready for final reviewready_for_publication— reviewed and approved, ready to publish
OpenGraph overrides#
All pages get auto-generated social cards by default. Override individual fields when needed:
og_title: 'Custom OG Title'
og_description: 'Custom OG description'
og_image: 'https://example.com/custom-image.jpg' # full URL required
Note boxes#
Use the kh-note-box pattern for asides, updates, or contextual callouts:
<aside class="kh-note-box">
<span class="kh-note-box__label">Update</span>
Your short note content goes here.
</aside>
Keep the label short: "Update", "Sidebar", "Related", "Context". Place a blank line before and after the aside. Prefer aside in post bodies; div is acceptable in layout templates.
Code and demo shortcode#
Use the codeAndDemo paired shortcode to show a snippet as both an escaped code block and a live rendered demo from the same source. Place it outside {% markdown %} blocks (Markdown will double-escape otherwise).
{% codeAndDemo 'html' %}
<button class="kh-button">Click me</button>
{% endcodeAndDemo %}
Guidelines:
- The first argument (e.g.,
'html') sets the language class for syntax highlighting - Best for runnable HTML/JS examples — avoid using it for Nunjucks template code
- Don't duplicate the same example in both a fenced code block and the shortcode — let it handle both
- Keep demos minimal and self-contained
Dos and don'ts#
Do:
- Open with value — one crisp sentence that sets context and benefit
- Use a tl;dr or "You'll learn" box near the top for posts over 700 words
- Prefer bullets/steps over long paragraphs for procedures
- Show first, then tell — place code/visuals before deep explanation
- Write descriptive links and include image alt text + attribution
- Close warmly with a brief summary and invitation for feedback
- Always include a blank line after headings before the next paragraph
Don't:
- Ship walls of text without headings and lists
- Over-optimize for wit — keep humor subtle and sparse
- Omit alt text or captions when images convey meaning
- Embed "click here" — link meaningful phrases instead
- Leave trailing whitespace or inconsistent heading levels
- Use emojis as replacements for clear writing
Examples: good vs bad#
Titles#
Impact stories:
- Good: "Reclaiming three weeks of editorial time every month"
- Bad: "Impact story: Editorial efficiency"
Section headers:
- Good: "What was actually breaking?" (question for momentum)
- Bad: "Problem description" (generic label)
Outcomes formatting#
Good:
Efficiency: 120 hours/month reclaimed — equivalent to 3 full work weeks. Reliability: Timeout failures reduced 85%. Editors stopped losing work.
Bad:
- Saved time
- Fewer errors
Showing vulnerability#
Good: "The first migration attempt failed silently. We discovered the database schema had drifted from what we assumed, which forced a two-week detour to reconcile field mappings."
Bad: "We successfully completed the migration on schedule."
tl;dr blocks#
Good:
tl;dr
- We forked 11ty's cmd.js to better integrate with gulp.
- Demo at khawkins98/gulp-eleventy-example.
Bad: "In this post I'm going to tell you about a lot of things. Let's get started."
Cross-linking#
- Impact story → impact story: Link to stories covering related domains or time periods
- Impact story → blog post: Link to tutorials explaining techniques used
- Blog post → impact story: Reference portfolio context where techniques were applied at scale
- Use descriptive link text explaining why the link is relevant
- Add brief parenthetical context when helpful: "(similar caching approach)"
- Prefer relative URLs for internal content
When to break these rules#
These guidelines are defaults, not laws. Legitimate exceptions:
- Longer paragraphs for narrative — when telling a story (how a project unfolded, how an idea evolved), sustained paragraphs of 6 – 8 sentences create momentum. Break for lists when enumerating parallel points.
- Scene-setting in opinion pieces — the "open with value" rule applies to instructional content. Analysis and opinion pieces sometimes need one paragraph of shared-experience context before the provocative claim.
- Genuine enthusiasm — the "no hype" rule discourages empty superlatives, but authentic excitement about a discovery or someone else's work is welcome. Avoid using it to hype your own contributions.
- Rhetorical questions as pivots — use them to shift between major sections or challenge an assumption. Avoid as filler or to open every section.
- Passive voice for de-emphasis — acceptable when the actor is irrelevant or you're emphasising inevitability ("Content will be consumed"). Never use it out of habit or to sound formal.
- Single-line sections for drama — occasionally a section can be just one sentence for emphasis. It works because it violates the expected rhythm.
Quality checklist#
Before publishing any content, verify:
- [ ] Headline is concise with no trailing punctuation
- [ ] Teaser is one sentence, 25 words or fewer, and persuasive
- [ ] Opening includes a crisp value statement
- [ ] tl;dr or "You'll learn" block added for posts over 700 words
- [ ] Dense prose converted to bullets or steps
- [ ] Code and visuals shown before deep explanation
- [ ] All images have alt text and attribution
- [ ] Internal and external links verified
- [ ] Heading hierarchy is sequential (H2 → H3 → H4)
- [ ] No trailing whitespace or inconsistent spacing
- [ ] Blank line after every heading before the next paragraph
- [ ] Warm closing restating main point and inviting feedback
- [ ] Frontmatter complete: title, teaser, date, layout, tags, topics
- [ ] Markdown polished: correct heading levels, fenced code, consistent formatting
Impact story additions#
- [ ] Title uses gerund format
- [ ] Result themes (3 short phrases) appear near the top
- [ ] Section headers are questions
- [ ] Uses "I" perspective throughout (not "we") — portfolio pieces showcase personal contribution
- [ ] Shows constraints, tradeoffs, and vulnerability
- [ ] Paragraphs are 2 – 3 sentences with bold lead-ins
- [ ] Metrics include human-impact framing
- [ ] 600 – 1,200 words