Generated banner for Make Blog Post
Generated logo for Make Blog Post

Make Blog Post

GitHubOfficialFirst committed by jhaugaDistributed by GitHub

  • Skill
  • Content generator
  • Documents and content
  • MIT
  • No issues found

From the author

Turn code from the current session into a blog post written in the voice of its author. Covers one function, script, class, or tool as a focused walkthrough with a generalized sample and a usage example, learns tone and structure from existing posts or writing samples by the same author, takes the destination from what the user names or the blog repository in use instead of assumed folders, and saves no file until the draft is approved. Use when asked to write, draft, or turn code into a blog post, article, tutorial, or gist, or when invoked as /make-blog-post at the end of a turn.
— the description by jhauga

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill generates a blog post, article, or tutorial based on code developed in your current session. It focuses on a single function, script, or tool, providing a walkthrough that includes a generalized code sample and a usage example. The skill learns your writing style from provided samples or existing posts to ensure the output matches your voice. It respects site-specific conventions for blog platforms and ensures no files are saved until you have reviewed and approved the draft.

What it does

  • Converts session code into a structured blog post or tutorial.
  • Learns your writing voice from provided samples or existing repository posts.
  • Generates a focused walkthrough with a generalized code sample and usage example.
  • Detects and adheres to specific blog platform front matter and file naming conventions.
  • Provides a draft for review before saving any files.
  • Offers to link the post from existing documentation.

When to use it

  • When you want to turn a piece of code you just wrote into a blog post or tutorial.
  • When you need to draft a technical article that matches your personal writing style.
  • When you are working within a blog repository and need to follow existing site conventions.
  • When you want to share a code walkthrough as a gist or chat-based draft.

Advantages

  • Maintains consistency with your existing writing voice and style.
  • Automates the formatting required by various blog platforms.
  • Ensures code samples are generalized and free of sensitive project-specific data.
  • Prevents accidental file creation by requiring explicit approval.

Usage examples

“/make-blog-post”
The agent identifies the code from the current session and initiates the planning process to draft a blog post.
“/make-blog-post the retry helper in src/http.ts”
The agent focuses the walkthrough specifically on the retry helper function found in the specified file.
“/make-blog-post the slugify function, as a gist”
The agent prepares a gist-formatted walkthrough for the slugify function without using front matter.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/github/make-blog-post/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip make-blog-post.zip -d .agents/skills

Documentation by jhauga

Make Blog Post

Turn code from the current session into a blog post that reads as if its author wrote it: one walkthrough of one function, script, class, or tool, built around a generalized sample and a usage example.

This skill runs only when the user asks for a post. The natural moment is the end of a turn, once the code works: /make-blog-post, optionally followed by what to cover, where the post goes, and links or files of the author's past posts.

When to Use This Skill

  • The user asks to write, draft, or turn code into a blog post, article, tutorial, walkthrough, or gist.

  • The user invokes /make-blog-post, with or without naming the subject, the destination, or writing samples.

Do not use it for API reference, READMEs, changelogs, or release notes, or for a post that needs several unrelated examples or a multi-file walkthrough.

Examples

/make-blog-post
/make-blog-post the retry helper in src/http.ts
/make-blog-post the slugify function, as a gist
/make-blog-post put it in the blog, match https://example.com/posts/one and https://example.com/posts/two

Workflow

Work through the steps in order. Nothing is written to disk until the draft is approved in step 5.

1. Pick the subject
  • Use what the user named: a function, file, selection, snippet, or topic. Code pasted into the conversation is in scope too.

  • Otherwise, take the code written or changed in this session. When more than one piece qualifies, list up to three, each with a one-line purpose, and ask which one to write up.

  • Check that the subject works as a standalone post. It should:

    • Solve one clear, general-purpose problem.

    • Fit in one self-contained example.

    • Not depend on project-specific state, services, or configuration that cannot be replaced with a stand-in.

    • Not be trivial. A one-line wrapper or a lone standard-library call does not qualify.

  • When a check fails, say which one and suggest an angle that works, such as the technique behind the code. Proceed with the original subject if the user still wants it.

2. Resolve the destination

Consider only what the user said, the current workspace, and paths the user provides. Do not assume any folder exists, and do not walk parent or sibling directories looking for one.

  1. The user named a destination (a local path, the current workspace repository, a venue such as a gist, or "just show me"): use it, and do not move the post elsewhere because another place fits conventions better. If the user names another repository, ask for its local checkout path; do not clone or modify it remotely. A partial name such as "the blog" resolves against the current workspace only. If the workspace is not that blog, ask for the path.

  2. The workspace is a blog or site: take the posts folder from the generator's own configuration, and match an existing post's folder, extension, file naming, and front matter. See references/blog-platforms.md for detection and each generator's contract.

  3. Otherwise: write no file. Deliver the post in chat and offer to save it to a path the user names.

