The tutorials carry one mini-case through every chapter; the API Reference enumerates every class. The Cookbook does neither. It answers seventeen specific questions of the form "I want to do X, what's the smallest code that works?" and gets out of the way.
Recipes are not graded by difficulty and not ordered as a course. Land on the page for the problem you have, copy the code, adapt it. The See also block at the bottom of each recipe points at the concept page that explains why the code works and the API page for each class it uses, so you can fill in the background later if you need to.
How each recipe is laid out
Every recipe follows the same four sections, in the same order:
- Problem. One sentence on what you are trying to do. If it does not match what you came here for, search the sidebar.
- Recipe. The smallest working code, with a short paragraph explaining the two or three pieces a reader cannot infer from the snippet alone (which file does this go in, which event does it listen to, which container binding is doing the work).
- Variants. One or two small adaptations of the same shape: different HTTP method, different cache layer, different middleware order. Skipped when there is nothing useful to add.
- See also. Sibling recipes, the concept page that explains the mechanism, the API Reference pages for each class the recipe uses, and the tutorial chapter that exercises the same surface against a real plugin.
Snippets are intentionally small. A recipe is the seed of a solution, not the solution itself; the concept page tells you where it fits, the API page tells you what else is on the surface.
What's covered
Seventeen recipes across five areas:
Routing & Endpoints (4)
How to mount custom URLs alongside Scriptor's page tree.
| Recipe | Problem |
|---|---|
| Wrap FastRoute or league/route in a plugin | Reuse a real router library instead of writing your own |
| Inline JSON endpoint in the theme | One-off /api/... endpoint without a separate plugin |
| Controller-with-DI via factory closure | Routes that dispatch to a class, with services injected |
| Auth middleware on a custom route | Require login (or an API key) before the handler runs |
Events & Resolution (3)
How to intercept Scriptor's request pipeline at the right point.
| Recipe | Problem |
|---|---|
| Replace 404 with a fallback handler | Catch unresolved URLs and serve something else (legacy redirects, search) |
| Serve dynamic pages from PageResolving | Generate a page from a database row or an API call instead of the page tree |
| Decorate page HTML in ContentRendering | Add a reading-time badge, TOC, or analytics snippet to every page body |
Frontend Surface (3)
How to expose page data through formats other than HTML.
| Recipe | Problem |
|---|---|
| Generate sitemap.xml from PageRepository | Search engines want a list of canonical URLs |
| RSS / Atom feed from a page tree | Readers want a subscribable feed of a track or blog |
| Image transforms with ImageUrlBuilder | Resize / crop / format images on demand without per-page boilerplate |
Editor Extensions (3)
How to add admin surfaces a plugin owns end-to-end.
| Recipe | Problem |
|---|---|
| Editor module with CRUD sub-routes | One module, four routes (index, edit, create, delete), one slug |
| Plugin contributes a sidebar menu item | Pin a custom module's slug into the editor sidebar |
| Add fields to the page edit form | Inject inputs into the built-in Pages form via PageFormRendering + PageSaving (incl. hide() for page-types) |
Plugin Authoring (4)
Patterns that show up across plugin codebases.
| Recipe | Problem |
|---|---|
| Custom CommonMark extension in a plugin | Add a :::callout block or a {{video:id}} shortcode to markdown rendering |
| Custom PSR-14 event for plugin-to-plugin communication | One plugin emits, another plugin listens, no direct coupling |
| Register schema with a LifecyclePlugin | Create real iManager fields on install, remove them on uninstall |
| CLI command via composer scripts | Maintenance or migration task you run with composer my-task |
Ordering and PR batching
Recipes land in eight PRs after the plan PR, grouped by area so each PR reviews as a coherent unit:
| # | PR | Recipes |
|---|---|---|
| 1 | Routing A | Wrap FastRoute, JSON endpoint |
| 2 | Routing B | Controller-with-DI, Auth middleware |
| 3 | Events A | 404 fallback, dynamic page resolver |
| 4 | Events B | ContentRendering decorator |
| 5 | Frontend A | sitemap.xml, RSS feed |
| 6 | Frontend B | Image transforms |
| 7 | Editor | Editor module CRUD, sidebar menu item |
| 8 | Plugin authoring | CommonMark extension, custom PSR-14 event, composer CLI |
| 9 | Editor + Plugin (2.1.0) | Add fields to the page form, Register schema with a LifecyclePlugin |
PRs 1–8 are the original fifteen recipes. PR 9 was added after Scriptor 2.1.0 shipped the editor page-form events and the plugin install/uninstall lifecycle, documenting that new surface.
Routing PR 1 ships first because two of the four documented forward references from the Build a Module tutorial (chapter 1 welcome, chapter 6 publishing) point at "wrap an existing router library inside a plugin"; merging that recipe early closes the gap.
What's not in the cookbook
Three categories of recipe are deliberately out of scope:
- Anything the tutorials already walk through. Build a Theme
covers contact form + flash + PRG. Build a Module covers the
stateless plugin flow end-to-end. Cookbook does not re-cover that
ground. (The one exception: the
install()/uninstall()schema lifecycle added in 2.1.0 does get a recipe, because the tutorial's mini-case is stateless and never exercises it.) - Recipes that fit inside one concept page. "How does Plugin
Discovery work" is not a recipe, it is a concept; it lives
under
developer-guide/concepts/plugin-discovery/. - Snippets that wrap a third-party library Scriptor does not ship. If the answer is "install package X and follow its README", the recipe adds nothing. The cookbook covers the Scriptor-side glue: how to register the result, where to put the wrapper, which event to hook.
If a recipe you wanted is missing, the surface to compose it from is in the API Reference. Open a discussion if it should be a canonical recipe; the cookbook grows by addition.
Where to go next
If you are mid-task, jump straight to the recipe on the sidebar. If you are browsing, the four Routing recipes are the most frequently used; Events and Frontend Surface are next; Editor and Plugin Authoring are for plugin authors specifically.
If you have not built anything yet, the tutorials are a better entry point than the cookbook:
- Build a Theme for the frontend surface.
- Build a Module for the plugin surface.
If you want to understand why a recipe is shaped the way it is before copying the code, the Concepts chapters explain the request pipeline, plugin discovery, frontend events, and editor extensions in narrative form.
This track lands one PR at a time, in the order in the table above. The first chapter PR (Routing A) opens immediately after this plan PR merges.