PHPackages                             mjoc1985/laravel-inertia-helpers - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. mjoc1985/laravel-inertia-helpers

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

mjoc1985/laravel-inertia-helpers
================================

Backend and frontend utilities for common Inertia.js + Laravel patterns. Type-safe shared data, flash messages, pagination, filters, sorting, and breadcrumbs.

v0.3.0(2mo ago)041MITTypeScriptPHP ^8.2

Since Feb 18Pushed 2mo agoCompare

[ Source](https://github.com/mjoc1985/laravel-inertia-helpers)[ Packagist](https://packagist.org/packages/mjoc1985/laravel-inertia-helpers)[ Docs](https://github.com/mjoc1985/laravel-inertia-helpers)[ RSS](/packages/mjoc1985-laravel-inertia-helpers/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (6)Versions (4)Used By (0)

Laravel Inertia Helpers
=======================

[](#laravel-inertia-helpers)

A collection of backend and frontend utilities for common [Inertia.js](https://inertiajs.com/) + [Laravel](https://laravel.com/) patterns. Type-safe, unopinionated about styling, and designed to eliminate the boilerplate every Inertia project ends up writing.

[![Latest Version on Packagist](https://camo.githubusercontent.com/d8c7a5794b0a1ad1500ee7dd6ada317cc08b41b33f9b562f733badb4cc579a9c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d6a6f63313938352f6c61726176656c2d696e65727469612d68656c706572732e737667)](https://packagist.org/packages/mjoc1985/laravel-inertia-helpers)[![npm version](https://camo.githubusercontent.com/0f8a7cfed0be53540f406b1cc14d28318d7071f42f6e07f0b7f0745afc1b3a7c/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f406d6a6f63313938352f696e65727469612d68656c706572732e737667)](https://www.npmjs.com/package/@mjoc1985/inertia-helpers)[![License: MIT](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](LICENSE.md)

---

Why?
----

[](#why)

Every Inertia.js + Laravel project ends up solving the same problems:

- Accessing shared data (auth user, flash messages) without type safety
- Wiring up flash messages with auto-dismiss and stacking
- Building pagination controls that work with Inertia's router
- Syncing filter/search forms with URL query parameters
- Managing breadcrumbs without duplicating logic across components

This package solves all of them with a clean, typed API on both sides of the stack.

---

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11+
- Vue 3.3+
- Inertia.js 2.x
- TypeScript 5+ (recommended but not required)

---

Installation
------------

[](#installation)

### Backend (Laravel)

[](#backend-laravel)

```
composer require mjoc1985/laravel-inertia-helpers
```

The service provider is auto-discovered. Optionally publish the config:

```
php artisan vendor:publish --tag=inertia-helpers-config
```

### Frontend (Vue 3)

[](#frontend-vue-3)

```
npm install @mjoc1985/inertia-helpers
```

---

Quick Start
-----------

[](#quick-start)

### 1. Zero-config shared data

[](#1-zero-config-shared-data)

The service provider automatically shares auth, flash messages, and breadcrumbs with Inertia — no middleware changes required. Just install the package and the `SharedData` service handles everything.

To customise the shared data, extend the `SharedData` class and rebind it in your `AppServiceProvider`:

```
// app/Services/CustomSharedData.php

use Illuminate\Http\Request;
use Mjoc1985\InertiaHelpers\SharedData;

class CustomSharedData extends SharedData
{
    public function auth(Request $request): array
    {
        $user = $request->user();

        return [
            'user' => $user ? [
                'id' => $user->id,
                'name' => $user->name,
                'email' => $user->email,
                'avatar_url' => $user->avatar_url,
                'roles' => $user->roles->pluck('name'),
            ] : null,
        ];
    }

    public function custom(Request $request): array
    {
        return [
            'app' => [
                'name' => config('app.name'),
                'environment' => app()->environment(),
            ],
        ];
    }
}
```

```
// app/Providers/AppServiceProvider.php

use Mjoc1985\InertiaHelpers\SharedData;
use App\Services\CustomSharedData;

public function register(): void
{
    $this->app->singleton(SharedData::class, CustomSharedData::class);
}
```

### 2. Define your shared data types

[](#2-define-your-shared-data-types)

```
// resources/js/types/inertia.d.ts

import type { SharedData } from '@mjoc1985/inertia-helpers'

// Extend with your app's user model
interface AppUser {
    id: number
    name: string
    email: string
    avatar_url: string | null
    roles: string[]
}

// Register your types globally
declare module '@mjoc1985/inertia-helpers' {
    interface SharedDataOverrides {
        auth: {
            user: AppUser | null
        }
    }
}
```

### 3. Use the composables

[](#3-use-the-composables)

```

import { useAuth, useFlash } from '@mjoc1985/inertia-helpers'

const { user, isAuthenticated, hasRole } = useAuth()
const { messages, dismiss } = useFlash()

        Welcome back, {{ user.name }}!

        {{ msg.text }}
        ×

```

---

Backend API
-----------

[](#backend-api)

### SharedData Service

[](#shareddata-service)

The `SharedData` service class structures all shared data into a predictable shape and is registered as a singleton. It is automatically wired into `Inertia::share()` by the service provider — no middleware changes needed.

**Public methods:**

MethodDescription`toArray(Request $request): array`Returns all shared data as lazy closures`auth(Request $request): array`User authentication payload`flash(Request $request): array`Flash messages`breadcrumbs(Request $request): array`Breadcrumb trail`custom(Request $request): array`Override hook, returns `[]` by defaultTo customise, extend and rebind (see [Quick Start](#1-zero-config-shared-data)).

**What gets shared automatically:**

```
[
    'auth' => [
        'user' => [...] | null,
    ],
    'flash' => [
        'success' => '...' | null,
        'error' => '...' | null,
        'warning' => '...' | null,
        'info' => '...' | null,
    ],
    'breadcrumbs' => [
        ['label' => 'Home', 'url' => '/'],
        ['label' => 'Users', 'url' => '/users'],
        ['label' => 'John Doe', 'url' => null], // current page, no link
    ],
]
```

### Flash Messages — Enhanced

[](#flash-messages--enhanced)

Beyond Laravel's basic `session()->flash()`, the package provides a fluent API for richer flash messages:

```
use Mjoc1985\InertiaHelpers\Flash;

// Simple usage (works with standard Laravel flash)
return redirect()->route('users.index')->with('success', 'User created.');

// Rich flash messages with metadata
Flash::success('User created successfully.')
    ->action('View User', route('users.show', $user))
    ->autoDismiss(5000) // milliseconds, or false to persist
    ->send();

Flash::error('Payment failed.')
    ->detail('Your card was declined. Please try a different payment method.')
    ->autoDismiss(false) // errors should persist
    ->send();

Flash::warning('Your trial expires in 3 days.')
    ->action('Upgrade Now', route('billing.plans'))
    ->send();

// Stack multiple flash messages
Flash::success('Project saved.')->send();
Flash::info('Collaborators have been notified.')->send();
```

### Breadcrumbs

[](#breadcrumbs)

Register breadcrumbs in a dedicated file, referenced by route name:

```
// routes/breadcrumbs.php (auto-loaded by the service provider)

use Mjoc1985\InertiaHelpers\Breadcrumbs;

Breadcrumbs::for('home', function ($trail) {
    $trail->push('Home', route('home'));
});

Breadcrumbs::for('users.index', function ($trail) {
    $trail->parent('home');
    $trail->push('Users', route('users.index'));
});

Breadcrumbs::for('users.show', function ($trail, $user) {
    $trail->parent('users.index');
    $trail->push($user->name); // no URL = current page
});

Breadcrumbs::for('users.edit', function ($trail, $user) {
    $trail->parent('users.show', $user);
    $trail->push('Edit');
});
```

Breadcrumbs are resolved automatically based on the current route and shared via the `SharedData` service. Route model binding works as expected — the parameters from the current route are passed to the breadcrumb callback.

**Config (config/inertia-helpers.php):**

```
return [
    'breadcrumbs' => [
        // Path to your breadcrumb definitions
        'file' => base_path('routes/breadcrumbs.php'),

        // Include 'Home' automatically on every trail
        'auto_home' => true,

        // Route name for the home breadcrumb
        'home_route' => 'home',
    ],

    'flash' => [
        // Default auto-dismiss duration in milliseconds
        'auto_dismiss' => 5000,

        // Flash types to share (maps to session keys)
        'types' => ['success', 'error', 'warning', 'info'],
    ],
];
```

### Pagination — Backend Helper

[](#pagination--backend-helper)

A macro on Laravel's LengthAwarePaginator that formats pagination data cleanly for the frontend composable:

```
// In a controller
public function index(Request $request)
{
    $users = User::query()
        ->filter($request->only(['search', 'role', 'status']))
        ->sort($request->get('sort', 'name'), $request->get('direction', 'asc'))
        ->paginate(15)
        ->withQueryString();

    return inertia('Users/Index', [
        'users' => $users,
        'filters' => $request->only(['search', 'role', 'status']),
        'sort' => [
            'field' => $request->get('sort', 'name'),
            'direction' => $request->get('direction', 'asc'),
        ],
    ]);
}
```

---

Frontend API
------------

[](#frontend-api)

### useAuth()

[](#useauth)

Type-safe access to the authenticated user.

```

import { useAuth } from '@mjoc1985/inertia-helpers'

const { user, isAuthenticated, isGuest, hasRole, hasAnyRole } = useAuth()

            {{ user.name }}

```

**API:**

```
interface UseAuthReturn {
    /** The authenticated user, or null. Reactive. */
    user: ComputedRef

    /** Whether a user is authenticated. Reactive. */
    isAuthenticated: ComputedRef

    /** Whether no user is authenticated. Reactive. */
    isGuest: ComputedRef

    /** Check if the user has a specific role */
    hasRole: (role: string) => boolean

    /** Check if the user has any of the given roles */
    hasAnyRole: (...roles: string[]) => boolean
}
```

### useFlash()

[](#useflash)

Manages flash messages with auto-dismiss, stacking, and lifecycle.

```

import { useFlash } from '@mjoc1985/inertia-helpers'

const { messages, dismiss, dismissAll, onFlash } = useFlash()

// Optional: react to new flash messages (returns an unsubscribe function)
const unsubscribe = onFlash((message) => {
    if (message.type === 'error') {
        console.error('Flash error:', message.text)
    }
})
// Call unsubscribe() when you no longer need the callback

                    {{ msg.text }}
                    {{ msg.detail }}

                ×

                {{ msg.action.label }}

```

**API:**

```
interface FlashMessage {
    id: string
    type: 'success' | 'error' | 'warning' | 'info'
    text: string
    detail?: string
    action?: { label: string; url: string }
    autoDismiss: number | false     // milliseconds or false
    remainingPercent: number         // 100 → 0, reactive, for progress bars
    createdAt: number
}

interface UseFlashReturn {
    /** All currently visible flash messages. Reactive. */
    messages: ComputedRef

    /** Dismiss a specific message by ID */
    dismiss: (id: string) => void

    /** Dismiss all messages */
    dismissAll: () => void

    /** Register a callback for new flash messages. Returns an unsubscribe function. */
    onFlash: (callback: (message: FlashMessage) => void) => () => void
}
```

### usePagination()

[](#usepagination)

Wraps an Inertia paginator response with reactive controls.

```

import { usePagination } from '@mjoc1985/inertia-helpers'

const props = defineProps