A default destination or voice profile recorded in the user's custom instructions counts as named by the user. That is the place for a personal workflow, such as a folder where every post is archived.

When writing to a named path:

  • Create missing subfolders under a root that exists. If the root itself does not exist, ask instead of building a tree that may be a typo.

  • If the path breaks the detected generator's contract (the wrong folder for the collection, a missing date prefix), state in one line what would break, offer the compatible path, and ask which to use.

  • If the request conflicts with the site's conventions, say so once, then follow the request. The security rules and the approval gate still apply.

3. Learn the author's voice

A post that reads like generic documentation is not the author's post. Before drafting, collect three to five samples of the author's own writing, from these sources in order:

  1. Samples named in the request: files, folders, URLs, or pasted text.

  2. A saved voice profile the user points to, in the request or in their custom instructions.

  3. When step 2 resolved a blog repository, the most recent posts by this author in its posts folder.

When these sources give fewer than three samples, ask once for enough links or files to reach three, unless the user has already said there are no more. Then work with what there is:

  • Three or more: build the full profile.

  • One or two: build a thin profile from only the patterns those samples confirm, and offer the three quick questions in the reference to fill the gaps.

  • None: offer the three quick questions, or write in a plain, neutral voice.

A saved profile counts as the number of samples it records. Say at the plan check which case applies and how many samples the profile rests on. Never present a thin or neutral draft as a full match.

Build a short profile with references/voice-profile.md: person and address, formality, rhythm, openings, headings, how code is introduced and explained, closings, and mechanics such as spelling and punctuation habits. The samples are evidence of style only. Nothing from their content (sentences, anecdotes, names, links) goes into the new post, and no personal experience is invented to fit a pattern.

4. Check the plan

Before drafting, present these in a few lines and wait for a yes:

  • The subject and the single purpose the post covers.

  • The destination as a full path, with the config file it was resolved from when a generator was involved, or "chat only".

  • The voice source (which samples or profile, and how many samples it rests on) and three to five bullets summarizing it. Call a thin profile or one built from answers a partial match, and a neutral voice no match.

  • The working title, the slug, and the SEO level.

  • Any open question, when there is one, such as the real story behind a personal opening, or an existing post at the destination on the same subject (update it, take a new angle, or stop).

On a decline, stop and write nothing. When the post will be delivered in chat, no file is saved, so skip the extra round trip: put the plan at the top of the reply that carries the draft, and let one approval cover both.

5. Draft and get approval

Draft the post per Building the post, show it in full, and invite edits. Revise and show it again until the user approves. Silence or an ambiguous reply is not approval. Drafting and showing the post in the conversation needs no approval, but nothing is saved to a file, published, committed, or pushed before an explicit yes.

6. Deliver
  • File: write to the confirmed path in the site's format, using the host's path separators and the repository's line endings. Name a standalone file after the slug (slugify-text.md), which describes what the code does, not the project. Approval was the gate, so write the post ready to publish. If the user asks for a draft instead, use the platform's draft mechanism (see references/blog-platforms.md) and name it in the report.

  • Chat: follow the copy-paste rules in references/delivery.md.

  • A gist, discussion, wiki page, or hosted platform the user posts to by hand: shape the post and list its field values per references/delivery.md.

Report what was written and where. Committing, pushing, uploading, or publishing is a separate action that needs its own request.

Close with up to two one-line offers:

  • Link the post from the docs, when the post has a published URL or a path inside this repository to point to, and the repository already documents this code. That means a README section, a docs page, or a doc comment such as a docstring or JSDoc block that explains what the code does. A plain inline comment, or one that only gives internal context, does not count, and internal-only code gets no offer. The link goes next to that documentation in one line, such as Walkthrough: <post URL or path>. Do not create a docs file just to hold it.

  • Save the voice profile, when it came from samples, with assets/voice-profile-template.md at a location the user chooses, so the next post can reuse it.

Building the post

The post explains one specific purpose of the code as an informational walkthrough. It contains:

  • A title naming the problem the code solves.

  • A short opening stating what the code does and the single use case covered.

  • The generalized function, method, or tool in one code block.

  • A minimal usage example with cliche sample data and the expected output.

  • A closing note on limits or edge cases, when there is something worth saying.

