Color mode

Search notes

Filter with tag:, lang:, or path:.

Plugin Recipes

Writing a Plugin builds one plugin from an empty folder to a working directive. This page is the next step: a set of small recipes for the extension points you are likely to need.

Each recipe is independent. Copy the one you need into extensions/, register it in riebeckite.config.ts, and check the result in the browser or build output. The recipes are task-oriented; the exact contracts are in the Plugin API.

Plugins are trusted application code. When a recipe builds HTML, it escapes untrusted values. When it emits URLs, it validates them for the context. Riebeckite does not sanitize plugin-generated HTML. See the Security model.

Before you start

The recipes assume a site created by create-riebeckite and a local plugin in extensions/. A local plugin does not need its own package.

Start with the smallest possible plugin:

ts
import { definePlugin } from "@riebeckite/core";
 
export function example() {
  return definePlugin({
    name: "example",
  });
}

Register it:

ts
import { defineConfig } from "@riebeckite/core";
import { example } from "./extensions/example";
 
export default defineConfig({
  plugins: [example()],
});

Each recipe defines its own factory. Put it in extensions/ and register it instead of example. The name must be unique across enabled plugins, because it owns the plugin cache and generated output namespace.

Recipe map

What you need Extension point Recipe
Transform Markdown or HTML remarkPlugins, rehypePlugins, pipeline hooks 1
Render an embedded file renderers 2
Read content during the build onConfigResolved, onContentLoaded, onPostParsed, onPostProcessed, onManifestCreated 3
Change public URLs resolveContentLocations, extendContentLocations 4
Add links for the graph and backlinks extendContentGraph 5
Add a standalone page pageTypes 6
Share a UI component package export 7
Add CSS and browser behavior assets, clientEntries 8
Expose JSON or another HTTP response endpoints 9
Change titles, feeds, or structured data seo 10
Report content problems addDiagnostics, inspectGeneratedHtml 11
Reuse derived data across builds cacheVersion, context.cache 12
Write files during the build planGeneratedOutputs, context.output 13
Control order and validate options provides, requires, optional, order, validateOptions 14
Inspect build behavior logger, tracer 15

Check each recipe

Recipe What to check
Transform The expected markup appears in the generated HTML
Renderer ![[data.csv]] shows the preview; a plain link still works
Content hooks The CLI prints the diagnostic with the plugin name
Locations The new URL works and the old URL redirects
Graph The related note appears as a backlink and graph neighbor
Page type /series/typescript is generated and lists the notes
Component The site imports it and renders it where it belongs
CSS and client The stylesheet loads and the button works after the page loads
Endpoint The dev server returns the expected JSON and cache header
SEO The page source, sitemap, and feeds use the new metadata
Diagnostics Warnings appear for the notes you expect
Cache The second build reuses the cache; a content change misses it
Generated files The file exists in the output with the expected content
Dependencies A missing provider fails with a clear error
Logging Debug messages appear only at the debug level

Run npm run build for recipes that affect static output. For browser behavior, use npm run dev and check the console and network panel.

The testing levels in Writing a Plugin apply to every recipe. For framework-level test conventions, see Testing.

Common mistakes

  • Reading manifest.entries for published output. It includes drafts. Use publicEntries or discoverableEntries.
  • Returning an empty string from a renderer for an unsupported target. Return null so another renderer can handle it.
  • Forgetting to escape values from frontmatter, files, or remote responses.
  • Passing secrets through publicConfig. Only that value is sent to the browser.
  • Adding a transform without processedContentCache. The site then cannot reuse processed content.
  • Assuming an endpoint becomes a static file. Use generated outputs for static export.
  • Emitting a planned output without dependencies. The runtime rejects it.
  • Changing a permalink without a redirect. Old links break; add a redirect if the URL was public.
  • Using order to override a capability dependency. Providers always run first.