Create blog posts — from a topic (writes content) or with provided content (scaffolding). Use proactively when creating new blog posts or articles.
Instalação
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Create blog posts — from a topic (writes content) or with provided content (scaffolding). Use proactively when creating new blog posts or articles.
disable-model-invocation
false
allowed-tools
Read, Write, Edit, Glob, Grep, Bash
model
sonnet
argument-hint
[topic, brief, or content]
tier
2
intent
create
max-files
6
max-loc
1200
Skill: Add Blog Post
Objective
Create multilingual blog posts (currently English + Spanish) for XergioAleX.com using Astro Content Collections. Supports two modes:
Topic mode: Given a topic or brief, writes the full article with personal-professional voice and narrative structure.
Content mode: Given pre-written content, scaffolds the post files with proper frontmatter and multilingual versions.
The skill auto-detects the mode based on the inputs provided.
Mandatory Invocation Policy (CRITICAL)
This skill is the mandatory workflow for creating new blog posts in this repository.
All AI agents and assistants MUST use /add-blog-post when creating new posts in src/content/blog/.
Do NOT create new blog posts manually unless the user explicitly requests bypassing the skill.
Always produce both language files (currently EN + ES) in the same task.
If creation starts outside this skill, stop and switch to /add-blog-post before writing files.
Non-Goals
Does NOT modify the Content Collections schema
Does NOT create new tags (uses existing tags from src/content/tags/)
Does NOT modify existing posts (use content-writer agent for rewrites, doc-edit for minor edits)
Does NOT create pages (use add-page skill)
Does NOT download or optimize images (use /optimize-image skill or pnpm run images:optimize)
Does NOT create interactive Svelte components
Tier Classification
Tier: 2 - Standard
Reasoning: Writing quality multilingual articles requires moderate reasoning for tone calibration, narrative structure, and natural translation. Content mode (scaffolding) is simpler but shares the same multilingual creation flow.
Inputs
Mode Detection
If provided
Mode
What happens
$TOPIC (no $CONTENT)
Topic mode
Researches, plans, and writes the article from scratch
$CONTENT (with $TITLE)
Content mode
Scaffolds files using the provided content
Both $TOPIC and $CONTENT
Content mode
Uses provided content, topic as context
Parameters
$TOPIC: Article topic, brief, or description (required for topic mode)
$TITLE: Post title (required for content mode, auto-generated in topic mode)
$DESCRIPTION: Post excerpt/description (required for content mode, auto-generated in topic mode)
$CONTENT: Pre-written post content in markdown (triggers content mode)
$TAGS: Array of tag names — both primary and secondary in one array (must exist in src/content/tags/)
$HERO_IMAGE: Hero image path (from public/). If the image contains text, provide a language-specific variant for ES (see Multilingual Hero Images)
$SLUG: Custom slug (default: kebab-case of title)
$LANG: Primary language, en or es (default: en). The other language version will be translated.
$PUB_DATE: Publication date in YYYY-MM-DD format (default: today's date). Scheduled posts: If set to a future date, the post will be hidden from production builds but visible in dev with an amber "Scheduled" badge. See Blog Posts — Scheduled Posts.
updatedDate: When the author asks to "mark that the post was updated on <date>" (ES: "pon que se actualizó el blog post en <fecha>"), set updatedDate: '<date>' — it renders an "Updated/Actualizado {date}" badge in the header. Set the same value in BOTH locales; must be on/after pubDate. See BLOG_POSTS.md — Marking a Post as Updated.
heroLayout:banner for landscape, side-by-side for square, minimal for secondary, none for text-only
Image path:/images/blog/posts/{slug}/hero.{ext} (ES variant: hero-es.{ext} when image has localized text)
Tags (unified array): All tags go in a single tags array. The tier (primary / secondary / subtopic) is resolved at build time from the tags collection — NOT by position in the array.
Primary tags (1-3 per post): tech, personal, talks, trading, portfolio, dailybot (do NOT use demo — that tag is only for demo posts in _demo/ folders).
Caps: per post — 1-3 primary, 0-10 secondary, 0-15 subtopic. At least 1 primary required. No fixed total cap — but only tag what the post genuinely covers (no tagging for the sake of tagging).
When to use a subtopic tag: the post is FOCUSED on that specific technology/framework/product (not just mentions it in passing). If you're unsure whether a candidate qualifies, run /audit-taxonomy to see the data.
tags: ["tech", "mobile", "kotlin"] — primary + secondary + subtopic (mobile post focused on Kotlin).
Full taxonomy reference: see Tag Taxonomy in BLOG_POSTS.md for the complete tier table, governance, and visual rendering rules.
Series (optional): If the post belongs to a series, add series: "{series-slug}" and seriesOrder: {n}. Available series are defined in src/content/series/. The SeriesNavigation panel and SeriesIndicator floating button render automatically — no component imports or page changes needed.
Series workflow (when adding to an existing series):
Check available series: ls src/content/series/
Read the series file to confirm the slug: cat src/content/series/{slug}.md
Find existing posts in the series: grep -r 'series: "{slug}"' src/content/blog/en/ to determine the next seriesOrder value
Add both series and seriesOrder to frontmatter in BOTH en/ and es/ versions
The SeriesNavigation (TOC + prev/next links) and SeriesIndicator (floating chapter progress button) appear automatically at build time
Creating a NEW series: Create src/content/series/{slug}.md with name, title, description, order fields. Then add the series fields to each post's frontmatter.
Author (optional): If the post belongs to an author other than the default, add author: "{author-slug}" to the frontmatter. Available authors are YAML files in src/content/authors/. When omitted, the post defaults to sergio-florez. Both EN and ES versions of a post must use the same author slug — authorship doesn't translate. The AuthorCard renders automatically at the end of the post and pulls localized role and bio from the author's YAML.
Author workflow (when adding a new author):
Create src/content/authors/{slug}.yaml with name, slug, avatar, role.{en,es}, bio.{en,es}, and optional social (x, linkedin, github, instagram, website)
Add the avatar at public/images/authors/{slug}.webp (WebP, ~160x160 px)
Reference the slug in author: on both EN and ES versions of the post
Posts are published (visible in production and dev)
Files in _demo/ folder: demo posts (accessible only by direct URL in local dev mode, never in production or listings)
Steps
Step 1: Analyze Input and Research
Determine mode (topic vs content) based on inputs provided
Check existing articles in src/content/blog/en/ for voice reference and to avoid overlap
Read demo posts in src/content/blog/en/_demo/ as structural references — these are example articles showcasing different hero layouts (banner, side-by-side, minimal, none), MDX features, rich markdown formatting, and code syntax highlighting. Use them as templates when deciding article structure and formatting.
Check available tags in src/content/tags/ — note which are tier: primary and which are tier: secondary
Assign tags: Choose 1-3 primary tags (section) + 0-10 secondary tags (topic) + 0-15 subtopic tags (specific tech). At least 1 primary is required. Put all in a single tags array. Add every tag the post genuinely covers, but never tag for the sake of tagging.
Verify any referenced images exist in public/images/blog/posts/ or public/images/blog/shared/
Topic mode only: Identify the core story or angle. If the brief is too vague, stop and ask for clarification.
# Check existing articlesls src/content/blog/en/
# Check available tagsls src/content/tags/
# Verify image assets if referencedls public/images/blog/posts/ public/images/blog/shared/ 2>/dev/null
Step 2: Generate Slug and Plan Structure
Convert title to kebab-case for the slug (or use provided $SLUG)
Ensure uniqueness among existing posts
File naming:YYYY-MM-DD_{slug}.md (use pubDate as date prefix)
Determine frontmatter values including heroLayout based on image aspect ratio
Topic mode only — plan article structure:
Opening hook — Personal, relatable opening (2-3 paragraphs). Series posts: DO NOT open with a mechanical recap of all previous chapters (e.g., "In chapter one I did X. In chapter two I did Y. In chapter three I did Z."). This pattern becomes robotic and impersonal as the series grows. Instead: open with the new chapter's own hook, and weave in references to prior chapters only when directly relevant — a single link, a short phrase, or an inline mention. The series navigation already shows readers the full chapter list; the opening should feel like a conversation, not an index.
Context/Why — Why this matters, why the author did it
Core content — Main story, breakdown, or explanation (3-6 sections)
Visual elements — Place images, tables, code blocks where they add value
Closing — Brief, forward-looking ("Let's keep building." / "A seguir construyendo."). Series posts: Do NOT create a "Bridge to Chapter N" or teaser section at the end that previews the next chapter. Each chapter should stand on its own — end with a satisfying conclusion, not a cliffhanger or preview. The series navigation already shows readers what comes next.
Resources — Links to repos, tools, docs, external references (when applicable). Do NOT list related articles or previous chapters — if the post belongs to a series, those already appear in the series navigation below; listing them in Resources is redundant.
Series independence principle: Each post in a series should read well on its own. Avoid explicit "In chapter N..." references. Instead: weave in context naturally with inline links, or simply state the fact without referencing which chapter covered it. A reader who lands on chapter 5 from a search engine should not feel lost.
Verify the image folder exists: public/images/blog/posts/{slug}/
Use path /images/blog/posts/{slug}/hero.{ext} in frontmatter
Multilingual hero: If the hero image contains text that needs localization, ask the user for a language-specific variant. Save as hero-es.{ext} in the same folder, generate WebP, and use the variant path in the ES frontmatter
Topic mode — voice rules:
First person (I, my, me) — the author is Sergio (XergioAleX)
Conversational and personal — like explaining to a friend
No marketing language, no empty superlatives
Specific details over vague claims
Honest reflections — what worked, what didn't, what was learned
Formatting rules:
Use --- horizontal rules between major sections
Use ## for section headings, ### for subsections
Wrap transparent PNG/SVG images in dark background containers:
Captions must be short (one line), additive (never repeat alt text), and exist in both EN and ES.
Markdown template:
---
title: 'Post Title Here'
description: 'A brief description of what this post is about.'
pubDate: '2026-01-31'
heroImage: '/images/blog/posts/post-title-here/hero.jpg'
heroLayout: 'banner'
tags: ['tech', 'web-development', 'javascript']
keywords: ['specific search phrase 1', 'long-tail keyword phrase 2', 'technology name tutorial', 'how to do X with Y', 'comparison A vs B']
# author: 'sergio-florez' # Optional — slug from src/content/authors/. Defaults to 'sergio-florez'# series: 'series-slug' # Optional — must match a slug in src/content/series/# seriesOrder: 1 # Required when series is set — positive integer, unique within the series# draft: true # Optional — hides post from production
---
## Introduction
Content starts here...
Note: Primary (tech) and secondary (web-development, javascript) tags go in one tags array. Tier is determined by the tags collection, not by position.
MANDATORY: Every blog post must have 5-8 SEO keywords per language version.
Keywords ≠ Tags. Tags are categorical labels from a controlled taxonomy (tech, web-development). Keywords are specific search phrases users type into search engines (replace ESLint with Biome, Biome linter setup).
Keyword generation rules:
5-8 keywords per post — mix of short-tail (1-2 words) and long-tail (3-6 words)
Think like a searcher — what would someone type into Google to find this content?
Include the main technology/topic in at least 2-3 keywords
No generic keywords — every keyword must be specific to the post content
Keywords complement tags — don't repeat tag names as keywords
English keywords: Natural English search phrases.
Spanish keywords: Adapted to Spanish search behavior (NOT literal translations):
heroImage: Use the same path as EN by default. If a hero-es.{ext} variant exists, use it in the ES frontmatter
Adapt idioms and expressions to sound natural
Keywords: Generate language-specific keywords (adapted, not translated) — see Step 4
Use informal-professional register (tuteo: tú/tienes/puedes)
CRITICAL — No voseo: NEVER use Argentine/Rioplatense voseo forms (vos, tenés, podés, sabés, querés, hacés, buscás, necesitás, decís, etc.). Always use tuteo: tienes, puedes, sabes, quieres, haces, buscas, necesitas, dices. The tone is personal but professional — tuteo, not voseo.
When translating to Spanish, prefer Colombian Spanish phrasing
Do NOT translate code blocks, CLI commands, technical terms, product names
Direct quotes in English: When the Spanish version includes a direct quote originally spoken/written in English, keep the original English text in italics and add a Spanish translation in parentheses immediately after. Example: "Express my will to my agents." ("Expresar mi voluntad a mis agentes.")
CRITICAL — Spanish orthography: ALL Spanish text MUST use correct diacritical marks (ñ, á, é, í, ó, ú). Never write pequeno (→ pequeño), tamano (→ tamaño), analisis (→ análisis), numero (→ número), codigo (→ código), pagina (→ página), etc. Verify before saving.
Step 6: Validate
pnpm run build
Verify:
Both files exist with matching frontmatter structure
All image paths reference existing files
Tags reference existing tag definitions
Both language versions have keywords array with 5-8 entries
Spanish keywords have correct diacritical marks
/add-blog-post workflow was used for creation (no manual bypass)
Output Format
Success Output
## Blog Post Created (Multilingual)
### Files Created
- English: `src/content/blog/en/YYYY-MM-DD_{slug}.md` -> URL: `/blog/{slug}/`
- Spanish: `src/content/blog/es/YYYY-MM-DD_{slug}.md` -> URL: `/es/blog/{slug}/`
### Details
- **Title (EN):** {title}
- **Title (ES):** {title_es}
- **Mode:** {topic|content}
- **Tags:** {tags}
- **Date:** {pubDate}
- **Hero:** {heroImage or "none"} ({heroLayout})
### Build: Passing
### Commit Message
content: add blog post "{title}" (en + es)
Guardrails
Scope Limits
Maximum files: 6 (2 article files + up to 4 supporting assets)
Maximum LOC: 1200 (combined EN + ES, ~600 per language)
Do NOT list related articles or previous chapters in Resources when the post belongs to a series — the SeriesNavigation panel already shows the full TOC below the content.
All referenced images exist (including ES hero variant if applicable)
Tags are valid (exist in src/content/tags/)
Frontmatter matches the Content Collections schema
No placeholder content — never leave [AUTHOR: ...], [TODO: ...], [TBD], or similar in published posts. Replace with real content or remove the section.
Multilingual Enforcement
MUST create all language versions. Never create a post in only one language. See src/lib/i18n.ts for active languages.
If translation quality is uncertain, use /translate-sync skill after creating the primary version.
Stop Conditions
Stop and ask if:
Topic is too vague to write an authentic personal article (topic mode)
Need to create a new tag
Article would require more than 600 lines combined
Post requires custom components not available
Article conflicts with or heavily overlaps existing content
Translation quality is uncertain for specialized content
Definition of Done
Post created in src/content/blog/en/ (English version)
Post created in src/content/blog/es/ (Spanish version)
Both versions have matching frontmatter structure
Translated title and description are natural and accurate
Voice is personal-professional, not marketing copy (topic mode)
Spanish reads naturally (not machine-translated)
Spanish uses tuteo (tú), NOT voseo (vos) — no tenés, podés, sabés, querés, etc.
Spanish text has correct diacritical marks (ñ, accents — no pequeno, tamano, numero, codigo)
Both EN and ES versions have keywords array (5-8 natural search phrases per post)
ES keywords adapted to Spanish search behavior (not literal translations)
No placeholder content ([AUTHOR:, [TODO:, [TBD], [FIXME] — zero in final post)
All referenced images exist
pnpm run build passes
Escalation Conditions
Escalate to a higher tier (or ask user) if:
Article requires new Content Collections schema fields
Topic requires creating new page templates or components
Multiple articles need to be created as a NEW series (plan with architect first). Adding a single post to an existing series is fine — just set series and seriesOrder in frontmatter.
Article requires custom interactive elements (Svelte islands)
Examples
Example 1: Topic Mode — Portfolio Article
Input:
$TOPIC: Portfolio article about my XergioAleX personal branding. Ninja coder logo designed by Koru.
$TAG: portfolio
$PUB_DATE: 2020-12-31
$HERO_IMAGE: /images/blog/posts/personal-branding-xergioalex/hero.jpg
Creates:
src/content/blog/en/2020-12-31_personal-branding-xergioalex.md (written from scratch)
Policy: Keep only the 3 most recent entries. When adding a new entry, remove the oldest.
Version
Date
Changes
3.0.0
2026-03-08
SEO keywords: added Step 4 for keyword generation (5-8 per post, both EN/ES). Keywords are search phrases distinct from tags. Updated frontmatter template, Definition of Done, and validation.
2.9.0
2026-03-03
Scheduled posts: documented that future $PUB_DATE creates a scheduled post (hidden in prod, amber badge in dev). Updated lifecycle references.
2.8.0
2026-03-03
No placeholder content: never leave [AUTHOR:], [TODO:], [TBD], [FIXME] in published posts. Added to Safety Checks and Definition of Done.