Hooks and Extension Index

Every supported way for a plugin or theme to plug into TruCMS, with the exact call and where it belongs. If what you need is not here, it is not an extension point yet; see what is not open yet.

Where each call goes

Admin

Extension pointCallWhereGuide
Admin request hookEvent::listen(AdminBooting::class, fn () => ...)boot()Service provider
Sidebar entryMenuManager::make(string $key, fn (MenuItems $item) => ..., ?int $order)AdminBootingAdmin menu
Sidebar childMenuManager::get($key)?->subMenu(string $key, callable)AdminBootingAdmin menu
Remove a core entryMenuManager::remove($key)AdminBootingAdmin menu
Settings section or tabSettingsManager::add(['id' => ..., 'title' => ..., 'link' => [...], 'pages' => fn () => [...]])AdminBootingSettings
Dashboard row and itemDashboard::admin()->row($name, $order)->widget($id, $class, async: true)boot()Dashboard
Visitor account dashboardDashboard::user()->row(...)->widget(...)boot()Dashboard
Your own dashboardDashboard::for('alias.dashboard') + @dashboard('alias.dashboard')boot() + viewDashboard
BreadcrumbsBreadcrumbs::for('admin.alias.index', fn (Trail $trail) => ...)routes/breadcrumbs.php required in boot()Breadcrumbs
PermissionsPermission::findOrCreate('manage alias', 'web') + ->can()Migration or seeder; routesPermissions

Content and the page builder

Extension pointCallWhereGuide
Block categoryShortcode::category(string $id, string $label, int $priority = 100)boot()Shortcodes
Shortcode (block)Shortcode::registerIfMissing(MyShortcode::class) + Blade::component(...)boot()Shortcodes
Replace a blockShortcode::replace(MyBlogShortcode::class)boot()Shortcodes
Assets by content markerShortcode::registerMarker('data-my-widget', ['vite' => [...]])boot()Shortcodes
AI visibility of a blockShortcodeDefinition::make(...)->ai(['enabled' => false])Shortcode definitionAI assistant
Data-bound section sourceapp(BindingSourceRegistry::class)->register(new MyBindingSource)boot()Data-bound sections
Front widgetWidgets::register('alias-name', MyWidget::class)boot()Widgets
Menu-builder link sourceMenuBuilder::register('alias-menu', fn (MenuContainer $menu) => ...)AdminBootingMenus
Page typeAppPages::register(PageDefinition::make('alias.page')->selectedBySetting(...)->pageSetup(...))boot()Page types
Public URL for a modelimplements ResolvableSlug, use HasSlug, resolvedSlugRenderer()ModelResolvable slugs
Back-fill support for your modelconfig(['slugs.models' => [...config('slugs.models'), MyModel::class]])boot()Resolvable slugs
Reserve URL segments"public_paths": ["alias"]module.jsonManifest
Template-library layoutsresources/page-templates + a seeder using TemplateSources::module('Name')Module filesTemplate library

Views and themes

Extension pointHowGuide
Restyle a plugin from a themeresources/themes/{theme}/vendor/{alias}/... overrides {alias}::... viewsRoutes and views
Site-level string overrideslang/modules/{alias}/{locale}/*.php (with the namespaced registerTranslations())Localization
Theme optionsEntries in the theme's theme.jsondefaultsTheme options
Per-request option overridesset_theme_option(), override_theme_options()Theme options
Child theme"extends": "echo" in a new theme.jsonCreating a theme

Data, events and background work

Extension pointCallGuide
Flush cached pages when data changesResponseCacheInvalidator::flushWhenChanged([Model::class]) (automatic for BaseModel)Caching
Keep a page out of the cacheCacheProfile::keepOutOfCache(), CacheProfile::GUESTS_ONLYCaching
Per-visitor fragments in cached pagesAppend a replacer class to config('responsecache.replacers')Caching
Scheduled taskprotected function configureSchedules(Schedule $schedule): voidEvents and jobs
Artisan commandprotected array $commands = [...]Events and jobs
React to paymentsListen to Vanilo\Payment\Events\PaymentCompleted and siblingsPayments
React to refundsModules\TruPayments\Events\RefundCreated, RefundStatusChangedPayments
React to tickets and registrationsTicketOpenEvent, TicketMessageEvent, TicketCloseEvent, RegisteredEvents and jobs

Payments

Extension pointCallGuide
Take payments for a recordapp(PaymentManager::class)->createFromPayable($payable, $method, $extra)Payments
New gateway: admin metadataGatewaySettings::registerGateway('key', ['label' => ..., 'class' => ..., 'required_credentials' => [...]])Add a gateway
New gateway: registryVanilo\Payment\PaymentGateways::register($id, Gateway::class)Add a gateway
Offer methods to your module only"payments": true in module.json, then availableMethods(context: 'yourmodule')Payments

TruCommerce registries

For plugins that extend the shop rather than the CMS. Read the TruCommerce module code before using them; they follow the e-commerce framework TruCommerce is built on.

RegistryAdds
Vanilo\Shipment\ShippingFeeCalculators::register($id, $class)Shipping fee calculator types. TruCommerce only offers calculators that implement its ConfigurableShippingCalculator contract (form fields, availability, calculation); see Modules/TruCommerce/app/Support/Shipping
Vanilo\Promotion\PromotionRuleTypes::register(), PromotionActionTypes::register()Promotion conditions and effects
Vanilo\Properties\PropertyTypes::register()Product attribute (property) types