create-blog-post
Converts draft markdown files into production-ready blog posts for the Home Assistant website.
Install
mkdir -p .claude/skills/create-blog-post && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/4446" && unzip -o skill.zip -d .claude/skills/create-blog-post && rm skill.zipInstalls to .claude/skills/create-blog-post
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Use this if the user wants to convert a blog post from Google Docs markdown to the format used in the Home Assistant website.Key capabilities
- →Extracts post metadata (author, date, category)
- →Processes hero and content images
- →Converts external links to target-blank HTML
- →Standardizes Jekyll front matter
- →Formats content structure for site publishing
How it works
Parses input files, cleans content of drafting notes, and applies formatting templates to create site-compliant posts.
Inputs & outputs
When to use create-blog-post
- →Publishing new blog posts
- →Converting markdown drafts to site format
- →Standardizing metadata for blog content
About this skill
Create Blog Post
Convert a draft markdown file into a properly formatted Home Assistant blog post.
There are two kinds of blog posts this skill handles:
- Standard blog posts — full content hosted on the Home Assistant website, converted from a Google Docs markdown draft. This is the default path, described in the sections below.
- Externally linked (crosspost) blog posts — a short teaser that redirects readers to an article hosted on another site (for example, the Open Home Foundation blog). If the user asks to "publish a blog that is externally linked", "create a crosspost", "add an external blog post", or similar, follow the Externally linked (crosspost) blog posts section instead.
Usage
Place your draft blog post markdown file in the project root create-blog-post/ directory (e.g., /workspaces/home-assistant.io/create-blog-post/), then run:
/create-blog-post
What This Skill Does
Automates conversion of a draft markdown file with metadata into a production-ready Home Assistant blog post:
- Extracts metadata (blog title, author, publish date, category, Social/OpenGraph fields)
- Removes "# Blog notes/preparations" section and lines with ☝️ emoji
- Converts
### **– Summary break / Read more –**to<!--more--> - Processes hero image and any additional images
- Converts external links to HTML
<a>tags withtarget="_blank" - Formats content (removes bold from headings, fixes link references)
- Creates properly formatted blog post in
source/_posts/with Jekyll front matter
Required Files in create-blog-post/ Directory
- Draft markdown file (any .md filename)
art.*- Hero/OG image (required, any common image format:.webp,.png,.jpg,.jpeg)image2.*,image3.*, etc. - Additional images (optional, any common image format)
Draft File Format
# Metadata
**Blog title:** Your Blog Title
**Author:** Author Name
**Publish date:** DD-MM-YYYY
**Category:** Category Name
**Social/OpenGraph title** (Usually same as the blog title, visibility mostly limited to 50-60 characters)**:**
A short title.
**Social/OpenGraph description** (120-158 characters):
Influences SEO ranking. Include the main keyword, describe what readers will find, and give them a clear reason to click.
# Blog notes/preparations
☝️ Any lines with the pointer emoji can be removed during processing
# Blog content
![][image1]
Your intro paragraph here...
### **– Summary break / Read more –**
Rest of content...
Notes:
- The
![][image1]reference should appear at the start of the "# Blog content" section. This will be replaced with theart.webphero image. - URL slug is optional and will be auto-generated from the blog title if not provided in metadata
- Lines beginning with ☝️ emoji are instructions and will be removed during processing
- The
### **– Summary break / Read more –**marker will be converted to<!--more-->
Output
Creates a production-ready blog post at:
source/_posts/YYYY-MM-DD-slug.markdown- The formatted blog postsource/images/blog/YYYY-MM-slug/art.webp- OG/hero image (moved fromcreate-blog-post/)source/images/blog/YYYY-MM-slug/image2.webp,image3.webp, etc. - Additional images (converted from PNGs)
Conversion Process
1. Pre-process Draft
Before doing anything else, strip out embedded base64 image data from the draft file using a shell command. Do not read the draft file before this step — the base64 data can make the file extremely large.
Google Docs markdown exports include image references like ![][image1] in the content body, with corresponding base64 definitions at the bottom of the file in the format:
[image1]: <data:image/png;base64,iVBORw0KGgo... (potentially megabytes of data)>
Run this sed command via the Bash tool to strip them in-place:
sed -i '/^\[image[0-9]*\]: <data:/d' "create-blog-post/draft.md"
- This removes all lines matching the base64 image definition pattern
- The
![][image1]references in the content body are preserved — they will be replaced with proper image paths later - Only after this command completes should you read the draft file
2. Parse Metadata
- Extract blog title, author, publish date, category (convert to YAML list), Social/OpenGraph title and description
- Auto-generate URL slug from blog title (lowercase, hyphens for spaces, remove special characters)
- Remove "# Blog notes/preparations" section and all content under it (up to "# Blog content")
- Remove all lines that start with ☝️ emoji (instruction lines)
- Convert
### **– Summary break / Read more –**marker to<!--more-->
3. Process Images
Before processing images, ensure the cwebp tool is installed. If not, install it:
# Check if cwebp is available, install if missing
which cwebp || sudo apt-get install -y webp
Hero image (art.*):
- Find the
artimage increate-blog-post/(any extension:.webp,.png,.jpg,.jpeg) - If the source is already
.webp, copy it tosource/images/blog/YYYY-MM-slug/art.webp - If the source is any other format, convert to WebP:
cwebp -resize 1200 630 -q 85 input -o source/images/blog/YYYY-MM-slug/art.webp - The OG image must be exactly 1200x630 pixels — the source image should already be this size, so use
-resize 1200 630to ensure correctness - Replace
![][image1]reference in "# Blog content" section with:<img src="/images/blog/YYYY-MM-slug/art.webp" alt="Blog Title" style="border: 0;box-shadow: none;"> - CRITICAL: Use double quotes for all HTML attributes (prevents breaking on apostrophes in alt text)
- Alt text uses the Social/OpenGraph title or blog title
- No wrapper tags (no
<p>tag)
Additional images (if any):
- Find
image2.*,image3.*, etc. increate-blog-post/(any extension:.webp,.png,.jpg,.jpeg) - Convert to WebP with a max width of 900px:
cwebp -resize 900 0 -q 85 input -o output.webp(the0for height preserves the aspect ratio) - If the source is already
.webp, still re-encode it with the resize:cwebp -resize 900 0 -q 85 input.webp -o output.webp - Output to
source/images/blog/YYYY-MM-slug/image2.webp,image3.webp, etc. - Update references in content
4. Transform Links
External links (different domains/subdomains):
- Convert to:
<a href="URL" target="_blank" rel="noopener">text</a> - Includes:
my.home-assistant.io,partner.home-assistant.io, etc.
Internal links (www.home-assistant.io only):
- Keep as Markdown links:
[text](/path)
5. Device List (Works with Home Assistant posts only)
If the blog post category is Works-with-Home-Assistant, look for a section that lists certified/supported devices. Replace any manually written device list with the dynamic device list shortcode:
{% include integrations/device_list.html brand="brandname" %}
- The
brandvalue must match a brand insource/_data/wwha_devices.json(for example:"eve","heatit","shelly","zooz") - The brand name is typically the lowercase company/brand name from the draft
- If the draft contains a manually listed set of devices (often as a bullet list or table), replace that list with the shortcode
- Keep any introductory or closing text around the device list — only replace the list itself
6. Clean Content
- Headings: Remove bold formatting (
## **Title**→## Title) - Heading levels: If content starts with H1 (
#), demote all headings one level (content should start at H2) - Backticks: Strip erroneous ``` characters (preserve code blocks/inline code)
- Text content: Do not change the author's wording, phrasing, or writing style. The blog text should stay as-is. If you spot obvious typos or locale spelling issues (such as British English instead of American English), do not fix them silently — collect them and ask the user for confirmation before applying any changes.
- Emojis: Preserve all emojis that appear in the blog content. Do not strip them out.
- Apostrophes and quotes: Convert straight apostrophes (
') and speech marks (") in prose — including quoted statements, like in blockquotes — to their curly equivalents (’,“/”). Only apply this to body text — never to HTML attribute values, URLs, code blocks/inline code, or Liquid/Jekyll syntax.
7. Build Blog Post
- Create
source/_posts/YYYY-MM-DD-slug.markdown - Jekyll front matter (layout, title, description, date, date_formatted, author, categories, og_image)
- Hero image (no wrapper)
- Intro paragraph
<!--more-->tag after first paragraph- Remaining content
Example
- Place in project root
create-blog-post/:draft-partner-update.md- Your draft fileart.webp- OG/hero imageimage2.png,image3.png- Additional images (if any)
- Run
/create-blog-post
This would create:
source/_posts/2026-01-13-partner-update.markdownsource/images/blog/2026-01-partner/art.webpsource/images/blog/2026-01-partner/image2.webp,image3.webp(if additional images exist)
Important Notes
Image references:
- Draft:
![][image1](at start of "# Blog content" section) → Output:art.webphero image (1200x630, OG image) - Draft:
![][image2]→ Look forimage2.*(any format), convert toimage2.webp(max 900px wide) - Draft:
![][image3]→ Look forimage3.*(any format), convert toimage3.webp(max 900px wide) - Source images can be any common format (
.webp,.png,.jpg,.jpeg) — all are converted/re-encoded to.webp
Requirements:
- Hero image reference should appear at the start of the "# Blog content" section
cwebptool is required — the skill will auto-install it viasudo apt-get install -y webpif not already present
Content processing:
- Remove "# Blog notes/preparations" section entirely
- Remove all lines starting with ☝️ emoji (instruction lines)
- Convert `
Content truncated.
When not to use it
- →Writing technical documentation (other than blog posts)
- →Non-Jekyll website platforms
Prerequisites
Limitations
- →Requires specific folder organization
- →Limited to Home Assistant website format
How it compares
Automates the entire transformation pipeline from raw draft to production-ready file structure.
Compared to similar skills
create-blog-post side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| create-blog-post (this skill) | 1 | 3mo | Review | Beginner |
| resume-builder | 53 | 3mo | No flags | Beginner |
| write-docs | 6 | 3mo | No flags | Beginner |
| wiki-changelog | 3 | 4mo | No flags | Beginner |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by home-assistant
View all by home-assistant →You might also like
resume-builder
amruthpillai
Generate professional resumes that conform to the Reactive Resume schema. Use when the user wants to create, build, or generate a resume through conversational AI, or asks about resume structure, sections, or content. This skill guides the agent to ask clarifying questions, avoid hallucination, and produce valid JSON output for https://rxresu.me.
write-docs
tldraw
Writing SDK documentation for tldraw. Use when creating new documentation articles, updating existing docs, or when documentation writing guidance is needed. Applies to docs in apps/docs/content/.
wiki-changelog
microsoft
Analyzes git commit history and generates structured changelogs categorized by change type. Use when the user asks about recent changes, wants a changelog, or needs to understand what changed in the repository.
docs-changelog
google-gemini
Provides a step-by-step procedure for generating Gemini CLI changelog files based on github release information.
docs-writer
google-gemini
Always use this skill when the task involves writing, reviewing, or editing files in the `/docs` directory or any `.md` files in the repository.
document-writer
onmax
Use when writing blog posts or documentation markdown files - provides writing style guide (active voice, present tense), content structure patterns, and MDC component usage. Overrides brevity rules for proper grammar. Use nuxt-content for MDC syntax, nuxt-ui for component props.