Admin Area
A protected back office to follow your users, manage your billing catalog, and receive admin notifications about your application.
Inertia Start ships a dedicated admin area at /admin, separate from the user-facing app and account pages. It gives you a place to follow who visits and signs up, inspect a single user's journey and activity, and manage your billing catalog without touching code. Outside the browser, admin notifications keep the people running the application informed by email.
Accessing the admin area
Every admin route lives in routes/admin.php under the /admin prefix and the auth, verified, and admin middleware. Only signed-in, verified users with the Super Admin or Admin role can open it (checked through the computed is_admin attribute); everyone else gets a 403 response.
Both roles open the admin area, but they differ in how they go through authorization:
| Role | Admin area | Authorization gates |
|---|---|---|
| Super Admin | Yes | Bypasses every non-team-scoped gate |
| Admin | Yes | Goes through normal authorization checks |
The first Super Admin is created by the setup wizard at /setup. On the teams branch, admins are the members of the reserved App Admins team, and Super Admins can invite more from the team settings page.
See Roles & Permissions for the is_admin attribute, the IsAdmin middleware, and the Super Admin gate bypass, and Teams for the App Admins team.
Layout and navigation
The admin area uses its own AdminLayout (resources/js/layouts/AdminLayout.vue), with a breadcrumb trail, the app footer, and a link back to the application. Like the app layout, it comes in two variants, selected with an environment variable:
I_S_APP_ADMIN_LAYOUT=sidebar # or headerThe navigation contains:
| Item | Route | Shown when |
|---|---|---|
| Dashboard | admin.dashboard (/admin/dashboard) | Always |
| Users | admin.users.index (/admin/users) | Always |
| Billing | Provider dashboard, Component Builder, Products, and Subscriptions | Billing is enabled |
To add your own page, register the route inside the group in routes/admin.php, so it inherits the admin middleware, then add an entry to mainNavItems in AdminLayout.vue.
Dashboard
The dashboard (resources/js/pages/admin/Dashboard.vue, rendered by App\Http\Controllers\Admin\DashboardController) is the landing page of the admin area. It ships as an empty grid of placeholder panels, ready for the metrics that matter to your product: signups, revenue, active subscriptions, and so on. Pass the data from the controller as Inertia props and replace the placeholders with your own components.
Users
Users list
/admin/users lists every visitor context, not only registered users, so you can see guests alongside the people who signed up. The table is built with Inertia Table and shows, for each row:
- the email address, or Guest for visitors who have not registered
- the first visit, last activity, registration, and conversion dates, each with the time elapsed
Rows are sorted by first visit by default. You can sort by any of the four dates and display 10, 25, 50, or 100 rows per page. The controller also accepts an email filter (filter[email]), which you can expose with the table's search prop. The action button opens the user's details page; for a guest, it shows how to find the visitor's session in Umami when Umami analytics is configured.
User details
/admin/users/{user} brings together everything known about one user:
- Analytics and tracking: the lifecycle timeline (first visit, registration, conversion, last activity), the acquisition source with UTM parameters, landing page and referrer, and a shortcut to the user's Umami session. See What the admin shows.
- Activity: the user's activity log, including profile and security changes and rate-limited requests.
Billing
When billing is enabled, the Billing menu groups the tools for running your catalog:
| Page | Path | Purpose |
|---|---|---|
| Provider dashboard | Stripe or Paddle dashboard (new tab) | Customers, payments, and payouts on the provider side |
| Component Builder | /admin/billing/component-builder | Preview and generate CheckoutButton, CheckoutSection, and PricingCards code |
| Products | /admin/billing/products | No-code editor for one-time products |
| Subscriptions | /admin/billing/subscriptions | No-code editor for subscription groups and plans |
See Component Builder and No-code config editors in the billing documentation.
Admin notifications
Admin notifications send emails about the application lifecycle to a list of recipients. Set the recipients as a comma-separated list of email addresses in I_S_ADMIN_NOTIFICATIONS_RECIPIENTS; with no recipients, no emails are sent. Whitespace and duplicate addresses are removed when the configuration is loaded.
Recipients are plain email addresses: they don't need an account in the application and are unrelated to the Admin and Super Admin roles. These are on-demand notifications, independent of any user's notification preferences.
Notification types
The starter kit currently includes these types:
| Type | Trigger | Details |
|---|---|---|
| User created | A user account is created. | User email and ID, and a link to the user in the admin area. |
| User deleted | A user account is deleted. | User email and ID captured before personal fields are cleared. |
Configuration
I_S_ADMIN_NOTIFICATIONS_RECIPIENTS=[email protected],[email protected]
I_S_ADMIN_NOTIFICATIONS_DELIVERY=queued
I_S_ADMIN_NOTIFICATIONS_QUEUE=These settings live under the admin_notifications key of config/inertia-start.php:
| Config key | Environment variable | Default |
|---|---|---|
admin_notifications.recipients | I_S_ADMIN_NOTIFICATIONS_RECIPIENTS | [] |
admin_notifications.delivery | I_S_ADMIN_NOTIFICATIONS_DELIVERY | queued |
admin_notifications.queue | I_S_ADMIN_NOTIFICATIONS_QUEUE | null (connection default) |
Delivery modes
I_S_ADMIN_NOTIFICATIONS_DELIVERY controls how emails are sent. Any other value falls back to queued.
| Mode | Behavior | Requires |
|---|---|---|
immediate | One email per event, sent during the request or command | Nothing |
queued | One email per event, sent in the background | A queue worker |
digest | Events grouped into one daily email at 6pm | A queue worker and the scheduler |
In every mode, when an event happens inside a database transaction, delivery waits until the transaction commits. Rolled-back changes do not produce admin notifications.
Immediate emails
With I_S_ADMIN_NOTIFICATIONS_DELIVERY=immediate, each event sends one email right away, without involving the queue.
Queued emails
Queued delivery is the default. Each event queues one email to the recipients.
Use an asynchronous QUEUE_CONNECTION, such as database or redis, and run a queue worker. Laravel's sync connection executes jobs immediately and does not move delivery into the background. The development processes started by composer run dev include a worker; configure a persistent worker for your deployed application. See the Laravel queue documentation.
Choosing the queue
Set I_S_ADMIN_NOTIFICATIONS_QUEUE to choose the queue for both queued emails and digest jobs. Leave it empty to use the default queue configured on your application's queue connection. Immediate delivery ignores this setting.
I_S_ADMIN_NOTIFICATIONS_QUEUE=admin-notificationsMake sure a worker listens to that queue. For example, to process admin notifications and the default queue:
php artisan queue:work --queue=admin-notifications,defaultThe queue connection continues to use QUEUE_CONNECTION.
Digests
Use the digest mode to combine events into one email:
I_S_ADMIN_NOTIFICATIONS_RECIPIENTS=[email protected],[email protected]
I_S_ADMIN_NOTIFICATIONS_DELIVERY=digest
I_S_ADMIN_NOTIFICATIONS_QUEUE=
QUEUE_CONNECTION=databaseBy default, digests run daily at 6pm in the application's timezone (config/app.php, UTC by default). Each run sends all pending events in one email. If there are no pending events, no email is sent.
For example, a user created at 10:00 and another deleted at 14:00 appear in the digest scheduled for 18:00 that day. A user created after that digest is sent appears in the following day's digest. A digest lists each event and the total numbers of created and deleted users. A user created and deleted during the same period appears in both events.
To change the time or frequency, edit the digest schedule in routes/console.php:
Schedule::job(SendAdminDigest::class)->dailyAt('18:00');Change the time passed to dailyAt(), or replace it with another Laravel scheduler frequency method. The schedule is registered only when digest delivery is enabled and recipients are configured.
Pending snapshots are stored in the admin_notification_digests table. At the scheduled time, routes/console.php queues App\Jobs\SendAdminDigest. Run both the Laravel scheduler and a queue worker in your deployed application. For local scheduler testing:
php artisan schedule:workSee the Laravel scheduler documentation. Queue delays can make delivery later than the scheduled time. Each scheduled run queues a job; the job skips sending when the digest is empty.
A database row lock protects the digest from concurrent writes and workers. The job also uses Laravel's unique-job cache lock to avoid duplicate queued jobs; use a shared cache when running multiple servers. A digest is cleared only after mail delivery succeeds. If delivery fails, the job retries up to three times with a 60-second backoff, and a later scheduled run can queue another attempt while the digest remains pending. As with other queued emails, a process interruption after the mail provider accepts a message can cause a duplicate on retry.
If you remove the recipients or switch to another delivery mode, pending events stay in the database and are sent once digests are enabled again. Digests use the current recipient list when they are delivered.
Event details and account deletion
Individual emails and digests contain a list of users with their email and ID. Created-user entries include a link to the user in the admin area. Deletion entries capture the identity before the account's personal fields are cleared.
Every individual email and digest also includes the total number of existing users, excluding soft-deleted accounts. This total is calculated when the email is prepared for sending, so queued emails reflect the current user count rather than the count when the event occurred.
Snapshots also let queued creation emails be delivered after the user has been deleted. Digest snapshots are removed from the digest table after successful delivery.
The observer covers normal Eloquent creations and deletions, including registration, admin actions, and application code. Permanently removing an already soft-deleted user does not send another deletion email. Bulk query deletes and operations using withoutEvents() do not trigger model observers.
Customizing admin notifications
| File | Responsibility |
|---|---|
app/Observers/UserObserver.php | Captures creation and deletion events |
app/Services/AdminNotificationService.php | Snapshots, transaction handling, and delivery mode |
app/Notifications/AdminUsersChanged.php | Subjects and content of individual emails and digests |
app/Jobs/SendAdminDigest.php | Delivers pending digests and clears them after success |
resources/views/mail/admin/users_changed.blade.php | Email template |
routes/console.php | Digest schedule: daily at 6pm by default |
Security alerts
Separately from admin notifications, every Super Admin receives a Suspicious Activity email when a rate limiter reaches its abuse threshold, for example on repeated login or password reset attempts. The email includes the action, route, IP address, user agent, user ID when known, and request parameters. These alerts go to Super Admin accounts, not to I_S_ADMIN_NOTIFICATIONS_RECIPIENTS.
See Activity Logging for how rate-limited requests are recorded.
Key files
| File | Responsibility |
|---|---|
routes/admin.php | Admin routes and middleware |
app/Http/Middleware/IsAdmin.php | Restricts access to admins |
app/Http/Controllers/Admin/DashboardController.php | Renders the dashboard |
app/Http/Controllers/Admin/UserController.php | Users list and user details |
app/Http/Controllers/Admin/BillingConfigController.php | Products and subscriptions editors |
resources/js/layouts/AdminLayout.vue | Admin layout and navigation |
resources/js/pages/admin/ | Admin pages |
app/Listeners/SecurityEventSubscriber.php | Sends security alerts to Super Admins |