Awn Awn
Back to Awn
Documentation menu — Extension points
Build / Extension points
Version
1.0
Last verified
2026-08-09

Extension points

Slots

PluginSlot: home_after_hero, page_after_content, before_footer. Each maps to slots.{name}.v1. A plugin declaring a slot must require that capability. Priorities are manifest integers 0..1000, default 100; lower first, slug breaks ties.

Dashboards

interface ContributesDashboard
{
    public function dashboards(): array;
}

new PluginDashboard(
    id: 'events',
    title: 'Events',
    description: 'Manage events.',
    routeName: 'plugin.events.dashboard.index',
    icon: DashboardIcon::Calendar,
    order: 30,
    requiresEnabled: false,
);

IDs are kebab-case and unique per plugin. Routes must exist and be globally unique among contributions. PluginDashboardResolver::groupsForOrganization() collects dashboards from effective plugins, rejects runtime duplicates or missing routes, sorts each plugin's items by order, and sorts groups by their first item's order. forOrganization() flattens that grouped order; it does not globally re-sort items across plugins.

Dashboard contributions from the same plugin are grouped into one sidebar submenu. Put index/overview and useful fixed-path shortcuts in dashboards(); Events intentionally includes its create page. Parameterized show/edit/delete actions remain contextual. The parent label comes from the manifest name and its icon from the first ordered child.

DashboardIcon is enum-backed rather than plugin-provided SVG. Available cases are Inbox, Calendar, Grid, Chart, Heart, CreditCard, Users, CheckCircle, and Folder.

Organization-home widgets

interface ContributesDashboardWidgets
{
    public function dashboardWidgets(Organization $organization): array;
}

new PluginDashboardWidget(
    id: 'fundraising-overview',
    view: view('plugin.fundraising::widgets.overview', $data),
    order: 10,
);

PluginDashboardWidgetResolver::forOrganization() walks enabled compatible plugins, calls dashboardWidgets() when supported, deduplicates by {plugin}:{widget-id}, and sorts widgets globally by order. The value contains only a validated kebab-case ID, a pre-built View, and order; it has no title, description, or icon. Widgets render on the organization dashboard and should summarize and link to a full plugin dashboard rather than duplicate management workflows.

Super Admin

ContributesSuperAdminPages returns PluginSuperAdminPage navigation descriptors for global platform routes. PluginSuperAdminPageResolver::groupsForPlatform() includes only installed and globally active plugins. Routes use /admin/plugins/{slug}/manage, plugin.{slug}.admin.*, auth, super.admin, and plugin.available:{slug},installed.

ContributesSuperAdminWidgets returns ordered PluginSuperAdminWidget views for admin.dashboard. These contributions are global, theme-independent, and never depend on an organization assignment.

See Organization dashboard surfaces, Super Admin pages and widgets, and Public pages and theme integration for complete recipes.

Pages

interface ContributesPages
{
    public function pages(): array;
    public function renderPage(
        PluginPage $page,
        PluginRenderContext $context,
        array $settings,
        array $parameters = [],
    ): PluginPageResponse;
}

PluginPage takes id, slug, title, showInNavigation = true, layout = Contained, order = 100. Dynamic whole-segment placeholders cannot be direct navigation. PluginPageResolver sorts navigation, resolves a matching page, calls the driver, renders the view, and wraps it in ResolvedPluginPage.

Collisions

Validation rejects duplicate dashboard IDs/routes, missing routes, dashboard/settings URL collisions, availability middleware inconsistent with requiresEnabled, duplicate page IDs, equivalent cross-plugin patterns (events/{a} vs events/{b}), and plugin route prefixes that are not plugin.{slug}.. Enabled dashboards require plugin.available:{slug}; installed-mode dashboards require plugin.available:{slug},installed. Enable validation blocks plugin patterns matching existing tenant CMS slugs. Runtime guards duplicate effective patterns.

Super Admin validation additionally requires plugin.{slug}.admin.*, /admin/plugins/{slug}/manage, auth, super.admin, installed-mode availability, and no organization middleware.

Multi-surface example

Events combines two organization dashboard links, a full-width navigable index, contained dynamic detail, priority-40 home slot, package CRUD, and tenant data. Contact Form combines one organization dashboard, contact-us, site navigation, before-footer rendering, and throttled submissions. Fundraising combines seven organization pages, organization and Super Admin widgets, three read-only Super Admin pages, public pages, private proof submission, and tenant-scoped reporting.

Current limits: no arbitrary slots, tenant placement/priority controls, catch-all/optional page parameters, plugin dependency API, or functional disabled-dashboard visibility. Both themes apply Contained versus FullWidth in their plugin-page partials.