Plugins

refrakt.md separates its rune library into focused packages. Core runes (grid, hint, tabs, nav, datatable, etc.) are available in every project without any additional installation. Domain-specific runes — marketing, storytelling, API documentation, and more — are distributed as plugins that you install as needed.

Official Packages

PackagePurposeFeatures
@refrakt-md/marketingLanding pages and conversion content8 runes
@refrakt-md/docsTechnical API documentation3 runes
@refrakt-md/designDesign system documentation7 runes, cross-page token pipeline
@refrakt-md/learningEducational and instructional content2 runes, SEO rich snippets
@refrakt-md/storytellingFiction, world-building, and narrative7 runes
@refrakt-md/businessOrganizational and team content3 runes
@refrakt-md/placesEvents, maps, and travel3 runes
@refrakt-md/mediaMusic and audio content3 runes
@refrakt-md/planSpec-driven project planning9 runes, 8 CLI commands, cross-page pipeline

Installing Packages

Install one or more packages with npm:

npm install @refrakt-md/marketing @refrakt-md/docs

Then register them in refrakt.config.json:

{
  "contentDir": "./content",
  "theme": "@refrakt-md/lumina",
  "target": "svelte",
  "plugins": [
    "@refrakt-md/marketing",
    "@refrakt-md/docs"
  ]
}

That's it. The Vite plugin loads the packages at build time, merges their rune schemas and theme configs, and makes their tags available in all your content files.

Configuration Options

packages

An array of npm package names to load. Packages are loaded in order; later entries take precedence when resolving name conflicts (see prefer below).

{
  "plugins": ["@refrakt-md/marketing", "@refrakt-md/storytelling"]
}

runes.prefer

When two packages define a rune with the same name, use prefer to specify which package wins. Use "__core__" to force the built-in core rune to take precedence.

{
  "plugins": ["@my-org/custom", "@refrakt-md/marketing"],
  "runes": {
    "prefer": {
      "hero": "@my-org/custom",
      "hint": "__core__"
    }
  }
}

runes.aliases

Create additional tag names that resolve to an existing rune. Useful for site-specific shorthand or migrating from a previous tag name.

{
  "runes": {
    "aliases": {
      "callout": "hint",
      "note": "hint"
    }
  }
}

runes.local

Load rune implementations from local files without publishing to npm. Paths are resolved relative to refrakt.config.json.

{
  "runes": {
    "local": {
      "game-item": "./src/runes/game-item.ts",
      "game-spell": "./src/runes/game-spell.ts"
    }
  }
}

Local runes take highest priority over any installed package runes of the same name. They are ideal for project-specific runes or runes under active development.

How Packages Work

Each plugin exports a Plugin object containing:

  • Rune schemas — Markdoc transforms that define how the tag is parsed and what it outputs
  • Theme config — BEM block names, modifiers, and structural config for the identity transform
  • Icons — SVG icon groups used by the package's runes
  • Pipeline hooks (optional) — Build-time hooks for cross-page indexing and enrichment
  • CLI plugins (optional) — Additional CLI commands (e.g., refrakt plan from @refrakt-md/plan)

The Vite plugin merges all packages together before each build, resolving collisions and assembling the final rune set that the content pipeline uses. Packages that provide CLI commands register them automatically when the package is installed.

See Building a Custom Plugin for details on authoring your own packages, and Cross-Page Pipeline for packages that need to build site-wide indexes.