Renderers
Static HTML, React, and plain-Markdown output from the same document.
Renderers consume a validated document. The parser and registry know nothing about React or HTML — every renderer is an adapter with a per-block renderer map you can override.
Static HTML
import { renderToHtml } from '@contentbit/html'
const html = renderToHtml(result.document, {
classPrefix: 'cb-', // default
renderMarkdown: (md) => myMarkdownPipeline(md),
onInvalid: 'fallback',
})- classPrefix — every emitted class is prefixed (
cb-callout,cb-comparison). - renderMarkdown — plug your Markdown pipeline for prose segments and Markdown bodies. The built-in default only escapes and wraps paragraphs. Step-by-step setups for marked, markdown-it, and remark: Plug in your Markdown library.
- renderers — merge custom block renderers over the generic defaults.
All user content is escaped. Tabs render as static sections and FAQs as native
<details>, so the output works without any JavaScript.
Error modes
onInvalid controls what happens to blocks that failed validation:
strict— throw. Use in CI and for repository-owned content.annotated— render a visible box withdata-cb-invalid. Use in development.fallback(default) — render the escaped raw body. Use in production for user- or CMS-supplied content.
React
import { ContentBlocks } from '@contentbit/react'
<ContentBlocks
document={result.document}
components={{ comparison: MyComparison }} // override any default
renderMarkdown={(md) => <Markdown source={md} />}
fallback={MyInvalidBlock}
/>The headless defaults cover every generic block with accessible semantics: tabs use
tablist/tab/tabpanel with keyboard-reachable buttons, FAQs use native
<details>. Interactivity is opt-in per block — only tabs carries client state.
For styled components, install the shadcn pack instead of writing your own:
pnpm dlx shadcn@latest add @contentbit/generic-packPlain Markdown fallback
import { renderToMarkdown } from '@contentbit/core'
import { genericMarkdownRenderers } from '@contentbit/blocks'
const md = renderToMarkdown(result.document, { renderers: genericMarkdownRenderers })Comparisons become Markdown tables, key metrics become bold-value bullets, tabs become headed sections. Useful for email, exports, search indexing, and any environment without a component runtime. Blocks without a renderer degrade to their raw body — information is never lost.