medienbaecker / kirby-modules
Easily add modules to your pages
Package info
github.com/medienbaecker/kirby-modules
Type:kirby-plugin
pkg:composer/medienbaecker/kirby-modules
Requires
This package is auto-updated.
Last update: 2026-03-25 23:28:00 UTC
README
Modular page building for Kirby using regular Kirby pages with their own blueprint and snippet, edited inline on the parent page.
Licensing
Kirby Modules is a commercial plugin. You can use it for free on local environments but using it in production requires a valid licence. You can pay what you want, the suggested price being 99€ per project. Feel free to choose "0" when working on a purposeful project ❤️
Features
- Edit module fields inline on the parent page with a blocks-like UI
- Draft previews for individual modules
- Great performance with large numbers of modules
- Robust multilanguage behaviour
- Automatic container page creation, separating modules from regular subpages
- Multiple modules sections per page
- Sensible defaults in module blueprints
Installation
composer require medienbaecker/kirby-modules
Or download this repository and put it into site/plugins/kirby-modules.
What's a Module?
A module is a regular page, differentiated from other pages by being inside a modules container. This makes it possible to use pages as modules without sacrificing regular subpages.
Page
├── Subpage A
├── Subpage B
└── Modules
├── Module A
└── Module B
Quick Start
Add a (or multiple) modules section to your page blueprint:
# site/blueprints/pages/default.yml title: Default Page sections: modules: type: modules
Create a module blueprint and snippet:
# site/blueprints/modules/text.yml title: Text fields: textarea: label: Text
// site/snippets/modules/text.php <div id="<?= $module->slug() ?>"> <?= $module->textarea()->kt() ?> </div>
Or create both files using the CLI command:
kirby make:module gallery
In your snippet, $module is the module page and $page is the parent page. Variables from controllers are also available.
Module blueprints support the full Kirby blueprint layout, including columns and sections:
# site/blueprints/modules/images.yml title: Images icon: images columns: - width: 1/2 fields: title: label: Title type: text images: label: Images type: files - width: 1/2 sections: files: true
Render in your template:
// site/templates/default.php <?= $page->modules() ?>
Anchor Links
Use $module->slug() as the element ID in your module snippet:
<div id="<?= $module->slug() ?>">
The slug is editable in the Panel via the #anchor button on each module card or the "Change anchor" button in the toolbar's dropdown.
Drafts
Module status can be toggled between draft and listed with a single click. Drafts can be freely positioned between listed modules.
Each draft module gets a signed preview URL for authenticated frontend previews without Panel login. A preview button appears in the module's toolbar when the module is a draft.
Section Options
| Option | Type | Description |
|---|---|---|
default |
string |
First/pre-selected module type in create dialog |
templates |
array |
Manually define available types instead of all |
templatesIgnore |
array |
Hide specific module types |
min |
int |
Minimum number of modules |
max |
int |
Maximum number of modules |
empty |
string |
Empty state text |
Multiple Sections
Each section's name (YAML key) becomes the container slug:
sections: modules: type: modules default: text sidebar: type: modules templates: - module.cta - module.newsletter
// Default container for modules section called `modules` <?= $page->modules() ?> // Secondary container for modules section called `sidebar` <?= $page->modules('sidebar') ?>
Config Options
// site/config/config.php return [ // Auto-publish new modules (default: draft) 'medienbaecker.modules.create.status' => 'listed', // Redirect to module page after creation (default: false) 'medienbaecker.modules.create.redirect' => true, ];
Template Methods
| Method | Description |
|---|---|
$page->modules() |
All modules (default container) |
$page->modules('sidebar') |
Modules from named container |
$page->hasModules() |
Page has modules |
$page->isModule() |
Page is a module |
$module->moduleId() |
CSS class (e.g. module--text) |
$module->moduleName() |
Blueprint title |
Custom Models
Override the model for all module types via config:
// site/config/config.php 'medienbaecker.modules.model' => CustomModulePage::class,
Or override a single module type via site/models/ (as you would with any regular page):
// site/models/module.text.php class ModuletextPage extends Medienbaecker\Modules\ModulePage { // your methods }
