Plugins

Using and configuring plugins to extend GenGen functionality

GenGen Plugins

GenGen uses a powerful plugin system to extend functionality. Plugins can be configured through your site's configuration file, and you can enable/disable them individually or by groups.

Plugin Configuration

Basic Configuration

Plugins are configured in your config.yaml file under the plugins section:

plugins:
  enabled:
    - core          # Enable the core plugin group
    - seo           # Enable SEO plugins
  disabled:
    - TailwindPlugin  # Disable a specific plugin

Plugin Groups

GenGen organizes plugins into logical groups for easier management:

  • core: Essential plugins for basic functionality

  • seo: Search engine optimization and discoverability plugins

  • assets: Asset processing and compilation plugins

  • content: Content enhancement and organization plugins

Default Configuration

By default, GenGen enables only the core group:

plugins:
  enabled:
    - core

  disabled: []
  groups:
    core:
      - DraftPlugin
      - MarkdownPlugin
      - LiquidPlugin

    seo:
      - RssPlugin
      - SitemapPlugin

    assets:
      - SassPlugin
      - TailwindPlugin

    content:
      - PaginationPlugin
      - AliasPlugin


Configuration Examples

Minimal setup with core plugins only:

{"plugins":{"enabled":["core"]}}

Blog setup with SEO and content plugins:

{"plugins":{"enabled":["core","seo","content"]}}

Full-featured site with all plugin groups:

{"plugins":{"enabled":["core","seo","assets","content"]}}

Custom plugin selection:

{"plugins":{"enabled":["MarkdownPlugin","LiquidPlugin","SassPlugin","RssPlugin"],"disabled":[]}}

Enable groups but disable specific plugins:

{"plugins":{"enabled":["core","assets"],"disabled":["TailwindPlugin"]}}

Safe Mode

Safe mode disables Lua plugins unless they are explicitly allowlisted.

safe: true
safe_plugins:
  - "site-enhancer"
  - "theme-banner"

You can also enable safe mode from the CLI:

gengen build --safe

Plugin Data Files

Plugins can include a _data/ directory inside the plugin folder. These files are merged into site.data at build time. Precedence is: site _data โ†’ theme _data โ†’ plugin _data.

Built-in Plugins

GenGen comes with several built-in plugins that provide core functionality:

Core Plugins

Essential plugins for basic functionality

DraftPlugin

Handles draft posts and pages. Posts with draft: true are excluded unless publish_drafts is enabled.

Default configuration:

publish_drafts:
false

Features:

  • Draft post filtering
  • Development mode support
  • Conditional publishing

MarkdownPlugin

Processes Markdown files and converts them to HTML with CommonMark specification.

Supported file extensions:

  • .md
  • .markdown

Features:

  • GitHub Flavored Markdown
  • Syntax highlighting
  • Table support
  • Task lists
  • Footnotes

LiquidPlugin

Processes Liquid templates for dynamic content generation.

Features:

  • Site data access
  • Template inheritance
  • Custom filters and tags
  • Variable interpolation

Available objects:

  • site: Site-wide data and configuration
  • page: Current page data
  • post: Current post data (for posts)
  • content: Rendered content

SEO Plugins

Search engine optimization and discoverability plugins

RssPlugin

Generates RSS 2.0 compliant XML feeds for your site's posts.

Default configuration:

rss:
{"path":"feed.xml","limit":20,"full_content":false}

Features:

  • RSS 2.0 compliance
  • Automatic post discovery
  • Configurable post limits
  • Full content or excerpt mode
  • Dublin Core metadata
  • Proper XML encoding

SitemapPlugin

Generates XML sitemaps following sitemap.org protocol for better search engine indexing.

Default configuration:

sitemap:
{"path":"sitemap.xml","include_posts":true,"include_pages":true}

Features:

  • Sitemap.org protocol compliance
  • Automatic URL discovery
  • Priority and change frequency settings
  • Excludes draft content
  • SEO-optimized structure

Asset Plugins

Asset processing and compilation plugins

SassPlugin

Compiles Sass/SCSS files to CSS with support for imports, variables, and mixins.

Default configuration:

sass:
{"style":"compressed","source_map":false,"load_paths":["_sass"]}

