Back to catalog
SkillDesign & MediaOfficial Verified

Technical Blog in My Voice

Turn a paper or repo into a technical blog post, then run a seven-check gate before publishing.

#blog#writing#medium#substack#voice#technical-writing#publishing

Install

With the Zana CLI
$ zana add technical-blog-in-my-voice

`scripts/voice_check.py` is stdlib-only Python 3.9+, so there is nothing to install. `scripts/table_to_image.py` needs Pillow and imports it at module load, so without it the script exits on a traceback rather than a message: `uv run --with pillow scripts/table_to_image.py table.md out.png`, or `pip install pillow`. Pass `--font-dir` pointing at the brand fonts; the default fallback renders type small. Internal note: `references/personal-threads.md` holds the author's approved biography threads. Scrub or replace it before this repo is made public.

How it runs

A publishable post, or a draft that says why it is blocked.

  1. 01

    Intake

    Two named audiences, publication status, length

  2. 02

    Anecdote

    One real failure. Never invented

  3. 03

    Draft

    Split lede, built-versus-specified, loop closed

  4. 04

    voice_check

    Dashes, prose colons, rhythm, surviving tables

  5. 05

    Publish gate

    Claims, invented details, clearance, links

  6. 06

    Deliver

    Post, images, and the specifics needing confirmation

Marked steps are enforced by a script.

8 files. Read them here, or pull the folder without the CLI.

Copy the folder into your skills directory
$ npx degit aminitech/amini-zana/catalog/skills/technical-blog-in-my-voice ~/.claude/skills/technical-blog-in-my-voice

No clone, no history. Just this folder.

Sparse checkout (private repos, uses your git auth)
$ git clone --depth 1 --filter=blob:none --sparse https://github.com/aminitech/amini-zana.git && cd amini-zana && git sparse-checkout set catalog/skills/technical-blog-in-my-voice
Single file (SKILL.md)
$ curl -sL https://raw.githubusercontent.com/aminitech/amini-zana/main/catalog/skills/technical-blog-in-my-voice/SKILL.md
SKILL.md
---
name: technical-blog-in-my-voice
description: Write a technical blog post, Medium article, Substack essay, launch post, or paper companion in Zoe's voice, then run a pre-publish gate over it. Produces casual-but-rigorous first-person prose with no em dashes, no prose colons and no emoji, a split lede for two named audiences, a real failure anecdote, a built-versus-specified honesty section, tables converted to images, and a seven-check gate covering claims, invented details, clearance, links and platform mechanics. Use this WHENEVER the user asks to "write a blog post", "write the Medium post", "write an accompanying blog for this paper", "turn this paper or repo into a post", "draft a launch post", "write this up for Substack or LinkedIn", "make this sound like me", "make this less AI generated", "rewrite this in my voice", or wants a draft checked before publishing. Trigger on a bare "blog this" or "write it up", and on the editing side when a draft sounds robotic or needs personality. Not for academic papers, decks, or internal status reports.
---

# Technical blog in Zoe's voice

Two failure modes kill these posts. The prose reads like a press release, or it overclaims and an
engineer who reads it carefully stops trusting the work. This skill exists to prevent both, and the
second one matters more.

The house style is casual and rigorous at the same time. Coffee with a friend who happens to be a
scientist. Short sentences next to long ones. Real failures admitted. Every number traceable.

## Before writing anything

Read `references/voice-rules.md` now. It is short and it is the whole point of the skill.

Then check whether the source material is in hand. Papers, repos, result plots, screenshots. If
the user pointed at a PDF or a folder, read it before asking questions, because half the intake
answers are usually sitting in the document and asking for what you could have read is annoying.

## Phase 0, intake

Ask four questions in a single `AskUserQuestion` block. Four is the tool maximum, and one block
means the user answers in twenty seconds instead of playing tennis across five turns.

1. **Source and publication status.** Already public with a link in hand, written but not yet
   announced so the post needs placeholders and an embargo hold, no paper because this is a build
   log, or repo and dataset only. This answer decides whether the draft carries `[ARXIV-ID]` and
   `[DOI]` placeholders and whether the whole file gets stamped do-not-publish.
2. **The two audiences, named specifically.** Push back on "technical and non-technical". "AI-RAN
   researchers" and "ministry permanent secretaries" produce a different lede than "GIS analysts"
   and "climate finance officers". The named answer becomes the split lede.
3. **Personal thread.** Offer the saved threads from `references/personal-threads.md` plus a new
   one and none. Reusing approved wording beats re-inventing someone's biography every time.
4. **Platform and length.** Medium only, Substack primary with a Medium cross-post and canonical
   link, both plus a LinkedIn teaser, or internal. Length 1,200 or 2,500 or long-form 4,000 plus.

Then ask the built-versus-specified question as plain text, because it cannot be multiple choice.
Two lists. What runs today, and what is specified but never evaluated. If the answer is
"everything works", ask once more what has never been measured, calibrated, or load tested.
Something always has not been.

## Phase 1, the anecdote

Ask for this separately and do not skip it. A post with one real failure in it outperforms a
flawless one, because the failure is what convinces a reader that a person did the work.

> I need one real failure story to break the flow about two thirds through. Not a triumph.
> Something that went wrong, ideally where you had to learn a tool that was not your job.
> Three things and I will shape it. What broke. Who caught it. What you had to go and quietly
> look up afterwards.
> If nothing comes to mind, tell me the last time a result looked completely plausible and was
> completely wrong.

