nunomaduro/laravel-starter-kit-inertia-vue
A Laravel starter kit that pairs the framework with Inertia.js and Vue, giving you a ready-made SPA-style application scaffold with authentication, a modern frontend stack, and sensible defaults so you can skip boilerplate and start building features right away.
This is a starter kit, not a runtime dependency. There is no composer require path — its value is entirely in the scaffolding decision made on day one, so the "day-to-day leverage" question is really "what does my application look like for the next two years if I start here."
First steps
laravel new --using=nunomaduro/laravel-starter-kit-inertia-vue or composer create-project), then commit the generated tree as your baseline before touching anything. Record the kit version (currently v1.9.0) in your README — you will need it to diff later.AGENTS.md and the .ai/ rule files before writing code — they are the actual specification of this kit. They encode: the Action pattern, PHP 8.5 conventions, Inertia v3 idioms, Fortify auth ownership, Wayfinder typed routes, and Boost-first workflows.composer run dev (which fans out to npm run dev + queue + Pail). If the UI shows stale content, that's a missing build, not a bug — see Gotchas.app/Actions, routes/, resources/js/pages, and app/Actions/Fortify.v1.9.0 fixed a reset form that posted to the settings password route instead of the reset route — cheap to verify on your own copy, expensive to discover in production.First real use case
Ship one end-to-end feature the kit's way rather than the fastest way — e.g. "toggle a favorite":
php artisan make:action "ToggleFavorite" --no-interaction → a final readonly class with a single handle().Inertia::render('favorites/index', [...]).resources/js/pages that calls the backend through a Wayfinder-generated function (import { store } from '@/actions/App/Http/Controllers/FavoriteController'), not a hardcoded URL.If that loop feels natural after one feature, the kit is paying for itself. If it fights you, that is your signal to bail — cheaply, on day one.
Business logic lives in Actions, everywhere. The kit's central claim is that app/Actions is the only seam for logic, so the same class is called from HTTP controllers, queued jobs, Artisan commands, and MCP tools. Follow it literally: one handle() method, dependencies injected via promoted constructor properties, DB::transaction() inside the action when more than one model is written. Controllers become 5-line adapters. This is the single highest-leverage habit the kit teaches, and it survives even if you later swap the frontend.
Typed routes via Wayfinder. Frontend never hardcodes URLs. Use .url(), .get(), .post(), .form() from @/actions and @/routes; .form() in particular is the idiomatic fit for Inertia form submissions. Route model bindings flow through as typed arguments. Regenerate on route changes (wayfinder:generate, or rely on the Vite plugin in dev).
Inertia v3 idioms, not v1 muscle memory. Reach for Inertia::defer() + an animated skeleton component for slow panels, Inertia::optional() where you used to write Inertia::lazy(), Inertia::merge() for paginated feeds, and the useHttp hook for standalone requests that shouldn't be page visits. Optimistic updates with automatic rollback are the right pattern for toggles and reorders — no manual router.reload().
Auth is Fortify's job. Login, registration, password reset, 2FA, and profile updates are registered by Fortify; customize by editing the actions in app/Actions/Fortify (CreateNewUser, UpdateUserProfileInformation) and config/fortify.php, not by hand-rolling auth controllers. Note this means "add social login" is a Socialite task layered outside this pattern, not a Fortify one.
Extend the browser tests when you touch auth pages. The kit now ships a browser test asserting the reset-password form posts to the correct route — a reminder that auth page wiring (which route() the form targets) is the fragile seam, not the PHP behind it. When you customise a Fortify page, add or adapt the matching browser test rather than trusting a feature test that only exercises the action.
Testing as the verification mechanism. The rules explicitly forbid throwaway tinker/verification scripts — write a Pest feature test instead and run php artisan test --compact --filter=.... Use factories and their named states rather than hand-built models. Run the full suite (feature and browser) before you diff against a new kit release, so you can tell a regression from an upstream change.
Boost as the daily driver. The kit assumes you work through Laravel Boost's MCP tools: search-docs before changing code (version-scoped to Laravel 13 / Inertia v3 / Fortify v1), database-schema before migrations, database-query instead of raw SQL, browser-logs for frontend exceptions. v1.9.0 floors Boost at ^2.10.0 — if your editor tooling predates that, upgrade before blaming the kit for stale docs.
v1.9.0's password-reset routing fix only helps people who scaffold after it. If you scaffolded earlier, your forgot-password flow can silently post to the settings route. Keep a pristine re-scaffold of the current tag in a scratch directory and diff -r it against your app after each release; cherry-pick the security- and auth-relevant hunks.^13.33.0 + Inertia v3 + Pest 5 + Wayfinder v0 (a 0.x!) + Boost ^2.10.0 means third-party packages will lag. Wayfinder being pre-1.0 is the sharpest edge — its generated import paths and plugin behaviour can shift under you, and every frontend file depends on it. Each point release moves these floors, so re-check composer.json constraints whenever you re-baseline.Inertia::lazy()/LazyProp are removed in favour of optional(), router.cancel() is now cancelAll(), events renamed (invalid → httpException, exception → networkError), and the future config namespace no longer exists. Copy-pasted v1/v2 snippets from blogs will silently misbehave.@/actions resolution errors, that's the cause before anything else.npm run build (or have npm run dev running), not by debugging PHP.tmp/. Since v1.9.0, Rector and PHPStan cache inside the project rather than in the system /tmp. Add tmp/ to .gitignore, include it in your CI cache path (and key that cache on your tool config files), and don't be surprised by a tmp/ directory appearing after the first static-analysis run.v1.9.0 bumps actions/checkout@v7, actions/cache@v6, actions/upload-artifact@v7. If you kept .github/workflows from an older scaffold, you own those stale versions — GitHub will nag you, and the old cache action may quietly degrade. Sync them manually.resources/js/pages unless vite.config.js says otherwise — moving them without updating the config yields blank Inertia responses.app/Actions (never a Services/ folder — it will fragment the pattern); override auth behaviour in app/Actions/Fortify + config/fortify.php; register custom Inertia exception handling for error pages rather than Blade error views; add per-page layout props via useLayoutProps instead of threading shared data through every controller.--no-interaction on all make: commands, no empty zero-parameter constructors, PHPDoc array shapes over inline comments. Pint + Larastan v3 at level-high are implied — run them before review, not after.How can I help you explore Laravel packages today?