Features:

  • SCSS and Sass syntax support
  • Import resolution
  • Source maps (optional)
  • Multiple output styles
  • Variable and mixin support

TailwindPlugin

Processes Tailwind CSS for utility-first styling.

Default configuration:

tailwind:
{"executable":"./tailwindcss","input":"assets/css/tailwind.css","output":"assets/css/styles.css"}

Features:

  • Automatic Tailwind compilation
  • Configurable input/output paths
  • Production optimization
  • Custom executable path
  • JIT mode support

Requirements:

  • Tailwind CSS executable

Content Plugins

Content enhancement and organization plugins

PaginationPlugin

Automatically paginates long lists of posts across multiple pages.

Default configuration:

pagination:
{"enabled":true,"per_page":10,"permalink":"/page/:num/","title_suffix":" - Page :num"}

Features:

  • Configurable posts per page
  • Custom permalink structure
  • Navigation helpers
  • SEO-friendly URLs
  • Template variables

AliasPlugin

Creates URL aliases and redirects for pages and posts.

Features:

  • Multiple aliases per page
  • Automatic redirect generation
  • SEO-friendly redirects
  • Link equity maintenance
  • Migration support

Usage: Add aliases: array to front matter

Plugin Management Commands

GenGen provides a command-line interface for managing plugins:

# 
gengen plugins

# --available
gengen plugins --available

# --enabled
gengen plugins --enabled

# --groups
gengen plugins --groups

Configuration Examples

Here are some common configuration patterns:

Basic Site Configuration

Minimal configuration for a simple site

title: "My Site"
url: "https://example.com"

plugins:
  enabled:
    - core

Blog Site Configuration

Configuration for a blog with SEO features

title: "My Blog"
url: "https://blog.example.com"
description: "A blog about interesting topics"

plugins:
  enabled:
    - core
    - seo
    - content

# RSS configuration
rss:
  path: feed.xml
  limit: 20
  full_content: false

# Pagination
pagination:
  enabled: true
  per_page: 5
  permalink: "/page/:num/"

Portfolio Site Configuration

Configuration for a portfolio with custom styling

title: "John Doe - Portfolio"
url: "https://johndoe.dev"
description: "Web developer and designer"

plugins:
  enabled:
    - core
    - assets
    - seo

# Sass configuration
sass:
  style: compressed
  source_map: false

# Tailwind configuration
tailwind:
  executable: "./tailwindcss"
  input: "assets/css/tailwind.css"
  output: "assets/css/styles.css"

Complete configuration with all plugin groups enabled

title: "Complete Site"
url: "https://complete.example.com"
description: "A fully-featured GenGen site"

plugins:
  enabled:
    - core
    - seo
    - assets
    - content

# Individual plugin configurations
rss:
  path: feed.xml
  limit: 25
  full_content: true

sitemap:
  path: sitemap.xml
  include_posts: true
  include_pages: true

sass:
  style: compressed
  source_map: true
  load_paths: ["_sass", "node_modules"]

tailwind:
  executable: "./node_modules/.bin/tailwindcss"
  input: "assets/css/tailwind.css"
  output: "assets/css/styles.css"

pagination:
  enabled: true
  per_page: 8
  permalink: "/blog/page/:num/"
  title_suffix: " - Page :num"

# Draft publishing for development
publish_drafts: false

Custom Plugin Selection

Selective plugin configuration without groups

title: "Custom Site"
url: "https://custom.example.com"

plugins:
  enabled:
    - MarkdownPlugin
    - LiquidPlugin
    - SassPlugin
    - RssPlugin
    - PaginationPlugin
  disabled: []

Development Configuration

Configuration optimized for development

title: "Dev Site"
url: "http://localhost:4000"

plugins:
  enabled:
    - core
    - assets

# Development settings
publish_drafts: true

sass:
  style: expanded
  source_map: true

# Disable external dependencies in development
plugins:
  disabled:
    - TailwindPlugin

Production Configuration

Optimized configuration for production deployment

title: "Production Site"
url: "https://mysite.com"

plugins:
  enabled:
    - core
    - seo
    - assets
    - content

# Production optimizations
sass:
  style: compressed
  source_map: false

rss:
  path: feed.xml
  limit: 20
  full_content: false

