What Makes mdsvex Special
A tour of mdsvex features: component imports, reactive state, expressions, and control flow inside Markdown
Published Jul 11, 2026 • Updated Aug 7, 2026
Table of contents
- Script blocks
- Importing and using components
- Inline expressions
- Control flow blocks
- Mixing Markdown and components freely
- Quick note
Script blocks
<script>
import Counter from './Counter.svelte';
import Alert from './Alert.svelte';
// Regular Svelte reactivity works right here in the post
let name = $state('reader');
let greeting = $derived(`Hello, ${name}!`);
const languages = ['Svelte', 'TypeScript', 'Markdown'];
</script> The last post was plain Markdown. This one shows what you get once mdsvex compiles your Markdown as a Svelte component — meaning the <script> block above is real, running Svelte code, not just decoration.
Importing and using components
Because mdsvex treats the file as a .svelte component under the hood, you
can import components at the top and drop them directly into the prose:
That’s a live, interactive counter — click it. Here’s the exact line that rendered it:
<Counter start={5} /> You can pass different props to render another instance:
Inline expressions
Any {expression} in curly braces is evaluated just like in a .svelte file. For example:
- {greeting}
- 2 + 2 is {2 + 2}. - Hello, reader!
- 2 + 2 is 4.
Control flow blocks
Svelte’s {#if}, {#each}, and {#await} blocks work directly in the
Markdown body:
<ul>
{#each languages as lang}
<li>{lang}</li>
{/each}
</ul>
{#if languages.includes('Svelte')}
<Alert type="success">
Yep, Svelte is on the list. 🎉
</Alert>
{:else}
<Alert type="warning">
Svelte isn't on the list — something's wrong.
</Alert>
{/if} - Svelte
- TypeScript
- Markdown
Mixing Markdown and components freely
You can keep writing normal Markdown between components without any special syntax:
mdsvex lets you treat prose and UI as the same medium — no more choosing between “write docs” and “build an interactive demo.”
Quick note
Markdown’s blank-line rules still apply inside {#each} / {#if} blocks,
so if a list or paragraph isn’t rendering the way you expect, check for
missing blank lines around the block — this trips people up more than
anything else when they start mixing Markdown syntax with Svelte syntax.
That covers the core of it: imports, reactive variables, expressions, and
control-flow blocks, all inside a .md (or .svx) file that SvelteKit
treats as a regular route/component.