This is the plugin tutorials track of the Developer Guide. Six chapters, each adding exactly one new surface to a real plugin, so by the end of the last chapter you have a working plugin you can install on any Scriptor site, not a pile of disconnected snippets.
Build a Theme taught how to layer a frontend on top of Scriptor's page tree. Build a Module teaches how to extend Scriptor itself: how to add behaviour that no theme alone can express. If you have not read the Concepts chapters on the plugin lifecycle and PSR-14 events yet, you can still follow along; every chapter links back to the relevant concept where it gets used.
The mini-case: Simple Router
You'll build a plugin called bigins/scriptor-simple-router. It lets
site authors register their own URL routes with closure or controller
handlers, parallel to (and ahead of) Scriptor's normal Pages routing.
The shape readers will end up with:
$router = \Scriptor\Boot\App::container()->get(Router::class);
$router->get('/api/users/{id}', function (Request $req): Response {
return Response::json(['id' => $req->param('id'), 'name' => 'Ada']);
});
$router->post('/webhook/stripe', StripeWebhookController::class);
That is the artefact. Each chapter takes it one step further; you can stop at any chapter and the plugin still loads cleanly.
Chapters
| # | Chapter | What it adds |
|---|---|---|
| 1 | Welcome | Meet the mini-case, see the target API, agree on what we are not building |
| 2 | Skeleton | composer.json, namespace, the ScriptorPlugin interface, Plugin Discovery picking it up |
| 3 | The Router | Route registry, pattern parsing with {id} placeholders, the match() algorithm |
| 4 | Request & Response | A thin Request wrapper for path/query/body params, Response helpers for JSON / HTML / status |
| 5 | Theme Integration | The one-line _ext.php hook that lets the plugin intercept requests before Scriptor's page resolver runs |
| 6 | Publishing | Tests, README, semver tag, GitHub VCS setup so consumers can composer require it |
What you will not find in this track
- Class-by-class reference. That lives in the API Reference track. Tutorials cite class names; they do not enumerate every method on them.
- Middleware, route groups, dependency injection per route. Real router libraries (Symfony Routing, FastRoute, league/route) cover those. Simple Router stays small on purpose. The goal here is to understand the plugin extension surface, not to ship a competitor to FastRoute. The Cookbook covers how to wrap an existing router library inside a Scriptor plugin instead.
- Auto-magical integration with every theme. Hooking the plugin
into the request pipeline requires one line in your theme's
_ext.php(chapter 5 explains why and how). Themes that ship a router-aware_ext.phpout of the box are a separate effort.
What you need before chapter 1
- A working Scriptor install, reachable on
http://localhost:<port>/with at least one page in the page tree. Thedocs/install.mdwalkthrough covers the three steps (git clone,composer install,php bin/scriptor install). - PHP 8.2+ and Composer 2 on your machine.
- A text editor. Anything that highlights PHP is plenty.
- Familiarity with the basics of Scriptor's plugin model. At minimum, read the Plugin Discovery and Frontend Events concepts.
If / serves a page, /editor/ lets you log in, and you've skimmed
the two concept chapters above, you are ready. Open chapter 1.
This page is markdown at
scriptor-cms-site/theme/themes/info/content/developer-guide/build-a-module/_index.md,
rendered by the bigins/scriptor-markdown-pages plugin via the
/developer-guide/build-a-module/ URL.