sitemap:
  path: sitemap.xml
  include_posts: true
  include_pages: true

pagination:
  enabled: true
  per_page: 10
  permalink: "/page/:num/"

Writing Custom Plugins

GenGen custom plugins are Lua-based and auto-discovered. Each plugin lives in its own directory with a config.yaml and a Lua entrypoint.

Legacy Dart-based plugins are still discovered but will log warnings during load. New plugins should use Lua.

Where plugins live

GenGen loads plugins from two locations:

  • Site plugins: /_plugins//
  • Theme plugins: /_themes//_plugins//

You can customize the site plugins folder with plugin_dir in config.yaml (default: _plugins).

Plugin directory structure

_plugins/
  my-plugin/
    config.yaml
    main.lua
    assets/
      banner.css

_themes/
  default/
    _plugins/
      theme-banner/
        config.yaml
        main.lua
        theme.css

Plugin config reference

Name Description

name

Required. Plugin identifier used in asset URLs; typically matches the plugin folder name.

entrypoint

Required. Lua entrypoint in "file.lua:init_function" format.

description

Optional description shown in docs or tooling.

author

Optional author name.

authorUrl

Optional author URL.

version

Optional version string.

license

Optional license identifier.

url

Optional homepage URL.

files

Optional explicit asset list. Each entry has name/path; path can be a glob. If omitted, GenGen scans the plugin directory. Non-Lua files are copied to /assets/plugins/.

Example with explicit files:

name: site-enhancer
entrypoint: main.lua:init_plugin
description: Adds a callout and writes extra output.
files:
  - name: styles
    path: "assets/*.css"
  - name: banner
    path: "images/banner.png"

If files is omitted, GenGen scans the plugin directory and registers all files. Non-Lua files are copied to /assets/plugins//.

Quick start: site plugin

_plugins/my-plugin/config.yaml:

name: my-plugin
entrypoint: main.lua:init_plugin
description: A custom plugin for GenGen
author: Your Name
version: 1.0.0

_plugins/my-plugin/main.lua:

