---
url: /internals/panel-frontend.md
---
# Panel frontend

The control panel is server-rendered Blade with Livewire 3 components and Alpine.js, built with Vite from `core/assets/` and shipped as a committed dist that projects publish with `evolve.assets`.

## Build

`core/assets/package.json` has one script, `vite build`, with `laravel-vite-plugin`, Tailwind (plus container queries), sass and the Alpine and TipTap dependencies. The output is `core/assets/public/build/`, committed, and published to `public/vendor/evolve` of a project. Rebuild after changing anything under `core/assets` and commit the dist. Gotcha from the repo's CLAUDE.md: the Tailwind content glob loops through the Testbench skeleton's vendor symlink; remove `vendor/orchestra/testbench-core/laravel/vendor` before building.

Since 2.13 the bundle is split (`core/assets/scripts/lazy.ts`): `app.ts` carries Alpine, the plugins, dropdowns, prefetch, tooltips, the command palette and the progress indicator; charts, the TipTap rich text editor, the tree, selects and date pickers load on first use and `window.makeChart`, `makeEditor`, `editorAi`, `makeTree`, `makeSelect`, `makeDatePicker` return Promises. No web font is loaded; the system stack is used.

## Scripts

`core/assets/scripts/`: `app.ts` (entry), `alpine-plugins.ts`, `command-palette.ts` (Cmd-K, filters views and actions in the browser from the server-rendered registry), `dropdown.ts` (the registered Alpine component `dropdown(alignment)`, popper created on first open), `custom-confirm.ts` and `custom-prompt.ts` (`window.betterPrompt`, used by the editor's link, image and AI prompt dialogs), `prefetch.ts` (`data-prefetch` links), `progressIndicator.ts`, `richtext.ts` (TipTap with the AI menu), `select.ts`, `datepicker.ts`, `tree.ts` (page tree), `sortable.ts`, `tooltips.ts`, `charts.ts`, `theme.ts` (light and dark mode), `definitions/` (TypeScript typings), `frontend/` (scripts the frontend info bar needs).

## Icons

`core/assets/icons/` holds the Nucleo set (licence in `LICENSE.md`, panel only) and `aliases.php`, which maps the old Font Awesome names that blueprints, sidebar entries and stored activity names still use. `<x-evolve::icon name="..." />` renders `<svg><use href="/evolve/icons.svg?v=<hash>#name">`; the sprite route is cached immutably by hash. `evolve:icons:sync` (workbench only) regenerates the sprite and fails above the 250 icon budget; `IconsTest` guards the manifest.

## Layouts and components

`core/views/app.blade.php`, `guest.blade.php`, `blank.blade.php` are the three layouts; `Support\PanelTheme` sets the CSS variables (`evolve.theme-color` feeds only the accent). Shared components under `core/views/components/`: `layout/sidebar`, `layout/header` (renders `layout.command-palette`), `layout/drawer` (records, with the `close-modal` contract and sizes xs to lg), `layout/modal` (tasks), `action-bar` (sticky, submits through the `form` attribute, unsaved guard), `segmented` and `segmented.item`, `resource/list` and `resource/list-item` (48 px rows, hairlines), `dropdown`, `card`, `tabs`, `toggle`, `form/*` (field types), `icon`.

Livewire conventions: `legacy_model_binding` must be `true` in the project's `config/livewire.php` (a documented v2 breaking change); components under `core/src/Http/Livewire` and `<module>/src/Http/Livewire`, loaded by `LivewireComponentLoader`; `ResourceComponent` is the base for list managers with `create`, `edit`, `delete`, search and sorting, `ResourceController` for the classic create and edit screens.

## Overrides

Projects may copy panel views into `resources/views/vendor/evolve` or `theme/views/vendor/evolve`. `Support\ViewOverrides` holds `CHANGES` (per version, which view changed and what a copy must follow) and `REMOVED`; `evolve:view-overrides {--since=} {--strict}` compares a project's copies against it and also matches content patterns (Font Awesome tags, synchronous `makeEditor`, white text on `bg-primary`). Every PR that changes a view a project might have copied adds an entry.
