cd /news/ai-tools/structured-markdown-components-witho… · home topics ai-tools article
[ARTICLE · art-24925] src=contentbit.dev pub= topic=ai-tools verified=true sentiment=· neutral

Structured Markdown components without framework lock-in

Contentbit launched a new open-source library that lets developers write structured, validated Markdown components without being locked into a specific JavaScript framework. The tool uses directive blocks inside ordinary Markdown, which are parsed into a source-mapped AST and validated against schemas before rendering in React, static HTML, or plain Markdown. This approach aims to solve content portability and validation issues for human writers, CMSes, and LLMs generating structured content.

read3 min publishedJun 12, 2026

Write Markdown with validated, structured blocks. Render it anywhere. Built for content written by humans, CMSes, and LLMs.

$ pnpm dlx contentbit@latest init

or see a complete article rendered by the library

01·The idea

Markdown in, components out #

Authors write directive blocks inside ordinary Markdown. The parser builds a source-mapped AST, the registry validates it, and your renderer of choice takes it from there. Below: the actual styled pack rendering live.

:::key-metrics- 65% | Hydration- 24h | Cold ferment- 250g | Ball weight- 450°C | Oven temp::: :::tabs::tab{title="Stand mixer"}Dough hook, speed 2, eight minutes. Stop when the dough **clears the bowl**.::tab{title="By hand"}Fold every 30 minutes, four times. Slower, same gluten.::: :::comparison{left="Fresh yeast" right="Instant"}- Amount | 9g | 3g- Where to buy | Bakeries | Everywhere- Flavor | Slightly richer | Neutral::: :::callout{type="tip" title="Same source, every target"}This panel is the real React pack. Prose runs through [react-markdown](https://github.com/remarkjs/react-markdown), exactly like your app would wire it.:::

Dough hook, speed 2, eight minutes. Stop when the dough clears the bowl.

Fresh yeast Instant
Amount 9g 3g
Where to buy Bakeries Everywhere
Flavor Slightly richer Neutral

02·The safety net

Errors with line numbers, not broken pages #

Validation runs before rendering: in your editor, your CI, or your agent loop. Diagnostics carry a code, a position, and a fix hint, so an LLM can repair its own output.

:::comparison{left="Basic"}
- Price | Free
:::
broken.md:1:1 error CB_PROPS_INVALIDcomparison: prop "right" Invalid input: expected string, received undefinedbroken.md:2:1 error CB_ROW_COLUMNS:::comparison rows require 3 columns (label | left | right). Found 2.hint: Format: - label | left | rightbroken.md:1:1 error CB_ROW_COUNT:::comparison needs at least 2 rows, found 0.

03·The system

One definition, every surface #

No framework lock-in

The content is a protocol. Renderers are adapters: React and static HTML today, plain Markdown always.

- Price | Free
- Price | Free | $12/mo

Validation before render

Every block has a schema. Bad content fails with file:line:col diagnostics, not broken pages.

## Dough basics

Weigh everything. Volume
measures drift by 20%.

:::callout{type="tip"}
Cold ferment for flavor.
:::

Still just Markdown

Documents stay readable in any text editor. Strip the renderer and the content still makes sense.

↳ generated from the registry

Made for generated content

The registry that validates content also writes the authoring instructions for LLMs, so prompts never drift from the rules.

components/
└─ content-blocks/
   └─ tabs-block.tsx ← yours now

shadcn distribution

Styled components install as editable source files through a shadcn registry. You own them after install.

const pricingTable = defineBlock({
  name: 'pricing-table',
  props: z.object({ currency: z.enum(['usd', 'eur']) }),
  content: pipeRows({ columns: ['plan', 'price'] }),
  authoring: { useWhen: [...], example },
})

Extensible registry

A custom block is a name, a zod props schema, a content model, and authoring guidance, in under 20 lines. It validates, renders, and documents itself from that one definition.

04·The generic pack

Eight blocks that work in any niche #

Pick a block. The example is its real authoring guidance from the registry, the same text LLMs get, rendered live by the styled pack.

All blocks →

:::callout{type="tip" title="Worth knowing"}Always weigh flour — volume measures drift by 20%.:::

Use when: Practical advice that prevents a common mistake (tip)

Highlighted note, tip, warning, important, or TLDR box.

05·Styled pack

Install the components, own the code #

The React pack ships through a shadcn registry. Components land in your app as editable source files: Tailwind, your tokens, your rules.

$ pnpm dlx shadcn@latest add @contentbit/generic-pack

registry: https://contentbit.dev/r/{name}.json

── more in #ai-tools 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/structured-markdown-…] indexed:0 read:3min 2026-06-12 ·