If the answer is thin, follow up with "what did the wrong version look like on screen, because the
funny part is usually that it looked fine."

If the user declines, leave the section out. Do not write one from imagination. Inventing an
anecdote is the single worst thing this skill could do, because the user will publish it under
their own name and be asked about it by someone who was there.

**The never-invent rule.** No invented ages, prices, durations, dates, colleague names, job
titles, or quotes. When a specific would help and is missing, either ask or leave `[CONFIRM: ...]`
inline. Every invented or inferred specific gets listed back at delivery for confirmation. This
is a hard gate in Phase 3.

## Phase 2, drafting

Structure that has worked, adapt freely:

1. Title with no colon, and a dek that carries the technical keywords the title does not
2. Split lede naming both audiences and telling each where to start
3. Personal opening that earns the topic rather than decorating it
4. The problem, stated as a number or a contradiction
5. The idea, in plain language, with the jargon term introduced after the concept
6. What was actually built, with real figures
7. The failure anecdote
8. The results, hardest evidence first
9. Architecture and the uncomfortable constraints
10. Built versus specified, tagged explicitly
11. Why it generalises, closing the personal thread from step 3
12. Read next, then references, then attribution and data-licence notes

The step 3 and step 11 pairing is what makes these posts feel written rather than assembled. Open
a loop, close it. In the S-CDT post the internet cafe opens the piece and comes back in the last
three paragraphs as the reason sovereign compute matters, which turns a technical constraint into
something a reader feels.

Introduce the concept before the acronym. "One base station, one waveform, two jobs" lands, then
"the industry term is ISAC" is a label for something the reader already understands.

Numbers do the persuading. "130,248 individual building footprints" is worth more than any
adjective. Pick the one figure in a section that should unsettle the reader and say so plainly,
the way "0.68 critical facilities per 10,000 residents" gets its own line.

## Phase 3, the pre-publish gate

Run `scripts/voice_check.py` on the draft first, because it catches the mechanical failures in a
second and there is no reason to eyeball them:

```bash
python3 scripts/voice_check.py path/to/draft.md
```

It reports dashes, prose colons, emoji, banned phrases, sentence-length statistics, surviving
markdown tables, suspected generic section openers, and reading time. Non-zero exit means a hard
failure. Fix and re-run rather than arguing with it.

Then work through `references/prepublish-gate.md`, which covers the six checks a script cannot
do. Claims traceability, invented details, clearance, links, platform mechanics, and reading the
opening out loud.

Report the gate as a short pass and fail list. Where something fails, say what specifically and
what it would take to clear it.

**Clearance behaviour.** Produce the draft either way, because the user needs to read it, but if
any clearance question is unresolved put a banner at the very top of the file:

```
> DO NOT PUBLISH YET. Blocked on [reason]. Remove this line when cleared.
```

Do not describe a post as ready while that banner is present. A blog post is a timestamped public
disclosure, and in most jurisdictions there is no patent grace period, so a cheerful "all set" on
an uncleared post is a real harm rather than a process foul.

## Platform mechanics

Read `references/platform-notes.md` when the target is Medium, Substack, or LinkedIn.

The one thing to internalise now is that Medium destroys markdown tables. Convert every table to
an image with `scripts/table_to_image.py`, and bake side-by-side comparisons into a single image
so a phone cannot stack them and break the comparison. Write alt text as real description, since
an image table is invisible to a screen reader otherwise.

## Delivery

Ship the markdown file, an image folder, and a short companion note giving upload order, image
grid instructions, suggested tags with live follower counts, and alternate titles.

Close with three things, in this order. The invented or inferred specifics needing confirmation.
The gate results. The single highest-value edit the user could make. Do not bury the invented
details under praise for the draft.

## Reference files

- `references/voice-rules.md`, the punctuation and rhythm spec, read this first and every time
- `references/prepublish-gate.md`, the six human checks in Phase 3
- `references/platform-notes.md`, Medium and Substack and LinkedIn mechanics, tags, canonical links
- `references/personal-threads.md`, approved biography threads and exemplar passages
- `scripts/voice_check.py`, the mechanical scanner
- `scripts/table_to_image.py`, renders a table to PNG in the Amini light palette

About

The full workflow for one artefact: a technical blog post, Medium article, Substack essay, launch post, or paper companion. It handles the parts a voice pass alone does not, including a four-question intake, a split lede written for two named audiences, a real failure anecdote, a built-versus-specified honesty section, tables converted to images because Medium destroys markdown tables, and a pre-publish gate. Two failure modes drive the design. Prose that reads like a press release, and prose that overclaims until a careful engineer stops trusting the work. The second one matters more, so the never-invent rule is a hard gate: no invented ages, prices, durations, dates, colleague names, job titles, or quotes, and every inferred specific gets listed back for confirmation at delivery. An unresolved clearance question puts a do-not-publish banner at the top of the file, because a blog post is a timestamped public disclosure. `scripts/voice_check.py` scans the mechanics: dashes, prose colons, emoji, banned phrases, sentence-length statistics, surviving markdown tables, generic section openers, and reading time. `scripts/table_to_image.py` renders tables to PNG in the Amini light palette. Pairs with humanizer-voice, which covers line-level voice across every other surface. This skill is stricter: it also bans prose colons, cuts the first sentence of every section, and targets specific rhythm statistics.

docs
Author

Amini 路 Manila, Philippines

Related in Design & Media