Plugin Structure and Metadata

Every plugin is a pair of files in its own directory: a compiled WASM module 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 module built with an Extism PDK

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 (passed to the plugin as JSON)
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 WASI filesystem access (optional, default: false)

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 processingBase64 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 maps template filter names to exported WASM function names:

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

The key is the filter name used in templates; the value is the function exported by the WASM module.

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 handle_shortcode exported WASM function. The plugin receives the shortcode name, arguments, and body content as JSON 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. These values are passed to the plugin as JSON when its functions are called:

[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"