Core

Everything on this page is installed by ui-kit:install before it asks about modules.

Auth pages

Seven pages as Livewire Volt single-file components over Fortify's actions, published to resources/views/livewire/pages/auth/ and routed from routes/auth.php:

RouteNamePage
GET /loginloginEmail, password, remember me
GET /registerregisterName, email, password; disposable email domains are rejected when features.disposable_email_block is on
GET /forgot-passwordpassword.requestSends the reset link
GET /reset-password/{token}password.reset
GET /two-factor-challengetwo-factor.challengeTOTP code, with a switch to a recovery code
GET /verify-emailverification.noticeWith a resend action
GET /verify-email/{id}/{hash}verification.verifySigned link handler
GET /confirm-passwordpassword.confirm

The copy on each page comes from config/ui-kit.php under copy, so a heading can change without editing a view. Every page renders in light and dark.

The registration page
/register in the guest layout.
The forgot-password page
/forgot-password.

Two-factor authentication

Fortify's twoFactorAuthentication feature is on by default and the installer publishes the migration that adds the two_factor_* columns to users. Login validates credentials first; when the user has a confirmed two-factor secret it stages a challenge and redirects to /two-factor-challenge, where a TOTP code or a recovery code completes the sign-in. Both steps are rate limited by the login and two-factor limiters the service provider registers.

The two-factor challenge page asking for a six-digit code
The challenge after a correct password. Recovery codes are one link away.

Enabling two-factor, confirming it with a code, showing recovery codes and disabling it again are the profile module. Without that module a user has no way to turn it on, so login never challenges, and nothing breaks.

Admin shell

resources/views/layouts/admin-sidebar.blade.php is the layout every admin Livewire component uses. It has a collapsible sidebar whose state persists in localStorage, a bottom navigation bar on phones, a theme toggle, and a footer with the current user, a profile link and a logout form. Navigation is read from config/admin.php; modules append their entries between the ui-kit:nav markers at install time and never touch yours.

The users list inside the admin shell
/admin/users: search, verified state and a detail link per row.
The admin dashboard on a phone with the bottom navigation bar
Below the md breakpoint the sidebar becomes a bottom bar.

Routes live in routes/admin.php, prefixed and named from the config:

// config/admin.php
'route_prefix' => 'admin',
'route_name_prefix' => 'admin.',
'middleware' => ['auth', 'verified', \Shipbytes\UiKit\Http\Middleware\EnsureIsAdminFallback::class],

EnsureIsAdminFallback lets a request through when $user->is_admin is truthy. The admin-middleware module swaps it for a Spatie role check.

Dashboard and users

RouteComponentWhat it shows
GET /adminApp\Livewire\Admin\DashboardThree counts: total users, verified, new this week. A stub to replace.
GET /admin/usersApp\Livewire\Admin\Users\UserListPaginated, searchable list
GET /admin/users/{user}App\Livewire\Admin\Users\UserDetailOne user, with the module partials that apply
A single user's detail page
/admin/users/2.

User shell

resources/views/layouts/user-shell.blade.php is a lighter authenticated layout for user-facing pages such as /profile. It carries the same head and banner components as the admin shell, so dark mode and the impersonation ribbon work there too. User routes live in routes/ui-kit-user.php behind auth.

Theme tokens

The kit's styles are a Tailwind v4 @theme block in resources/css/ui-kit-theme.css, imported by resources/css/ui-kit.css, which the installer imports from app.css right after tailwindcss:

@theme {
  --color-brand-500: #6366f1; /* bg-brand-500, text-brand-600, … */
  --font-boldtext: 'Poppins', ui-sans-serif, system-ui, sans-serif;
}

A @custom-variant dark binds dark: to a dark class on <html> rather than the OS preference, so the toggle can override the system setting. Override any token in your own CSS after the import; the last definition wins.

Alpine stores and the two components

resources/js/ui-kit.js registers two Alpine stores on alpine:init. Livewire loads Alpine, so there is nothing else to include.

StoreHoldsPersisted as
$store.sidebarcollapsed, with toggle()ui-kit.sidebar.collapsed
$store.themevalue of light or dark, with toggle() and apply()ui-kit.theme

Two Blade components from the package tie the stores to any layout, including your own public one:

<head>
    <x-ui-kit::head />      {{-- applies the saved theme before first paint, so no flash --}}
</head>
<body>
    <x-ui-kit::banners />   {{-- the impersonation ribbon, when that module is installed --}}

The kit's three layouts already include both. <x-theme-toggle /> is the published toggle button and works anywhere the store is loaded.

Artisan commands

CommandDoes
ui-kit:installCore install, then the module picker. --modules=a,b or --modules=all skips the prompt; --force overwrites existing files. Safe to re-run: an existing install is detected and updated in place.
ui-kit:install-module <slug>...Installs one or more modules into an existing install. Slugs can be space- or comma-separated; the batch is validated first, and one unknown slug aborts the whole run. ui-kit:install-modules is an alias.
ui-kit:list-modulesEvery module with its installed state.
ui-kit:make-admin {email?}Grants admin: the Spatie admin role when that module is installed, the is_admin flag when the column exists. No email promotes the first user.
ui-kit:doctorThe health check below.

What the doctor checks

CheckFails when
Published filesAny of the two configs, two route files, CSS or JS is missing
Auto-loaded routesA route file lacks the ui-kit:managed header (reported as a skip)
Fortify views disabledconfig/fortify.php is missing or views is not false
Vite wiringapp.css does not import ui-kit.css, or app.js does not import ./ui-kit
UiKitUser trait appliedThe trait was generated but app/Models/User.php does not use it
Storage linkedThe profile module is installed and public/storage is missing
Two-factor columnsThe profile module is installed and users.two_factor_secret is absent
No duplicate route namesTwo routes share a name, which would break route:cache
Mail from addressMAIL_FROM_ADDRESS is unset or still the default (a skip, not a failure)

Every failure prints the command that fixes it.

Was this page helpful?