function init_plugin(metadata)
  return {
    head_injection = '',

    css_assets = { 'assets/styles.css' },

    convert = function(content, page)
      return '
Injected by Lua
\n' .. content end, after_generate = function() gengen.content.write_site('assets/my-plugin.txt', 'Generated by my-plugin') end } end

Quick start: theme plugin

_themes/default/_plugins/theme-banner/config.yaml:

name: theme-banner
entrypoint: main.lua:init_plugin
description: Theme-level badge and CSS.

_themes/default/_plugins/theme-banner/main.lua:

function init_plugin(metadata)
  return {
    css_assets = { 'theme.css' },
    body_injection = '
Theme plugin active
' } end

Lua hook reference

All hook names are snake_case. Missing hooks are treated as no-ops.

Lifecycle hooks

Name Description

after_init

Called once after the plugin is initialized.

before_read

Called before content is read.

after_read

Called after content is read.

before_generate

Called before generators run.

generate

Called during generation.

after_generate

Called after generators finish.

before_render

Called before rendering.

after_render

Called after rendering.

before_write

Called before writing files.

after_write

Called after writing files.

before_convert

Called before convert hooks run.

after_convert

Called after convert hooks run.

Convert hook

Name Description

convert(content, page) -> string

Called for each document. Must return a string. Returning nil or non-strings throws a plugin error.

Asset and head hooks

Name Description

head_injection

String or function returning a string injected into .

body_injection

String or function returning a string injected before .

css_assets

List or function returning a list of CSS asset paths relative to the plugin directory.

js_assets

List or function returning a list of JS asset paths relative to the plugin directory.

meta_tags

Map or function returning a map of meta tag name/value pairs.

Asset paths are relative to the plugin directory and are served at /assets/plugins//.

Liquid filters

Name Description

liquid_filters

Map or function returning a map of Liquid filter functions keyed by filter name.

Filters receive (value, args, named_args) and return the transformed value.

liquid_filters = {
  shout = function(value, args, named)
    return string.upper(tostring(value))
  end
}

Page object in convert

The page argument is a plain Lua table derived from the internal document model.

Name Description

name

Source name relative to the site root.

relativePath

Path relative to collections root for posts/collections, or site source for pages.

filePath

Absolute file path.

ext

File extension including the dot.

isPost

True for posts.

isCollection

True for collection documents.

collection

Collection label (posts, pages, or custom collection name).

output

True when the document is written to destination.

isDraft

True for drafts.

isStatic

True for static files.

isAsset

True for asset-like content (for example Sass).

isPage

True for pages.

permalink

Resolved output permalink.

frontMatter

Raw front matter map.

config

Merged config (site + dir + front matter + defaults).

Lua standard library (gengen table)

GenGen exposes a standard library inside Lua plugins:

Logging

Name Description

gengen.log.debug(message)

Debug log entry.

gengen.log.info(message)

Info log entry.

gengen.log.warn(message)

Warning log entry.

gengen.log.error(message)

Error log entry.

Configuration

Name Description

gengen.config.get(key, default)

Read site configuration with optional default.

Paths

Name Description

gengen.paths.plugin(relative)

Resolve a path inside the plugin folder.

gengen.paths.plugin_root()

Absolute plugin root path.

gengen.paths.site_source(relative)

Resolve a path in the site source.

gengen.paths.site_destination(relative)

Resolve a path in the site destination.

gengen.paths.join(...parts)

Join path segments.

gengen.paths.basename(path)

Basename of a path.

gengen.paths.dirname(path)

Directory name of a path.

Content

Name Description

gengen.content.read_plugin(path)

Read a file from the plugin directory.

gengen.content.read_site(path)

Read a file from the site source.

gengen.content.write_site(path, content)

Write a file to the site destination.

gengen.content.exists_plugin(path)

Check if a plugin file exists.

gengen.content.exists_site(path)

Check if a site file exists.

Utilities

Name Description

gengen.util.slugify(value)

Slugify a string.

gengen.util.contains_markdown(value)

Return true if the string contains markdown markers.

gengen.util.excerpt(html, maxLength)

Extract a plain-text excerpt from HTML (default maxLength 200).

gengen.util.parse_date(dateString, format)

Parse a date string and return ISO string.

Plugin metadata

Name Description

gengen.plugin.metadata

Plugin metadata map (name, version, author, path, and more).

gengen.plugin.name

Plugin name.

gengen.plugin.version

Plugin version.

gengen.plugin.description

Plugin description.

gengen.plugin.author

Plugin author.

gengen.plugin.path

Plugin root path.

Execution order

Plugins run in discovery order: site plugins first, then theme plugins. Conversion hooks run after Liquid renders content and before layout rendering.

Template Integration

To enable automatic asset injection in your templates:




    Plugins
    
    


    
    
    
    


injects `head_injection`, CSS assets, and meta tags from plugins. injects body_injection and JavaScript assets.

Best Practices

  1. Use plugin groups: Organize related plugins into logical groups
  2. Start with core: Always enable at least the core plugin group
  3. Test configurations: Verify your plugin configuration works as expected
  4. Monitor performance: Some plugins may impact build times
  5. Keep plugins updated: Ensure custom plugins work with GenGen updates
  6. Document dependencies: Clearly document any external tool requirements

Troubleshooting

Common Issues

Plugin not loading:

  • Check that the plugin name is spelled correctly
  • Verify the plugin is in the enabled list or group
  • Ensure the plugin isn't in the disabled list

Build errors:

  • Check plugin configuration syntax
  • Verify external tool dependencies (e.g., Tailwind CSS executable)
  • Review plugin-specific configuration options

Performance issues:

  • Disable unnecessary plugins
  • Check for plugin conflicts
  • Monitor build times with different plugin combinations

Debug Commands

# Check current plugin status
gengen plugins

# Build with verbose logging
gengen build --verbose

# Check site configuration
gengen dump

Contributing Plugins

When contributing plugins to GenGen:

  1. Follow the established plugin structure
  2. Include comprehensive documentation
  3. Add appropriate tests
  4. Consider plugin groups and categorization
  5. Ensure compatibility with existing plugins

Conclusion

GenGen's plugin system provides powerful extensibility while maintaining simplicity through configuration-based management. Whether you're using built-in plugins or developing custom ones, the system is designed to be flexible and developer-friendly.