Render documents
Render a validated contentbit document in React, Astro, or plain Markdown.
Renderers consume a validated document. Parse and validate first, then hand the result to the target that matches your app:
import { genericBlocks } from '@contentbit/blocks'
import { assertValidDocument, compileDocument, createBlockRegistry } from '@contentbit/core'
const registry = createBlockRegistry().use(genericBlocks())
const document = assertValidDocument(compileDocument(markdown, registry), 'article.md')For the design behind this split, see Rendering model.
React
import { ContentBlocks } from '@contentbit/react'
<ContentBlocks
document={document}
components={{ comparison: MyComparison }}
renderMarkdown={(md) => <Markdown source={md} />}
fallback={MyInvalidBlock}
/>@contentbit/react renders Markdown segments through renderMarkdown, calls
your block components by name, and uses fallback for invalid or unregistered
blocks in development surfaces.
For pre-made components, install the shadcn pack. The files land in your app and are yours to edit:
pnpm dlx shadcn@latest add @contentbit/generic-packAstro
---
import { ContentBlocks } from '@contentbit/astro/components'
import QuoteBlock from '../blocks/QuoteBlock.astro'
---
<ContentBlocks
document={document}
components={{ quote: QuoteBlock }}
renderMarkdown={renderMarkdown}
onInvalid="annotated"
/>Per-block overrides are plain .astro components: validated props arrive as
component props, nested content via <slot />, and the raw AST node as the
reserved node prop. They also receive ctx, currently { renderMarkdown },
so Markdown strings inside node.data can use the same site pipeline as normal
prose. The onInvalid default is annotated, which keeps invalid blocks loud
during dev. Full guide: Astro.
For pre-made Astro components:
pnpm dlx shadcn@latest add @contentbit/astro-packPlain Markdown fallback
import { renderToMarkdown } from '@contentbit/core'
import { genericMarkdownRenderers } from '@contentbit/blocks'
const md = renderToMarkdown(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, so information is not lost.
Markdown prose
React and Astro renderers both need a Markdown prose function. Wire that once with Plug in your Markdown library, then reuse it for paragraphs between blocks and Markdown bodies inside blocks.