Skip to content

Panels

A panel is a self-contained area of the application with its own URL, look, navigation and access rules – e.g. /admin for the back office and /portal for employees or customers. Everything users see in Anvil lives in a panel: the resources with their lists and forms, own pages, the dashboard, the search, the notifications.

namespace App\Panels;
use Anvil\Access\Access;
use Anvil\Page\Dashboard;
use Anvil\Panel\Navigation\NavigationGroup;
use Anvil\Panel\Panel;
final class AdminPanel extends Panel
{
public function id(): string { return 'admin'; }
public function brand(): string { return 'ACME Back Office'; }
public function primaryColor(): ?string { return '#0d9488'; }
public function permission(): ?string { return 'admin.access'; }
public function resources(): array
{
return [InvoiceResource::class, CustomerResource::class, ...Access::resources()];
}
public function pages(): array
{
return [Dashboard::class, ReportsPage::class, ...Access::pages()];
}
public function navigationGroups(): array
{
return ['Sales', NavigationGroup::make('Reports')->icon('bar-chart')->collapsible()];
}
}
Terminal window
php spark make:anvil-panel Admin --suffix

generates App\Panels\AdminPanel (options: --namespace, --force). Register the panel in app/Config/Anvil.php:

namespace Config;
use Anvil\Config\Anvil as BaseAnvil;
class Anvil extends BaseAnvil
{
public array $panels = [\App\Panels\AdminPanel::class];
}

Panels are registered explicitly; Anvil never scans the file system. The ids must be unique (LogicException otherwise). From the registered panels Anvil derives the routes, the navigation, the permissions in the role editor and the components of the endpoint.

Topic Methods Details
Identity and look id(), path(), brand(), logo(), primaryColor(), maxContentWidth(), stylesheets(), scripts() Configuration
Content resources(), pages() Resources and pages
Start page widgets() Dashboard
Navigation navigationGroups(), userMenuItems() Navigation
Access permission(), authMethods(), requiresMfa(), filters(), logoutUrl() Access and login
Tenants hasTenancy() Tenants
URLs url(), endpointUrl() Routes and URLs

Methods not overridden keep their defaults; most panels only need id(), brand(), resources() and pages().

  1. The route belongs to the panel (/admin/...); its filters run first: session, login method, forced password change, handover lock, tenant and panel permission (Access and login).
  2. The panel becomes the current panel: service('panels')->current().
  3. The page or resource checks its own permission and policies.
  4. The content is rendered into the layout of the panel with sidebar and topbar.
  5. Interactive parts (lists, forms, actions, search) talk to the component endpoint of the panel with signed tokens.

An application can have several panels, e.g. a back office and a self service portal with different resources, colours and access rules. See Several panels.