inertia start
Features

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:

RoleAdmin areaAuthorization gates
Super AdminYesBypasses every non-team-scoped gate
AdminYesGoes 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:

.env
I_S_APP_ADMIN_LAYOUT=sidebar # or header

The navigation contains:

ItemRouteShown when
Dashboardadmin.dashboard (/admin/dashboard)Always
Usersadmin.users.index (/admin/users)Always
BillingProvider dashboard, Component Builder, Products, and SubscriptionsBilling 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:

PagePathPurpose
Provider dashboardStripe or Paddle dashboard (new tab)Customers, payments, and payouts on the provider side
Component Builder/admin/billing/component-builderPreview and generate CheckoutButton, CheckoutSection, and PricingCards code
Products/admin/billing/productsNo-code editor for one-time products
Subscriptions/admin/billing/subscriptionsNo-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:

TypeTriggerDetails
User createdA user account is created.User email and ID, and a link to the user in the admin area.
User deletedA user account is deleted.User email and ID captured before personal fields are cleared.

Configuration

.env
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 keyEnvironment variableDefault
admin_notifications.recipientsI_S_ADMIN_NOTIFICATIONS_RECIPIENTS[]
admin_notifications.deliveryI_S_ADMIN_NOTIFICATIONS_DELIVERYqueued
admin_notifications.queueI_S_ADMIN_NOTIFICATIONS_QUEUEnull (connection default)

Delivery modes

I_S_ADMIN_NOTIFICATIONS_DELIVERY controls how emails are sent. Any other value falls back to queued.

ModeBehaviorRequires
immediateOne email per event, sent during the request or commandNothing
queuedOne email per event, sent in the backgroundA queue worker
digestEvents grouped into one daily email at 6pmA 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.

.env
I_S_ADMIN_NOTIFICATIONS_QUEUE=admin-notifications

Make sure a worker listens to that queue. For example, to process admin notifications and the default queue:

php artisan queue:work --queue=admin-notifications,default

The queue connection continues to use QUEUE_CONNECTION.

Digests

Use the digest mode to combine events into one email:

.env
I_S_ADMIN_NOTIFICATIONS_RECIPIENTS=[email protected],[email protected]
I_S_ADMIN_NOTIFICATIONS_DELIVERY=digest
I_S_ADMIN_NOTIFICATIONS_QUEUE=
QUEUE_CONNECTION=database

By 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:

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:work

See 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

FileResponsibility
app/Observers/UserObserver.phpCaptures creation and deletion events
app/Services/AdminNotificationService.phpSnapshots, transaction handling, and delivery mode
app/Notifications/AdminUsersChanged.phpSubjects and content of individual emails and digests
app/Jobs/SendAdminDigest.phpDelivers pending digests and clears them after success
resources/views/mail/admin/users_changed.blade.phpEmail template
routes/console.phpDigest 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

FileResponsibility
routes/admin.phpAdmin routes and middleware
app/Http/Middleware/IsAdmin.phpRestricts access to admins
app/Http/Controllers/Admin/DashboardController.phpRenders the dashboard
app/Http/Controllers/Admin/UserController.phpUsers list and user details
app/Http/Controllers/Admin/BillingConfigController.phpProducts and subscriptions editors
resources/js/layouts/AdminLayout.vueAdmin layout and navigation
resources/js/pages/admin/Admin pages
app/Listeners/SecurityEventSubscriber.phpSends security alerts to Super Admins

On this page