← Back to blog

Building This Blog with mdsvex

SvelteKitmdsvexMarkdown

I wanted a blog that I could write in plain Markdown, keep under version control, and ship as static HTML — no database, no CMS, no runtime fetching. Here is how this very page is built.

Why mdsvex

mdsvex is a Markdown preprocessor for Svelte. Each .md file becomes a Svelte component, and its YAML frontmatter is exported as a metadata object. That means I get:

  • Posts authored in Markdown, living in src/posts/
  • Typed frontmatter (title, description, date, tags)
  • Full prerendering — every post is a static file at build time

The frontmatter

Every post starts with a small block of metadata:

---
title: 'Building This Blog with mdsvex'
description: 'How this site turns Markdown into prerendered posts.'
date: '2026-06-10'
tags: ['SvelteKit', 'mdsvex']
published: true
---

A single helper globs every file and sorts them by date:

const files = import.meta.glob('/src/posts/*.md', { eager: true });

export const posts = Object.entries(files)
  .map(([path, mod]) => ({
    slug: path.split('/').pop().replace('.md', ''),
    meta: mod.metadata,
    Component: mod.default
  }))
  .sort((a, b) => +new Date(b.meta.date) - +new Date(a.meta.date));

The whole index is derived from the filesystem. To publish, I drop a new .md file in src/posts/ — the listing, the route, and the sitemap all pick it up automatically.

What you get for free

Because each post is a real Svelte component, styling is just Tailwind’s prose class, and the content is indexed by search engines as static HTML. No client-side hydration is needed to read it.

That is the entire setup. Simple, fast, and easy to maintain.