| name | good-docs-writer |
| description | Turn a topic into a structured blog-post draft using Good Docs templates with blog voice. Triggers: "$good-docs-writer <intent> <topic>", "write a blog post about X", "draft a blog post on X".
|
| allowed-tools | Bash Read Write Glob Grep AskUserQuestion |
| metadata | {"author":"Alexander Opalic","version":"0.1"} |
Good Docs Writer
Turn a topic into a first-draft blog post that already has a solid structural spine (a Good Docs template) and a blog voice (hook, narrative, takeaways, CTA).
Built on top of The Good Docs Project — templates fetched at runtime from gitlab.com/tgdp/templates (MIT-0). All credit for the structural craft of the templates goes to that community; this skill is just the adapter.
Why this matters
The hardest part of a blog post is not the writing — it's deciding what shape the post should have. Good Docs templates already encode the right shape for each documentation intent. This skill maps blog-post intents to those templates, fetches the live template, and layers blog voice on top.
This is the blog-flavored counterpart to doc-generator (which produces neutral docs) and doc-improver (which improves existing rough markdown).
Process
1. Classify the post intent
If the user used the explicit form ($good-docs-writer walkthrough adding auth to Astro), trust the intent and skip classification.
Otherwise, read references/template-index.md and walk the decision matrix top-to-bottom. Stop at the first row that matches.
If two rows fit equally — most commonly concept (explainer) vs. tutorial (walkthrough), or tutorial vs. how-to — call AskUserQuestion. Don't guess.
State the chosen intent and template back to the user in one sentence before generating, e.g. "Treating this as an explainer — using the Good Docs concept template as the spine."
If the topic is an opinion essay or personal narrative with no good template fit, tell the user and offer either a loose concept backbone or freeform.
2. Read the bundled template + guide
The skill ships with a frozen snapshot of every supported Good Docs template under references/templates/. Use Read on the local files — do not WebFetch, the snapshot is the source of truth.
Read references/templates.md for the catalog and exact paths. For the chosen key, read:
references/templates/<key>/template.md — the scaffold to fill in
references/templates/<key>/guide.md — explains what each section/placeholder means
Also read references/writing-tips.md once per session if you need general voice/concision guidance. Only read the larger references/style-guide.md when verifying a specific style call (it's ~49 KB).
Do not reproduce template structure from memory. The bundled file is canonical — if you can't read it, stop and tell the user something is wrong with the install.
3. Gather material for the post
Two paths:
- Topic is tied to the user's repo (e.g. "blog post about how our auth flow works"): explore the repo with
Glob / Grep / Read to collect concrete file paths, function names, code excerpts. For larger explorations, you can launch subagents — but most blog posts only need a focused scan, not parallel agents.
- Topic is general / not repo-tied (e.g. "blog post about Postgres advisory locks"): ask the user for any anchor material — links, prior drafts, key points they want included. If they have none, proceed from general knowledge but flag it ("this draft uses general knowledge — verify specifics before publishing").
Either way, ask the user once for: target audience (e.g. "Vue devs new to Pinia"), rough length, and any voice cues they want preserved (their existing posts, a tone they want to match). Skip if they already specified.
4. Fill the template, then blogify
Walk the fetched template section by section:
- Replace each
{placeholder} with concrete content drawn from material gathered in step 3.
- If a section has no matching material, skip it entirely — do not invent filler.
- Preserve the template's section order and heading text where it reads naturally; rename headings if the docs phrasing sounds stiff in a blog context (the section-by-section moves in references/blog-voice.md tell you which renames are safe).
Then layer blog voice using references/blog-voice.md:
- Add a hook in place of the neutral summary paragraph.
- Add a stakes paragraph right after the hook — what the reader walks away with.
- Add a takeaways block before the conclusion (3–5 bullets, full sentences).
- Add a CTA as the final paragraph — one specific next action.
- Apply the voice rules globally (first person OK, contractions on, short hook sentences, show trade-offs, code over prose).
Code snippets must be real — if the post is repo-tied, every snippet should be greppable in the repo. If general, mark sample code as illustrative.
5. Write the output file
- Slug: kebab-case of the topic (e.g. "Adding auth to Astro" →
adding-auth-to-astro.md).
- Path: detect existing blog folder convention, in this order:
src/content/blog/ (Astro/most modern setups)
content/blog/ (Nuxt/Hugo)
posts/ (Jekyll/older blogs)
_posts/ (Jekyll convention)
- Fallback:
blog/ (create if missing)
- Frontmatter: if sibling posts in the chosen folder use frontmatter (Astro content collections, Hugo, Jekyll, etc.), match their shape exactly — title, date (today, ISO), description, draft-flag, tags. Read 1–2 sibling files to confirm. If no sibling pattern exists, omit frontmatter.
- Filenames use hyphens, never underscores or spaces.
6. Report what was generated
After writing, print a short summary (≤ 10 lines):
- The intent and template chosen, in one sentence.
- Which template sections were filled vs. skipped, with the reason for any skips.
- Where the file was written, and which sibling-frontmatter convention was matched (or "no frontmatter — none detected").
- The 1–2 things the user should manually verify (claims that came from general knowledge, code snippets that need a working example, etc.).
The user will read the draft themselves — don't summarize the post content.
Rules
- Never fabricate the template. Always
Read from references/templates/<key>/. If the file is missing, stop and tell the user the install is incomplete.
- Never invent code, file paths, or APIs for repo-tied posts. Every snippet must be greppable.
- One topic per run. If the user asks for a series, push back and ask which post to start with.
- Preserve template structure — Good Docs sections are load-bearing. Add blog voice around them, not by deleting them.
- Ask when ambiguous. Use
AskUserQuestion for intent ties (concept vs. tutorial, tutorial vs. how-to) rather than guessing.
- Show, don't pad. A working snippet beats three paragraphs of explanation. Cut filler aggressively.
Example invocations
$good-docs-writer explainer how Vue's reactivity proxy works
$good-docs-writer walkthrough adding Clerk auth to an Astro site
$good-docs-writer debug-story the trailing-slash 404 in production
write a blog post about Postgres advisory locks
draft a blog post on our migration from Webpack to Turbopack