inertia start
Features

Activity Logging

View and monitor user activity.

Inertia Start uses Spatie Laravel Activitylog to record events and store the metadata needed to display them cleanly in the UI.

Activity model

Inertia Start uses its custom App\Models\Activity model instead of the package default.

That custom model adds support for record expiration through alajusticia/laravel-expirable, which allows us to add an expiration date for specific logs.

What we log

We currently log account-related events, under the users log name:

  • account_requested
  • created
  • deleted
  • email_updated
  • password_created
  • password_updated
  • profile_updated

We also log request rate limiting under the throttle log name. A throttle activity is created when one of the built-in limiters reaches its configured maximum for actions such as login, registration, password reset, email change, or resend flows. Its activity description is the limiter key itself (for example login, register, password, email-modification, or email-specific variants such as login_<email>), and its properties include request context plus action, route, params, and nb_attempts.

At higher abuse thresholds, the app also dispatches a TooManyAttempts event so Super Admins can be notified about suspicious activity.

When an action changes data, Inertia Start stores the new values in properties.attributes and the previous values in properties.old, following the default data structure used by the laravel-activitylog package when enabling model events auto-logging:

app/Http/Controllers/Account/ProfileController.php
activity('users')
    ->by($request->user())
    ->on($request->user())
    ->withProperties([
        'attributes' => $newData,
        'old' => array_intersect_key($oldData, $newData),
    ])
    ->log('profile_updated');

Sensitive events also include request context such as IP address and user agent through Helpers::getRequestContext().

These are the built-in activity logs, but you can customize them or add new ones as needed.

Automatic expiration and purging

Inertia Start lets you decide which activity log names should expire automatically through the activity_log_lifetimes option in config/inertia-start.php.

config/inertia-start.php
'activity_log_lifetimes' => file_exists(config_path('env/activity_log_lifetimes.json'))
    ? json_decode(file_get_contents(config_path('env/activity_log_lifetimes.json')), true)
    : [
        'throttle' => '2 days',
    ],

Only the log names listed in this configuration are marked as expirable. When a matching activity is created, App\Models\Activity sets its expiration timestamp automatically.

This purge flow is powered by alajusticia/laravel-expirable, and Inertia Start already schedules the cleanup command in routes/console.php:

routes/console.php
Schedule::command('expirable:purge')->dailyAt('1:20');

If you want to purge additional log names periodically, add them to activity_log_lifetimes. A common way to override the default is to create config/env/activity_log_lifetimes.json.

Displaying activities

The shared UI for activity logs lives in resources/js/components/ActivityTable.vue.

This component is used in two places:

  • the account activity page
  • the admin user details page

ActivityTable.vue is built on top of Inertia Start’s InertiaTable component. It renders:

  • the activity date
  • the translated log category
  • the translated activity description
  • a "changes" dialog when properties.attributes or properties.old are present

It supports both modes used in the app:

  • server-provided paginated Inertia data for the account activity page
  • API fetching through useHttp() for the admin user page

Translations

Activity labels are translated from these language files:

  • lang/{locale}/messages.php
    • activity_log_names
    • activity_log_attributes
  • lang/{locale}/activities.php

ActivityTable.vue uses these keys to resolve labels:

  • messages.activity_log_names.<log_name>
  • messages.activity_log_attributes.<attribute>
  • activities.<log_name>.<description>

If you add a new log name, a new activity description, or a new tracked attribute, update these translation files so the activity table shows human-readable text instead of raw keys.

Extending the system

When adding a new activity type, the usual flow is:

  1. Create the log entry with the activity() helper.
  2. Use an appropriate log name. Prefer multiple log names to group related activities and make filtering easier when retrieving/purging logs.
  3. Add properties.attributes and properties.old if you want before/after values in the table dialog.
  4. Add translations in messages.activity_log_names, messages.activity_log_attributes, and the activities translation file.
  5. Optionally add the log name to activity_log_lifetimes if it should be purged automatically.

The account activity page currently lists only the users log. If you introduce additional log names and want to expose them in the UI, you'll need to adapt the controller queries and table filters.

On this page