Integrating Comark with Astro
How it works
Instead of using Astro's built-in remark/rehype pipeline, we use Comark's framework-agnostic API:
- Define collections — Use
glob()loader to load.mdfiles with Zod-validated frontmatter - Get the body — Access the raw Markdown via
entry.body - Parse with Comark — Call
parse()to build the AST - Render to HTML — Call
renderHTML()with custom component renderers
import { parse } from 'comark'
import { renderHTML } from '@comark/html'
const tree = await parse(entry.body)
const html = await renderHTML(tree, {
components: {
alert: ([tag, attrs, ...children], { render }) => {
return `<div class="alert">${render(children)}</div>`
},
},
})parse() and renderHTML() are called at build time — zero JavaScript is sent to the client.Custom components
You can register any number of custom components. Each one receives the Comark AST element and a render helper to process children:
const badge: ComponentRenderFn = ([tag, attrs, ...children], { render }) => {
const color = attrs.color || 'blue'
return `<span class="badge badge-${color}">${render(children)}</span>`
}This makes it easy to extend your Markdown with reusable, styled components.
title: Integrating Comark with Astro description: How the Comark + Astro integration works under the hood. pubDate: 2026-01-10 tags: comark, astro, integration
This example uses Astro's content collections with Comark as the Markdown renderer.
How it works
Instead of using Astro's built-in remark/rehype pipeline, we use Comark's framework-agnostic API:
- Define collections — Use
glob()loader to load.mdfiles with Zod-validated frontmatter - Get the body — Access the raw Markdown via
entry.body - Parse with Comark — Call
parse()to build the AST - Render to HTML — Call
renderHTML()with custom component renderers
import { parse } from 'comark'
import { renderHTML } from '@comark/html'
const tree = await parse(entry.body)
const html = await renderHTML(tree, {
components: {
alert: ([tag, attrs, ...children], { render }) => {
return `<div class="alert">${render(children)}</div>`
},
},
})parse() and renderHTML() are called at build time — zero JavaScript is sent to the client.Custom components
You can register any number of custom components. Each one receives the Comark AST element and a render helper to process children:
const badge: ComponentRenderFn = ([tag, attrs, ...children], { render }) => {
const color = attrs.color || 'blue'
return `<span class="badge badge-${color}">${render(children)}</span>`
}This makes it easy to extend your Markdown with reusable, styled components.
