Slim routes, middleware, and public URL patterns.
Route files
Core groups live in routes/*.php—admin, public content, commerce, API, etc. Plugins add:
routes/public.php— Public storefront routesroutes/admin.php— Routes under/admin/...
Both receive (App $app, PluginBootContext $ctx). Register plugin public routes before core variable content catch-alls to avoid shadowing.
Named routes
$group->get('/my-tool', $handler)->setName('admin.my_tool');
Generate URLs in Twig with url_for('admin.my_tool').
Middleware
RequireCmsStaff— Staff authentication for admin groups- CSRF tokens — Protect POST forms
- Permission checks — Gate sensitive actions in handlers
Public content URLs
When has_public_route is enabled:
GET /{typeSlug}— Type archiveGET /{typeSlug}/{entrySlug}— Single entryGET /{typeSlug}/{taxonomySlug}/{termSlug}— Taxonomy archive
Reserved slugs
Core blocks content type slugs that collide with system paths (admin, api, shop, login, …). Plugins register additional reserved segments via registerPluginReservedSlugs() in boot().
Admin content routes
routes/admin_content.php provides CRUD for types, fields, entries, block builder, and revisions—gated by permissions like manage_content_types, create_content, edit_content.
Troubleshooting
- 404 on plugin route — Plugin may not be active; route name typo in nav registration.
- Content type shadowed — Slug conflicts with reserved segment or plugin public path.