Krate Docs

Plugin System

Krate's plugin system is a single, unified interface with 7 lifecycle hooks. Built-in plugins are written in Go; community plugins are JavaScript modules executed inside the embedded QuickJS runtime — no subprocess, no stdin/stdout protocol.

The plugin interface

type Plugin interface {
    Name() string
    Order() int                    // Lower runs first (default: 50)
    Hooks() PluginHooks
}

type PluginHooks struct {
    BeforeBuild        func(ctx *BuildHookCtx) error
    AfterParse         func(ctx *ParseHookCtx) error
    AfterMarkdownParse func(ctx *MarkdownHookCtx) error
    AfterRender        func(ctx *RenderHookCtx) error
    GenerateRoutes     func(ctx *BuildHookCtx) ([]Route, error)
    AfterPage          func(ctx *PageHookCtx) error
    AfterBuild         func(ctx *BuildResultHookCtx) error
}

The 7 lifecycle hooks

HookWhenMutable Context
BeforeBuildBefore any pages are builtRoot, Config
AfterParseAfter a page is parsed (AST available)AST, Source
AfterMarkdownParseAfter markdown/MDX is parsedHTML, Frontmatter
AfterRenderAfter SSR renderingHTML, HeadHTML, Signals, Handlers
GenerateRoutesGenerate virtual pagesRoutes
AfterPageAfter a page is fully builtHTML, Route
AfterBuildAfter all pages are builtResults, Manifest

Config usage (typed)

import { defineConfig, sitemap, docs } from '@krate/core';
import demoPlugin from './plugins/krate-plugin-demo';

export default defineConfig({
  plugins: [
    sitemap({ baseUrl: "https://example.com" }),
    docs({ contentDir: "content/docs", title: "Docs" }),
    demoPlugin({ greeting: "Hello!" }),
  ],
});

Each factory returns a serializable descriptor: { name, order, options } (built-ins) or { name, order, module, options } (community plugins).

Community plugin protocol

Community plugins are JavaScript modules executed inside the embedded QuickJS runtime (modernc.org/quickjs). The module is bundled with esbuild into a self-contained IIFE and its hooks are called directly from Go.

// plugins/my-plugin/index.js
export const hooks = {
  BeforeBuild(ctx, options, krate) {
    return { files: [{ path: "note.txt", content: "hi" }] };
  },
  AfterRender(ctx, options, krate) {
    return {
      html: "<b>" + ctx.html,
      headHTML: "<meta ...>",
      rawCSS: ".x{}",
    };
  },
};

export default function myPlugin(options) {
  return {
    name: "my-plugin",
    order: 20,
    module: typeof import.meta !== "undefined" && import.meta.url ? import.meta.url : "",
    options: options || {},
  };
}
  • Hook signature — every hook receives (ctx, options, krate) where ctx is the JSON-serialized hook context (lowercase fields like ctx.html, ctx.page, ctx.outName, ctx.headHTML, ctx.rawCSS) and krate is { root, outDir, version }.
  • Return value — hooks return { files, routes, generatedPages, html, headHTML, rawCSS } (all optional; may be a Promise). files are written into the output directory (path traversal is rejected), routes become static HTML pages, generatedPages feed the page pipeline, and html/headHTML/ rawCSS mutate the hook context.
  • Runtime capabilities — bundled plugins can use import fs from 'fs' / import path from 'path' (polyfilled) plus Web API polyfills (fetch, URL, Headers, Response, TextEncoder, timers, process.env). Non-relative third-party imports are left external and unavailable.

Built-in plugins

PluginPurpose
sitemapGenerates sitemap.xml
icons<Icon> → Iconify SVG with disk cache
imageprocessing<Image> → responsive <picture> with srcset
markdownMarkdown/MDX compilation
cspContent Security Policy meta tag
docsDocumentation site generator with WASM search

See Guides: Create a Plugin and the demo plugin in the examples for a full walkthrough.