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.md files 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.

Once you see content through the refrakt lens, plain Markdown starts feeling like it's leaving so much on the table.

Claude OpusAI, Anthropic

Under the hood

A single hint tag flows through five pipeline stages — from the Markdown you type to styled, semantic HTML.

  1. You write Markdown

    Wrap content in a rune tag. The type attribute tells the system this is a warning.

    {% hint type="warning" %}
    Back up your data before proceeding.
    {% /hint %}
    
  2. 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."
    
  3. Rune schema interprets

    The Hint model reads type, emits a hintType meta tag, and wraps content in a body container. The typeof marker carries semantic meaning forward.

    section { typeof: "Hint" }
    ├── meta { property: "hintType", content: "warning" }
    └── div { data-name: "body" }
        └── p "Back up your data before proceeding."
    
  4. 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."
    
  5. 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>
    
warning

Back up your data before proceeding.

See it in action

Every example below is pure Markdown — no custom components, no JSX, no frontmatter gymnastics.

  1. Write Markdown

    Create pages with standard Markdown. Runes wrap your content in semantic contexts — no new syntax to learn.

  2. Add runes

    Pick from 60+ built-in runes for navigation, SEO, pricing tables, API docs, changelogs, and more.

  3. Ship it

    Run npm create refrakt to 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.