Getting started
One command to set up Content Blocks — then your coding agent writes validated content.
Content Blocks is a framework-agnostic block layer for Markdown — the contract between whatever writes your content (you, a CMS, a coding agent) and whatever renders it. Authors write Markdown with directive-style blocks; every block has a schema, validation runs before anything renders, and every example on this site is rendered live by the library it documents:
:::comparison{left="Basic" right="Pro"}
- Price | Free | $12/mo
- Support | Community | Priority
:::| Basic | Pro | |
|---|---|---|
| Price | Free | $12/mo |
| Support | Community | Priority |
The shortest path from install to publishable content is two steps: run init,
then ask your coding agent to write.
1. One command
pnpm dlx contentbit@latest initnpx contentbit@latest initbunx contentbit@latest inityarn dlx contentbit@latest initIt detects your framework and package manager, asks two questions (or none with
-y), and leaves you with everything wired:
That's packages for your render target, a custom-block registry, a starter
document with a rendered /example page, a content:check validate script,
LLM authoring instructions, and the coding-agent integration
(skip it with --no-agents).
2. Ask your agent
Your coding agent now knows how to write content for this project. Try:
write a blog post about our new dark mode
audit my content
The installed contentbit-author skill runs the loop a careful human would:
fetch the live authoring guide, write, validate, fix every diagnostic until the
validator exits 0.
content/dark-mode.md:18:1 error CB_ROW_COLUMNS:::comparison rows require 3 columns (label | left | right). Found 2.hint: Format: - label | left | right1 file(s): 0 errors, 0 warningsThis is reliable because the skills contain no schemas. They read everything
from the CLI at runtime (the authoring guide, the diagnostics, the stats), so
when you add a custom block, every agent picks it up on the next run with
nothing to regenerate. Works beyond Claude Code too: AGENTS.md carries the
same instructions for Cursor, Codex, Copilot, and friends.
The validation contract
What makes the loop converge is the diagnostic format. Invalid content never renders; it produces errors a machine can act on:
content.md:12:3 error CB_ROW_COLUMNS
:::comparison rows require 3 columns (label | left | right). Found 2.
hint: Format: - label | left | rightEach diagnostic carries the exact source position, a stable code, and a fix
hint, so your agent (or your CI) can act on it. The same gate runs in the
editor loop, in pnpm run content:check, and before every render.
Under the hood
Prefer wiring things up manually? Install the pieces directly:
pnpm add @contentbit/core @contentbit/blocks
pnpm add @contentbit/html # static HTML strings
pnpm add @contentbit/react # React components
pnpm add @contentbit/astro # .astro componentsThe whole pipeline is three calls — parse to a source-mapped AST, validate against the registry, render through the adapter of your choice:
import { createBlockRegistry, parseDocument, validateDocument } from '@contentbit/core'
import { genericBlocks } from '@contentbit/blocks'
import { renderToHtml } from '@contentbit/html'
const registry = createBlockRegistry().use(genericBlocks())
const result = validateDocument(parseDocument(markdown), registry)
if (!result.ok) {
console.error(result.diagnostics) // code, severity, message, exact position
}
const html = renderToHtml(result.document)In React, ContentBlocks ships headless, accessible defaults for every generic
block:
import { ContentBlocks } from '@contentbit/react'
export function Article({ document }: { document: DocumentNode }) {
return <ContentBlocks document={document} renderMarkdown={(md) => <Markdown source={md} />} />
}One thing not to skip: Content Blocks parses blocks only — prose and block
bodies are handed to a renderMarkdown function you provide (react-markdown,
marked, markdown-it, remark…). Without it, **bold** renders as literal
characters. Step-by-step wiring for each library:
Plug in your Markdown library.
And if headless isn't your thing, a polished Tailwind-styled pack installs through the shadcn registry — components land as editable source files you own:
pnpm dlx shadcn@latest add @contentbit/generic-packNext steps
- Coding-agent integration — what
initinstalled, and how to wire other agents - Plug in your Markdown library
- Learn the block syntax
- Define custom blocks
- Document stats & auditing — rank what needs attention across your content
- Render with Astro
- Browse the block reference and the changelog