Customizing Markdown
How zfb renders Markdown and how to configure or extend the pipeline.
zfb’s Markdown pipeline lives in the zfb-content Rust crate. It parses
each file, runs a chain of visitors (Core always-on, plus any Opt-in
features you enable), highlights code blocks server-side with syntect,
and hands each entry back as both a raw body string and a
ready-to-render Content component.
For the full list of what the pipeline provides — Core features that are
always on, Opt-in features you enable in zfb.config.ts, and how to add
your own visitors in-tree — see the
Markdown Features category.
Rendering Markdown in a page
The standard pattern is to receive a content entry through paths() and
render its Content component:
import { getCollection } from "zfb/content";
export async function paths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
export default function PostPage({ post }) {
return (
<article className="prose">
<post.Content />
</article>
);
}
entry.Content is the JSX component zfb compiles from your Markdown. It
renders MDX-aware output including syntect-highlighted code blocks and any
custom directives you have registered. If you only need the raw markdown
source (for example, to compute a summary or feed an RSS generator), reach
for entry.body instead.
Extension points
The plugins: [] field in zfb.config is the build-orchestration plugin
system. Each registered plugin exposes three optional hooks — preBuild,
postBuild, and devMiddleware — for tasks like emitting extra files
alongside the build, running post-build verification, or adding routes to
the dev server. Plugins do not participate in Markdown rendering: the
parse and visitor chain run inside the Rust engine and never call back into
npm-installed plugins.
Markdown-pipeline customisation lives in-tree as MdastVisitor /
HastVisitor implementations on the engine side. See
Extending the Markdown Pipeline.
💡 Tip
When in doubt, render the body and style it. Most “I want to customize Markdown” requests turn out to be styling questions that CSS solves.
See also
- Markdown Features — full catalog of Core and Opt-in features.
- Custom Directives — register new
directive names against the
DirectiveRegistry, no Rust required. - Extending the Markdown Pipeline — write a Rust visitor and wire it into the engine.