Start Here
Configuration
Every config file these packages publish, what each key decides, and the defaults you get for saying nothing.
On this page
Wire works out of the box after installation. Publish config files only when you need to change defaults for notifications, date formats, uploads, table behavior, sortable behavior, or audit logging.
Publish Config Files
php artisan vendor:publish --tag=wire-core::configphp artisan vendor:publish --tag=wire-forms::configphp artisan vendor:publish --tag=wire-table::configphp artisan vendor:publish --tag=wire-sortable::configphp artisan vendor:publish --tag=wire-panels::configphp artisan vendor:publish --tag=wire-admin::configphp artisan vendor:publish --tag=wire-boost::config # One per installed modulephp artisan vendor:publish --tag=wire-module-users::configphp artisan vendor:publish --tag=wire-module-auth::configphp artisan vendor:publish --tag=wire-module-settings::configphp artisan vendor:publish --tag=wire-module-notifications::configphp artisan vendor:publish --tag=wire-module-audit::configphp artisan vendor:publish --tag=wire-module-media::config
You only need the tags for packages you installed. Every module's own installer
(php artisan wire-module-users:install and friends) publishes its config for
you, so the lines above are for an application setting one up by hand.
Environment Variables
| Variable | Default | Used by |
|---|---|---|
WIRE_NOTIFICATIONS_DRIVER |
session |
Core notifications |
WIRE_AUDIT_ENABLED |
true |
Core audit log |
WIRE_AUDIT_USER_MODEL |
App\Models\User |
Core audit log |
WIRE_FORMS_UPLOAD_DISK |
public |
Forms file upload |
WIRE_MOBILE_SHEET |
true |
Core mobile bottom-sheets |
WIRE_MOBILE_BREAKPOINT |
sm |
Core mobile sheet breakpoint |
WIRE_AUTH_CODE_LOGIN |
false |
Signing in with a mailed code, no password |
WIRE_AUTH_CODE_SECOND_FACTOR |
false |
A mailed code after a correct password |
WIRE_AUTH_CODE_VERIFY_EMAIL |
false |
Confirming an address by code |
WIRE_AUTH_CODE_RESET_PASSWORD |
false |
A reset mail that carries a code, not a link |
WIRE_USERS_PASSKEYS |
auto |
The passkey card on the profile page |
JavaScript Assets
Nothing needs configuring and nothing needs publishing: every package copies its
own pre-built bundles into public/vendor/<package> and serves them as static
files, cache-busted by file modification time. The one thing your app decides is
where they are emitted — put
@wireStackScripts
once in the layout <head> and every installed package's Alpine controllers are in
the initial document, which is what keeps them working across wire:navigate
(including the cached Back/Forward path). Pass a package name —
@wireStackScripts('wire-table') — to emit only one package's bundles.
php artisan vendor:publish --tag=laravel-assets --force does the same copy ahead
of time, which moves it off the first request after a deploy — useful, never
required. There is no config key either way.
Full explanation in Getting Started → JavaScript Assets.
Core
The wire-core config controls shared UI behavior.
return [ 'notifications' => [ 'default' => env('WIRE_NOTIFICATIONS_DRIVER', 'session'), ], 'icons' => [ 'default_set' => 'default', 'sets' => [ 'default' => \NyonCode\WireCore\Foundation\Icons\DefaultIconSet::class, // 'lucide' => App\Wire\Icons\LucideIconSet::class, // => "lucide:home" ], 'paths' => [ // resource_path('icons'), // logo.svg => "logo" // 'brand' => resource_path('icons/brand'), // mark.svg => "brand-mark" ], 'warn_missing' => env('WIRE_ICONS_WARN_MISSING', false), ], 'colors' => [ 'palette' => [], // Roles, not colours: every surface follows what they point at. // 'success' => 'emerald', 'danger' => 'red', 'warning' => 'amber', 'info' => 'cyan', ], // 'normal' or 'compact' — see Theming → Density. 'density' => env('WIRE_DENSITY', 'normal'), // 'rounded' or 'sharp' — see Theming → Shape. 'shape' => env('WIRE_SHAPE', 'rounded'), 'plugins' => [ // App\Wire\Plugins\ExamplePlugin::class, ], 'modals' => [ 'default_width' => 'md', 'slide_over_width' => 'md', 'close_on_click_away' => true, 'close_on_escape' => true, ],];
Notifications
Built-in notification drivers are:
| Value | Driver |
|---|---|
session |
Stores notifications in session flash data |
livewire |
Dispatches Livewire browser events |
flasher |
Uses Flasher when your app has it installed |
null |
Disables delivery |
WIRE_NOTIFICATIONS_DRIVER=livewire
See Core Notifications for usage examples.
Icons
| Key | Purpose |
|---|---|
default_set |
Which sets key is the unprefixed base set (default 'default' = Heroicons). |
sets |
Registered icon sets. The default-set key is unprefixed; every other key is a required prefix, so its icons are addressed as prefix:name (e.g. lucide:home). Registering a non-default set without a string prefix throws. |
paths |
Folders of .svg files auto-registered as bare-named icons. A string key adds a dash-joined name prefix ('brand' => … → brand-mark). |
warn_missing |
Log a warning (and render the fallback) when an unknown icon name is used — handy for catching typos in development. |
'icons' => [ 'default_set' => 'default', 'sets' => [ 'default' => DefaultIconSet::class, // "pencil" (Heroicons, 20×20 fill) 'lucide' => LucideIconSet::class, // "lucide:home" (24×24 stroke) ], 'paths' => [ 'brand' => resource_path('icons/brand'), ], 'warn_missing' => env('WIRE_ICONS_WARN_MISSING', false),],
Sets are used together with deterministic, collision-free resolution. See
Core → Foundation → Icons for the full API, the
prefix:name model, custom sets, and accessibility.
Plugins
Register application or package plugins in the plugins array:
'plugins' => [ App\Wire\Plugins\TenantPlugin::class,],
Plugins that implement HasConfiguration can also read merged options from wire-core.plugins.config.{pluginId}:
'plugins' => [ App\Wire\Plugins\ExportPlugin::class, 'config' => [ 'export' => [ 'format' => 'xlsx', ], ],],
See Core Plugins for plugin classes, lifecycle, dependencies, macros, hooks, type registries, query pipes, and plugin configuration.
Modals
Modal width values are Tailwind-style size tokens such as sm, md, lg, xl, 2xl, or full.
'modals' => [ 'default_width' => 'lg', 'slide_over_width' => 'xl', 'close_on_click_away' => false, 'close_on_escape' => true,],
See Core Modals for modal actions and slide-overs.
Mobile
Floating panels (dropdowns, action-group menus, select/date/tag pickers, table filter & column-toggle panels) and the mobile modal variants present as a bottom sheet below a breakpoint. These are the global defaults — every component overrides them per instance.
'mobile' => [ // Present floating panels as a bottom sheet on mobile. false = classic // trigger-anchored floating panel everywhere. 'sheet' => env('WIRE_MOBILE_SHEET', true), // Breakpoint below which panels become a sheet: // 'sm' (< 640px, phones — default) // 'md' (< 768px, incl. small tablets) // 'lg' (< 1024px, incl. tablet portrait) 'breakpoint' => env('WIRE_MOBILE_BREAKPOINT', 'sm'),],
Per-component overrides (win over the global defaults):
// Sheet on/offSelect::make('role')->options([...])->sheetOnMobile(false); // force floatingSelect::make('country')->searchable()->sheetOnMobile(); // force sheet even when searchable$table->sheetOnMobile(false); // filter + column-toggle panels // Breakpoint (sm | md | lg)Select::make('role')->mobileBreakpoint('lg'); // sheet up to 1024px$table->mobileBreakpoint('md');ActionGroup::make([...])->mobileBreakpoint('md');Action::make('edit')->form([...])->slideOverOnMobile()->mobileBreakpoint('md');
<x-wire::dropdown :sheet-on-mobile="false" :breakpoint="'md'">…</x-wire::dropdown>
Priority: per-component (->sheetOnMobile() / ->mobileBreakpoint()) > searchable-auto-floating > global
config. Searchable selects default to floating so the search box stays usable. Sheets add safe-area
padding, a drag-to-dismiss grabber and a focus trap automatically.
Forms
The wire-forms config controls date and time defaults, how money and phone numbers are
written, uploads, and the rich editor toolbar.
return [ 'date_format' => 'd.m.Y', 'time_format' => 'H:i', 'datetime_format' => 'd.m.Y H:i', 'first_day_of_week' => 1, 'money' => [ 'currency' => 'CZK', 'decimal_separator' => ',', 'thousands_separator' => ' ', ], 'phone' => [ 'countries' => [], 'default_country' => null, ], 'file_upload' => [ 'disk' => env('WIRE_FORMS_UPLOAD_DISK', 'public'), 'directory' => 'uploads', ], 'rich_editor' => [ 'toolbar' => [ 'bold', 'italic', 'underline', 'strike', '|', 'heading', 'bulletList', 'orderedList', '|', 'link', 'blockquote', 'codeBlock', '|', 'undo', 'redo', ], ],];
money is what MoneyInput writes an amount with when a field does
not say otherwise, and phone is PhoneInput's offer — an empty
countries list offers the whole dialling-code table, and the list is also the validation.
Use WIRE_FORMS_UPLOAD_DISK to move uploads to a different filesystem disk:
WIRE_FORMS_UPLOAD_DISK=s3
See Field Reference for field-specific options.
Table
The wire-table config controls default table behavior and inline text input behavior.
return [ 'defaults' => [ 'per_page' => 10, 'per_page_options' => [10, 25, 50, 100], 'searchable' => true, 'sortable' => true, 'hoverable' => true, 'striped' => false, ], 'text_input' => [ 'save_on_blur' => true, 'save_on_enter' => true, 'live_validation' => false, 'live_debounce' => 500, ], 'notification_driver' => null,];
notification_driver may be left as null; the table then uses the core session driver. Set it only when a table needs a different driver class.
See Table Overview, Columns, and Exports.
Sortable
The wire-sortable config controls row ordering.
return [ 'order_column' => 'sort_order', 'sortablejs_cdn' => null, 'animation' => 150, 'user_model' => 'App\\Models\\User', 'user_key_type' => 'id', // 'uuid' / 'ulid' for non-integer user keys];
sortablejs_cdn defaults to null because SortableJS is compiled into the package's
own bundle — reordering needs no CDN request, so it works offline and under a strict
CSP. Set it only if your own code needs a global window.Sortable: the tag is then
loaded in addition to the bundle, never instead of it, and the drag controller uses
the bundled copy either way.
Set user_key_type to uuid or ulid (before running the column-order migration) when your user model uses a non-integer primary key.
Panels
The wire-panels config decides whether the framework registers a resource's
pages as routes for you.
return [ 'routes' => [ 'enabled' => false, 'prefix' => 'admin', 'middleware' => ['web', 'auth'], 'domain' => null, 'only' => [], 'except' => [], ],];
enabled is false because Route::wireResources() in your own route file is
the reference path — these are the same group arguments, handed over once, for an
application that would rather not keep a route file for them.
Two things to know before turning it on. Package providers boot before your own,
so these routes are matched before everything in routes/web.php; an
application with a catch-all under the same prefix wins today and would stop
winning. And enabling this and calling Route::wireResources() yourself is
refused rather than resolved — it would register every page twice under one route
name.
only / except take registered keys: a resource key or a dashboard key, the
same key the menu and ResourceRoutes::urlFor() use.
For several mount points — admin, business, production — add a zones key,
one entry per zone; each inherits the values above it and overrides what it
names. The array key becomes the route-name prefix, so the same resource in two
zones gets two route names instead of two routes fighting over one.
'zones' => [ 'admin' => ['prefix' => 'admin', 'middleware' => ['web', 'auth', 'can:admin']], 'business' => ['prefix' => 'business', 'only' => ['orders']],],
See Resources for zones and Routing for the rest.
Boost
The wire-boost config controls the AI tooling MCP server. The two code-executing tools are disabled by default.
return [ 'server' => [ 'name' => 'WireStack Boost', 'version' => '1.0.0', ], 'tools' => [ 'database_query' => env('WIRE_BOOST_DATABASE_QUERY', false), 'tinker' => env('WIRE_BOOST_TINKER', false), 'browser_logs' => env('WIRE_BOOST_BROWSER_LOGS', true), ], 'scan' => [ 'paths' => [app_path()], // where list-wire-components searches ], 'docs' => [ 'paths' => [], // extra Markdown directories for search-wire-docs ], 'browser_logs' => [ 'path' => storage_path('wire-boost/browser.log'), 'max_entries' => 50, ],];
Enable database-query and tinker only when you trust the agent connecting to the server. See
MCP Server & Tools.
Audit
Audit log settings live in config/wire-core.php:
'audit' => [ 'enabled' => env('WIRE_AUDIT_ENABLED', true), 'model' => \NyonCode\WireCore\Audit\AuditEntry::class, 'user_model' => env('WIRE_AUDIT_USER_MODEL', 'App\\Models\\User'), 'events' => null, 'exclude_columns' => [ 'password', 'remember_token', ], 'retention_days' => null,],
Set events to an array when you want to log only selected event types:
'events' => ['created', 'updated', 'deleted'],
See Audit Log for setup, model usage, and pruning.
Admin
The shell publishes one block, and it is the brand — everything else about it is markup you write (see The Admin Shell):
// config/wire-admin.php'brand' => [ 'name' => null, // falls back to config('app.name') 'logo' => null, // the wide menu — a path under public/, or a URL 'logo_dark' => null, // the dark-theme variant of it 'mark' => null, // the 64-pixel rail — falls back to the app's initial 'height' => 28, // the logo's rendered height, in pixels 'url' => null, // where the brand links to — defaults to the panel root],
Why there are two logo forms, and why the choice is made before the page paints: Branding And Theme.
Modules
Each ready-made module publishes a config file of its own, and the keys are documented on the module's page rather than here — a module is a whole area, and its options only make sense beside the screens they change:
| File | What it configures | Page |
|---|---|---|
wire-module-users.php |
The user model, the resource, roles and teams, the profile screen | Users |
wire-module-auth.php |
Which screens the auth module registers, the routes it claims, and the four one-time-code flows | Auth |
wire-module-settings.php |
The settings table, its cache, and the groups the screen shows | Settings |
wire-module-notifications.php |
The bell, its panel, and the stored-notification table | Notifications |
wire-module-audit.php |
The audit screen over the trail wire-core records |
Audit |
wire-module-media.php |
Disks, conversions, accepted types, and the picker | Media |
The Rest Of wire-core
Three keys in config/wire-core.php are declarations rather than settings, and
each one is covered where the thing it declares is explained:
| Key | What it holds | Page |
|---|---|---|
resources |
The resource classes an application registers | Resources → Registration |
dashboards |
The dashboard classes, the same way | Dashboards |
tenancy |
enabled and the column a tenant scope is applied on |
Authorization |
config/wire-table.php has one more: preferences picks the driver a table's
per-user column order, visibility and page size are stored in (null, session
or database, with guest naming the driver for a visitor who is not signed
in). See Advanced Features.