Write Markdown. Get structure.
A content framework built on Markdoc. Extend Markdown with 60+ semantic runes — tags that transform standard Markdown into structured, SEO-rich, machine-readable content.
npm create refrakt
Why refrakt.md?
- Built on Markdoc
- Not another Markdown dialect. refrakt.md extends Markdoc with semantic runes that add meaning to the Markdown you already write. Everything Markdoc does, you keep.
- Runes, not components
- Runes reinterpret the Markdown inside them. A heading inside
{% nav %}becomes a group title. A list inside{% cta %}becomes action buttons. You write Markdown — the rune decides what it means. - SEO from the start
- Every rune can emit Schema.org JSON-LD and Open Graph metadata automatically. Recipes get Recipe schema, events get Event schema, FAQs get FAQ schema — no manual wiring.
- AI-powered authoring
- Generate full pages with
refrakt write. The CLI knows every rune and produces valid Markdown with proper rune structure. Supports Claude and local models via Ollama. - Layout inheritance
- Define regions in
_layout.mdfiles that cascade down directory trees. Headers, navigation, and sidebars compose automatically — no config files needed. - Portable content
- Runes transform at the Markdoc level, producing a generic tag tree. Your content stays decoupled from presentation — currently rendering with Svelte, with more frameworks planned.
Claude OpusAI, AnthropicOnce you see content through the refrakt lens, plain Markdown starts feeling like it's leaving so much on the table.
Under the hood
A single hint tag flows through five pipeline stages — from the Markdown you type to styled, semantic HTML.
You write Markdown
Wrap content in a rune tag. The
typeattribute tells the system this is a warning.{% hint type="warning" %} Back up your data before proceeding. {% /hint %}Markdoc parses it
Markdoc turns your text into an abstract syntax tree — a structured representation of every tag, heading, and paragraph.
Document └── Tag(hint) { type: "warning" } └── Paragraph └── "Back up your data before proceeding."Rune schema interprets
The Hint model reads
type, emits ahintTypemeta tag, and wraps content in a body container. Thetypeofmarker carries semantic meaning forward.section { typeof: "Hint" } ├── meta { property: "hintType", content: "warning" } └── div { data-name: "body" } └── p "Back up your data before proceeding."Theme engine styles
The identity transform reads the meta tag, injects a header with icon and title, adds BEM classes, and strips the consumed metadata.
section.rf-hint.rf-hint--warning ├── div.rf-hint__header │ ├── span.rf-hint__icon │ └── span.rf-hint__title "warning" └── div.rf-hint__body └── p "Back up your data before proceeding."Renderer outputs HTML
The framework renderer walks the styled tree and produces clean, semantic HTML.
<section class="rf-hint rf-hint--warning"> <div class="rf-hint__header"> <span class="rf-hint__icon"></span> <span class="rf-hint__title">warning</span> </div> <div class="rf-hint__body"> <p>Back up your data before proceeding.</p> </div> </section>
Back up your data before proceeding.
See it in action
Every example below is pure Markdown — no custom components, no JSX, no frontmatter gymnastics.
Write Markdown
Create pages with standard Markdown. Runes wrap your content in semantic contexts — no new syntax to learn.
Add runes
Pick from 60+ built-in runes for navigation, SEO, pricing tables, API docs, changelogs, and more.
Ship it
Run
npm create refraktto scaffold a project. Deploy anywhere SvelteKit runs — Vercel, Netlify, or self-hosted.
Ready to get started?
Scaffold a project in seconds and start writing content with runes.