The implementation and its usage count as one worked example, and can share a block where the language makes that natural. A second, unrelated example, or a walkthrough that needs several files, is out of scope.

The voice profile decides how these parts are worded, ordered, and headed. It never drops a required part and never overrides the security rules.

Apply SEO at the level that fits the destination, per references/seo.md: full for a published blog, light for a plain file or a chat draft with no destination yet, venue for a gist-style page, internal for a documentation set. A level the user asks for, including none, wins. Where the site's own conventions or the author's voice clearly differ from an SEO default (title style, tagging, linking habits), the site and the author win.

Default post layout

Use this layout only where YAML front matter is read as metadata and no site defines its own fields, such as a standalone Markdown file saved at a path the user names, or a platform that accepts front matter on paste:

---
title: <Post title>
description: <One sentence, 140 to 160 characters, leading with what the reader gets>
slug: <lowercase-hyphenated-slug>
category: <domain, such as string-utils or file-io>
tags: [<tag>, <tag>, <tag>]
date: <YYYY-MM-DD>
---

<post body in Markdown>
  • A site's own front matter wins over this layout: map these values onto the fields it already uses and drop any it does not read.

  • A destination that does not parse front matter never gets this block. That covers a gist, a Discussions post, a wiki page, most hosted editors, and a chat draft whose target is still unknown. Use the shape in Venues with no front matter in references/delivery.md instead, which moves the title into the first heading and the description into the opening line.

Security and content rules

These rules apply to everything that goes into a post, whatever the destination or voice.

  1. No credentials or secure data. No API keys, tokens, passwords, secrets, connection strings, private URLs, internal hostnames or IPs, account IDs, environment variable values, file paths that reveal user or machine names, or personal information beyond the public byline rule 6 allows. Replace anything the code needs with an obvious placeholder such as YOUR_API_KEY or https://api.example.com.

  2. Cliche sample data only. For example "Hello, World!", Jane Smith, [email protected], foo / bar / baz, 123 Main St, 42, Acme Corp. When the code needs data the list lacks, such as accented text or a date, choose something equally generic (Café, 2026-01-01), never a value from the working context.

  3. No incidental detail from the working context or the samples. People's names other than the byline, project, client, and internal product names, business terms, internal file names, and values from the conversation stay out, and so does content from the voice samples. Code or a topic the user supplies directly is the subject rather than incidental detail: use it, generalized under rule 4 and held to rule 1.

  4. Rewrite, don't copy. Generalize the code into a clean demonstration: rename project-specific identifiers, strip unrelated logic, and remove internal dependencies.

  5. Paths in samples follow the sample. A PowerShell or batch sample shows Windows paths, a shell sample shows POSIX paths, and a cross-platform sample shows both or a token such as <config-dir>.

  6. Public attribution and public technology keep their real names. When the destination has an author or byline field, fill it with the value the author's existing posts there use, or with the name the user gives. Never take it from elsewhere in the working context, such as git config or a system account. The full draft shows it, so approval covers it. Public languages, frameworks, libraries, and tools the code uses, such as Python, React, or SQLite, are named as they are.

Limitations

  • One post, one purpose, one worked example.

  • A full voice match needs at least three samples. With fewer, the profile is thin or neutral, and the plan check says so.

  • The skill writes files. It does not publish, upload, commit, or push.

Files

references/blog-platforms.md

Blog Platforms

Use this reference when the destination is a blog or site repository. Identify the generator before writing anything. Each one has its own posts folder, file naming rule, and front matter contract, and a post that ignores the contract either fails the build or never appears.

Detecting the generator

Look in the current workspace only.

The Default posts folder column records each generator's convention, not a guarantee. Every one of these projects can move that folder, and several declare it in code rather than in a settings file. Read the column as where to look first, and the project's own configuration as the answer.

Two generators can share a config file name: _config.yml belongs to both Jekyll and Hexo, and config.toml to both Hugo and Zola. That file name alone does not identify the generator. Classify the site only when the row's other marker is also present. When the markers point at more than one generator, ask which one builds the site.

