Plugin Structure and Metadata

Every plugin is a pair of files in its own directory: a compiled WASM component and a TOML manifest that tells Accent CMS what the plugin can do. This page covers the directory layout and every section of the plugin.toml file.

Plugin Directory Structure

Plugins live in site/plugins/, with each plugin in its own subdirectory:

site/
  plugins/
    syntax-highlight/
      plugin.toml          # Metadata (required)
      plugin.wasm          # Compiled WASM module (required)
    contact-form/
      plugin.toml
      plugin.wasm
    search/
      plugin.toml
      plugin.wasm

Each plugin directory must contain both files:

  • plugin.toml - Declares the plugin’s name, version, and capabilities
  • plugin.wasm - The compiled WebAssembly component built with a Component-Model toolchain (cargo-component or jco)

If either file is missing, the plugin is skipped with a warning. Invalid plugins do not prevent the server from starting.

Plugin Metadata (plugin.toml)

The plugin.toml file declares what a plugin can do. Here is a complete example:

[plugin]
name = "syntax-highlight"
version = "0.1.0"
api_version = "0.1.0"
description = "Syntax highlighting for code blocks"

[hooks]
on_render = true             # Called after markdown-to-HTML rendering
on_page_load = false         # Called before markdown processing
on_media_discover = false    # Called during content scanning for media files
on_media_process = false     # Called after image processing

[filters]
# filter_name = "exported_function_name"
highlight = "apply_highlight"
lang_name = "get_language_name"

[shortcodes]
# List of shortcode names this plugin handles
codes = ["code", "highlight"]

[routes]
# path = "HTTP method"
"/api/highlight" = "POST"
"/api/languages" = "GET"

[config]
# Plugin-specific settings (read via the config capability)
theme = "monokai"
line_numbers = true

Required Fields

The [plugin] section is required:

FieldTypeDescription
namestringUnique plugin identifier (used as registry key)
versionstringSemantic version of the plugin
api_versionstringHost API version the plugin targets (checked against the host’s supported range; see Security)
descriptionstringHuman-readable description (optional)
requires_fsboolRequest scoped WASI filesystem access (optional, default: false)
allowed_hostsarrayHosts the plugin may reach over outbound HTTP (optional; see Security)
host_servicesarrayHost services the plugin may call through the typed host-services capability: "mail", "data" (optional; see Security)

Hooks

The [hooks] section declares which lifecycle hooks the plugin listens to:

HookWhen it firesInputOutput
on_page_loadBefore markdown processingRaw markdownModified markdown
on_renderAfter HTML renderingRendered HTMLModified HTML
on_media_discoverDuring content scanningFile path, MIME typeMetadata key-value pairs
on_media_processAfter image processingRaw image bytes, dimensionsModified bytes, metadata

Multiple plugins can register for the same hook. They are called in the order they were loaded.

The on_media_discover and on_media_process hooks are described in detail in the Media Hooks section.

Filters

The [filters] section declares the template filter names the plugin provides:

[filters]
highlight = "apply"    # {{ code | highlight("rust") }}
uppercase = "apply"    # {{ text | uppercase }}

The key is the filter name used in templates. The host dispatches every filter to the component’s single apply export, keyed on the filter name, so the value is simply that export.

Shortcodes

The [shortcodes] section lists shortcode names the plugin handles. Shortcodes are inline content components that authors embed in markdown using square-bracket notation (see Shortcodes for syntax details).

[shortcodes]
codes = ["note", "warning", "gallery"]

When Accent CMS encounters [note]...[/note] or [gallery/] in content, it calls the plugin’s render export from the shortcodes interface. The plugin receives the shortcode name, attributes, and optional body as typed values and returns rendered HTML.

Plugin shortcodes are checked after built-in and theme shortcodes in the resolution chain. This means a theme can override a plugin shortcode by providing a template with the same name in its shortcodes/ directory.

Routes

The [routes] section registers custom HTTP endpoints:

[routes]
"/api/search" = "GET"
"/api/contact" = "POST"

Plugin Configuration

The [config] section holds plugin-specific settings. A plugin reads them at runtime through the config capability (config::get(key) / config::get_all()); they merge under any overrides from plugins.config in config.yaml:

[config]
theme = "monokai"
line_numbers = true
max_results = 50

A minimal plugin.toml only needs the [plugin] section:

[plugin]
name = "my-plugin"
version = "0.1.0"
api_version = "0.1.0"