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 configurationpage: Current page datapost: 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"
Full-Featured Site Configuration
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 |
|---|---|
|
Required. Plugin identifier used in asset URLs; typically matches the plugin folder name. |
|
Required. Lua entrypoint in "file.lua:init_function" format. |
|
Optional description shown in docs or tooling. |
|
Optional author name. |
|
Optional author URL. |
|
Optional version string. |
|
Optional license identifier. |
|
Optional homepage URL. |
|
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 |
|---|---|
|
Called once after the plugin is initialized. |
|
Called before content is read. |
|
Called after content is read. |
|
Called before generators run. |
|
Called during generation. |
|
Called after generators finish. |
|
Called before rendering. |
|
Called after rendering. |
|
Called before writing files. |
|
Called after writing files. |
|
Called before convert hooks run. |
|
Called after convert hooks run. |
Convert hook
| Name | Description |
|---|---|
|
Called for each document. Must return a string. Returning nil or non-strings throws a plugin error. |
Asset and head hooks
| Name | Description |
|---|---|
|
String or function returning a string injected into . |
|
String or function returning a string injected before . |
|
List or function returning a list of CSS asset paths relative to the plugin directory. |
|
List or function returning a list of JS asset paths relative to the plugin directory. |
|
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 |
|---|---|
|
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 |
|---|---|
|
Source name relative to the site root. |
|
Path relative to collections root for posts/collections, or site source for pages. |
|
Absolute file path. |
|
File extension including the dot. |
|
True for posts. |
|
True for collection documents. |
|
Collection label (posts, pages, or custom collection name). |
|
True when the document is written to destination. |
|
True for drafts. |
|
True for static files. |
|
True for asset-like content (for example Sass). |
|
True for pages. |
|
Resolved output permalink. |
|
Raw front matter map. |
|
Merged config (site + dir + front matter + defaults). |
Lua standard library (gengen table)
GenGen exposes a standard library inside Lua plugins:
Logging
| Name | Description |
|---|---|
|
Debug log entry. |
|
Info log entry. |
|
Warning log entry. |
|
Error log entry. |
Configuration
| Name | Description |
|---|---|
|
Read site configuration with optional default. |
Paths
| Name | Description |
|---|---|
|
Resolve a path inside the plugin folder. |
|
Absolute plugin root path. |
|
Resolve a path in the site source. |
|
Resolve a path in the site destination. |
|
Join path segments. |
|
Basename of a path. |
|
Directory name of a path. |
Content
| Name | Description |
|---|---|
|
Read a file from the plugin directory. |
|
Read a file from the site source. |
|
Write a file to the site destination. |
|
Check if a plugin file exists. |
|
Check if a site file exists. |
Utilities
| Name | Description |
|---|---|
|
Slugify a string. |
|
Return true if the string contains markdown markers. |
|
Extract a plain-text excerpt from HTML (default maxLength 200). |
|
Parse a date string and return ISO string. |
Plugin metadata
| Name | Description |
|---|---|
|
Plugin metadata map (name, version, author, path, and more). |
|
Plugin name. |
|
Plugin version. |
|
Plugin description. |
|
Plugin author. |
|
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
- Use plugin groups: Organize related plugins into logical groups
- Start with core: Always enable at least the core plugin group
- Test configurations: Verify your plugin configuration works as expected
- Monitor performance: Some plugins may impact build times
- Keep plugins updated: Ensure custom plugins work with GenGen updates
- 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:
- Follow the established plugin structure
- Include comprehensive documentation
- Add appropriate tests
- Consider plugin groups and categorization
- 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.