---
title: 'MdSvex'
slug: mdsvex
description: 'Enable Markdown support in Mochi pages with mdsvex and rehype/remark plugins.'
---
## MdSvex
Experimental — `markdown` and `mochi-framework/highlight` APIs may change.
Markdown support is opt-in. Install `mdsvex` and any rehype/remark plugins you
want, then inject them through `Mochi.serve({ markdown: ... })`.
```sh
bun add mdsvex@^0.12 rehype-slug@^6
```
Mochi is tested against `mdsvex ^0.12` and `rehype-slug ^6`. Other rehype/remark
plugins follow their own version ranges — install whichever your pipeline needs.
```ts
// src/index.ts
import { Mochi } from 'mochi-framework';
import { compile as mdsvexCompile } from 'mdsvex';
import rehypeSlug from 'rehype-slug';
import { routes } from './routes';
await Mochi.serve({
markdown: {
compile: mdsvexCompile,
rehypePlugins: [rehypeSlug],
},
routes,
});
```
With `markdown` configured, `.md` and `.svx` files compile through the supplied
pipeline and can be used anywhere a `.svelte` component is accepted — including
as a `Mochi.page()` route target:
```ts
// src/routes.ts
import { Mochi } from 'mochi-framework';
export const routes = {
'/about': Mochi.page('./src/about.md'),
};
```
Markdown can embed Svelte syntax — a top-level `
# Hello, {name}
This page was rendered at {new Date().toISOString()}.
```
The `markdown` config accepts a full plugin chain — anything compatible with
mdsvex's `rehypePlugins` and `remarkPlugins` works:
```ts
import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
markdown: {
compile: mdsvexCompile,
rehypePlugins: [rehypeSlug, rehypeAutolinkHeadings],
remarkPlugins: [],
}
```
### Syntax highlighting
Fenced code blocks are passed through unchanged unless you supply
`markdown.highlight.highlighter`. Install a highlighting engine (Shiki,
highlight.js, Prism, etc.) and build a highlighter with the framework's
`createHighlighter` factory — it adds the code-block wrapper, copy button,
and Svelte-brace escape around the engine's output.
```sh
bun add shiki
```
```ts
// src/lib/highlightCode.ts
import { createHighlighter as createShiki } from 'shiki';
import { createHighlighter } from 'mochi-framework/highlight';
const shiki = await createShiki({
themes: ['vitesse-dark'],
langs: ['typescript', 'bash'],
});
export const highlightCode = createHighlighter((code, lang) => shiki.codeToHtml(code, { lang, theme: 'vitesse-dark' }));
```
```ts
// src/index.ts
import { highlightCode } from './lib/highlightCode';
markdown: {
compile: mdsvexCompile,
highlight: { highlighter: (code, lang) => highlightCode(code, lang) },
}
```
`highlightCode` is also usable directly in pages and components for
snippets outside the markdown pipeline.
`createHighlighter` accepts any `(code, lang) => string | Promise`
function, so you can plug in highlight.js, Prism, or a custom engine the
same way.
### Islands in markdown
`mochi:hydrate`, `mochi:hydrate:visible`, `mochi:defer`, and `mochi:defer:visible` all work on
components instantiated inside a `.md` / `.svx` file. Import the component
as a default import from the markdown's top-level `
```
Omitting the `markdown` config disables `.md`/`.svx` handling entirely —
importing one then surfaces as a "no loader" error from Bun's bundler. Your
`svelte.config.js` `compilerOptions` still apply to compiled markdown. See
[Svelte config](/docs/svelte-config/).