Skip to content

Configuration

A panel is configured by overriding methods of Anvil\Panel\Panel. This page covers identity, look and assets; content, access and tenants have pages of their own.

Method Default Purpose
id() – (required) unique id
path() id() URI prefix
brand() Anvil name in the sidebar, the title and the login page
logo() null (brand mark) URL of a logo
primaryColor() null (theme colour) accent colour
maxContentWidth() Panel::WIDTH_FULL width of the content area
stylesheets() [] own CSS files
scripts() [] own JavaScript files
public function id(): string { return 'admin'; }

Lower case letters, digits and -, starting with a letter, at most 32 characters (Panel::ID_PATTERN); otherwise registering the panel throws an InvalidArgumentException. The id appears in:

  • permissions of pages (admin.page.reports) and the panel itself,
  • component ids (admin:invoices:collection) and tokens – a token of one panel is not valid in another,
  • route names (anvil.admin.dashboard, anvil.admin.invoices.index),
  • saved views and widget layouts of the users.

Changing the id later invalidates these: choose it once.

public function path(): string { return 'backoffice'; } // https://example.com/backoffice

The URI prefix of all routes of the panel, defaults to the id. It can be changed later; links built with url() follow.

public function brand(): string { return 'ACME Back Office'; }
public function logo(): ?string { return base_url('images/logo.svg'); }

The brand is shown in the sidebar, in the browser title (Page · Brand) and on the login page. A logo is a public URL of the own origin (the Content Security Policy blocks other origins); without one the brand mark of Anvil is shown. SVG or PNG with a transparent background work best in light and dark mode.

public function primaryColor(): ?string { return '#0f3d76'; }

The accent colour as #rrggbb: buttons, links, active navigation entries, focus rings. Other formats are ignored. Pick a colour with enough contrast to white text (WCAG AA, 4.5:1). Different panels can have different colours, e.g. blue for the back office and green for the portal. See Colours.

public function maxContentWidth(): string { return Panel::WIDTH_WIDE; }
Value Effect
Panel::WIDTH_FULL lists and cards use the whole window (default)
Panel::WIDTH_WIDE the content stops at 1440px

Forms and detail pages always stop at 1440px, so their fields stay readable.

public function stylesheets(): array { return [base_url('css/app.css')]; }
public function scripts(): array { return [base_url('js/app.js')]; }

Own CSS and JavaScript files as URLs of the own origin, loaded on every page of the panel: stylesheets after Anvil’s stylesheet (so they can override it), scripts before Anvil’s script. Inline styles and scripts are not possible with the Content Security Policy.

Scripts are loaded deferred before Anvil starts Alpine, so they can register Alpine components:

document.addEventListener('alpine:init', () => {
Alpine.data('counter', () => ({ count: 0, increment() { this.count++; } }));
});

Alpine runs in its CSP build: templates reference properties and methods by name, not with expressions. See Own styles and scripts.