Content validation
The validate-content script that checks frontmatter completeness, slug hygiene, and required fields before publishing.
Before publishing, scripts/validate-content.mjs runs a set of checks across all content files. It’s invoked by the /publish skill as a pre-flight step.
What it checks
- Required fields present:
title,date,maturity,tags - Maturity is a known value: one of
draft,developing,solid,complete - Slug hygiene: filename is lowercase, hyphenated, no spaces or special characters
- Description length: warns if description is absent or too short (under 30 characters)
- AI field: warns if
aiis not set (all published posts should declare their AI involvement) - Date format: validates that
dateis a parseable ISO date - Draft flag: checks that posts being published don’t have
draft: true
Output
The script prints a report to stdout. Errors (missing required fields, invalid values) fail the process with a non-zero exit code. Warnings (missing description, missing AI field) are printed but don’t fail.
✓ articles/my-post.md
⚠ seeds/rough-idea.md — description missing
✗ field-notes/broken.md — maturity "in-progress" is not a valid value
Where it runs
- Manually:
node scripts/validate-content.mjs - Via
/publishskill: runs before OG image generation and git push - The skill aborts if validation fails with errors
Why not rely on Zod alone
Astro’s Zod schema validation runs at build time and will fail the build if required fields are missing. The validate script is a faster, earlier check — it runs in under a second without starting the full Astro build. It also surfaces warnings (like missing descriptions) that Zod doesn’t cover because those fields are optional in the schema.
Adding new checks
The script uses a simple array of check functions. Each check receives the parsed frontmatter and filename, and returns { type: 'error' | 'warn' | 'ok', message: string }.