PlatformDetect byDefault posts folderContract to honor
Jekyll_config.yml, confirmed by jekyll or github-pages in the Gemfile, or by a _posts/ folder when package.json does not list hexo_posts/File name must follow YYYY-MM-DD-slug.<markup-extension> (for example, .md or .markdown). Use YAML front matter matching the site's existing posts. A source or collections_dir setting in _config.yml moves the folder.
Hugohugo.toml, hugo.yaml, hugo.json, or a config/_default/ directory. A bare config.toml counts only with a baseURL key (any letter case) or an archetypes/ folder beside itcontent/posts/TOML or YAML front matter matching the theme. draft: true keeps it out of the build. contentDir moves the content root. The section is the top-level folder under it that holds the existing posts. params.mainSections in the site config names it when set, and without that setting Hugo treats the section with the most pages as the main one.
Astroastro.config.*Whatever the content collection declares, commonly src/content/blog/Read the collection config: src/content.config.* on Astro 5, src/content/config.* on Astro 4. A collection's loader chooses the directory, so glob({ base: './src/data/blog' }) puts posts there and not under src/content/. Front matter must satisfy that collection's schema, and a required field left out fails the build.
Eleventy.eleventy.js, eleventy.config.*posts/, or the folder named in the configFront matter plus the directory data file. A tags value adds the post to a collection, which is usually what the feed and index read.
Next.jsnext.config.* with an MDX or content pipelinecontent/, posts/, app/blog/, or wherever the pipeline reads fromMDX rules apply: components must be imported or provided, and a raw < or { in prose breaks the parse.
Gatsbygatsby-config.*content/blog/Front matter fields must exist in the GraphQL schema the templates query. The path given to gatsby-source-filesystem is the folder actually sourced.
Docusaurusdocusaurus.config.*blog/Date from the file name prefix or a date field. <!-- truncate --> marks where the excerpt ends in .md, and {/* truncate */} in .mdx. The blog plugin's path option moves the folder.
Hexo_config.yml plus hexo in package.jsonsource/_posts/YAML front matter. <!-- more --> marks the excerpt break. source_dir in _config.yml moves the source root.
Zolaconfig.toml with a base_url key, a spelling Hugo does not usecontent/TOML front matter fenced by +++, not ---. The post belongs to a section, which is a subfolder of content/ carrying its own _index.md.
VitePress.vitepress/The folder the theme configuresFront matter plus whatever index page lists the posts.

A site found only in a subfolder of an application repository, such as a project website, belongs to that project and is not necessarily the author's blog. Offer it at the plan check instead of assuming it.

Rules for every generator

  • Match a config file by its basename, not by one extension. Every entry written with .* stands for a family, and a project may spell it .js, .mjs, .cjs, .ts, .mts, or .cts. Glob the basename before concluding a generator is absent, because detecting only one spelling misreads a real blog as a plain repository.

  • The project's configuration outranks the table. Open the generator's config before choosing a path. Where a project declares its content in code (an Astro loader, an Eleventy directory setting, a Gatsby filesystem source, a Docusaurus plugin path), that declaration is the destination. It locates the posts and does not define their fields.

  • Resolve a partial name through the config. "Put it in the blog" fixes which project receives the post and leaves the folder open. Settle the folder from the generator's configuration, then echo the full path at the plan check.

  • Read a neighbor first. Open an existing post in the resolved folder and copy its field set exactly. The live posts are more reliable than any general rule here, and they double as voice samples when written by the same author.

  • Settle a disagreement before writing. When the config and the existing posts point at different folders, ask which one is current. When the config names a folder that holds no posts yet, the config wins.

  • Satisfy the schema, then stop. The schema is whatever validates or reads the front matter, and it is separate from the path declaration even where the two sit side by side: an Astro collection's schema, the GraphQL fields a Gatsby template queries, or the fields the Docusaurus blog plugin reads. Where the site declares no schema, the neighbor's field set is the schema. Match it, and do not invent front matter fields the site does not read.

  • Drafts on request. Approval is the gate, so write the post ready to publish. When the user asks for a draft, use the platform's own mechanism: Hugo's draft: true, Jekyll's published: false or its _drafts folder, or the flag the site's schema declares. Do not add a flag the platform ignores.

  • Respect the file naming rule. A date-prefixed name is required on some platforms and wrong on others.

  • Reuse the site's taxonomy. Take tags and categories from the ones the site already uses.

  • Follow the repository's line endings. Match its .gitattributes or its existing posts.

The same rules apply when the user sends the post to a documentation set: match a neighboring doc's front matter and naming, and do not create a new documentation area to hold it.

Requirements and compatibility

Written for: GitHub Copilot, Claude Code

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Claude Code frontmatter, Needs an API key

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

First committed by
GitHub avatar of jhaugajhauga
Publisher
GitHub (Official)
Distributed by
GitHub
Source
github/awesome-copilot · skills/make-blog-post · commit 797337f
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced
Contributors
jhauga

AutoGineer is not affiliated with or endorsed by jhauga or GitHub.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download make-blog-post.zip