Laravel 13 shipped with a polished Vue starter kit, Livewire 4 keeps gaining adoption, and plenty of teams still swear by a decoupled API with a standalone Vue SPA. If you are starting a new Laravel + Vue project in 2026, which approach actually makes sense?
This guide compares all three stacks using the official Laravel 13 starter kits as the baseline, with real code snippets, architecture trade-offs, and a decision framework you can use today.
Table of Contents
- The Three Approaches
- Official Laravel 13 Vue Starter Kit (Inertia)
- Livewire 4 + Blade
- Decoupled API + Vue SPA
- Side-by-Side Comparison
- When to Pick Which Stack
- FAQ
The Three Approaches at a Glance
| Inertia + Vue | Livewire 4 | API + Vue SPA | |
|---|---|---|---|
| Frontend | Vue 3, TypeScript | Blade, Flux UI | Vue 3, TypeScript |
| Routing | Server-side (Laravel) | Server-side (Laravel) | Client-side (Vue Router) |
| API layer | None needed | None needed | REST or GraphQL |
| Auth | Fortify / WorkOS | Fortify / WorkOS | Sanctum / Passport |
| Deployment | Single app | Single app | Two apps (or mono-repo) |
Official Laravel 13 Vue Starter Kit (Inertia)
The official Vue starter kit is the path of least resistance for Laravel + Vue teams. It pairs Inertia 2 with Vue 3 Composition API, TypeScript, Tailwind, and shadcn-vue out of the box.
Scaffolding a new project
composer global require laravel/installer
laravel new my-app
# Select "Vue with Inertia" when prompted
cd my-app
npm install && npm run build
composer run devYour app is live at http://localhost:8000 with authentication, profile management, and dark mode already wired up.
Project structure
resources/js/
├── components/ # Reusable Vue components
├── composables/ # Vue composables / hooks
├── layouts/ # Sidebar and header layouts
├── lib/ # Utility functions
├── pages/ # Page components (one per route)
└── types/ # TypeScript definitionsEvery page is a standard Vue single-file component. Inertia turns your Laravel routes and controllers into the router, so there is no separate Vue Router config to maintain.
A typical Inertia page
<script setup lang="ts">
import AppLayout from '@/layouts/AppLayout.vue'
import { Head } from '@inertiajs/vue3'
defineProps<{
projects: Array<{ id: number; name: string; status: string }>
}>()
</script>
<template>
<AppLayout>
<Head title="Projects" />
<ul>
<li v-for="project in projects" :key="project.id">
{{ project.name }} — {{ project.status }}
</li>
</ul>
</AppLayout>
</template>The controller that feeds this page looks exactly like a normal Laravel controller:
use Inertia\Inertia;
class ProjectController extends Controller
{
public function index()
{
return Inertia::render('Projects/Index', [
'projects' => auth()->user()
->projects()
->select('id', 'name', 'status')
->latest()
->paginate(20),
]);
}
}No dedicated API, no manual JSON serialization — Inertia handles the request/response bridge between Laravel and Vue.
Layout options
The starter kit ships with two primary layouts you can swap in resources/js/layouts/AppLayout.vue:
// Sidebar layout (default)
import AppLayout from '@/layouts/app/AppSidebarLayout.vue'
// Header layout
import AppLayout from '@/layouts/app/AppHeaderLayout.vue'There are also sidebar variants (sidebar, inset, floating) and multiple auth page layouts (simple, card, split).
Authentication out of the box
Fortify registers routes for login, registration, password reset, email verification, and two-factor authentication. If you need social login or passkeys, you can swap in WorkOS AuthKit during project creation.
Livewire 4 + Blade
The Livewire starter kit uses Livewire 4, Blade, Tailwind, and Flux UI components. It targets teams that prefer to stay in PHP and avoid a JavaScript build step for most features.
When Livewire works well
- CRUD-heavy admin panels and internal tools
- Forms with server-side validation that update in real time
- Teams where everyone knows Laravel but not everyone knows Vue
Where Livewire hits its ceiling
Highly interactive UIs — drag-and-drop builders, real-time collaborative editors, complex chart dashboards — push you back toward JavaScript anyway. Every interaction round-trips to the server, which adds latency that Vue handles client-side.
A Livewire component
use Livewire\Component;
class ProjectList extends Component
{
public string $search = '';
public function render()
{
return view('livewire.project-list', [
'projects' => auth()->user()
->projects()
->where('name', 'like', "%{$this->search}%")
->latest()
->paginate(20),
]);
}
}<div>
<input wire:model.live.debounce.300ms="search" placeholder="Search projects..." />
<ul>
@foreach($projects as $project)
<li>{{ $project->name }} — {{ $project->status }}</li>
@endforeach
</ul>
{{ $projects->links() }}
</div>Simple, effective, and zero JavaScript. But notice the wire:model.live — every keystroke triggers a server round-trip (debounced at 300ms). For a search field this is fine. For a drawing canvas or a drag-and-drop interface, it is not.
Decoupled API + Vue SPA
The third approach is a full separation: Laravel serves a JSON API, Vue runs as an independent SPA with its own router. This is the traditional pattern before Inertia existed.
When it makes sense
- You need the same API for a mobile app, a third-party integration, or a public developer platform
- The frontend and backend teams deploy independently
- You want full offline-first or PWA capability
Typical setup
# Backend
laravel new api-backend
cd api-backend
php artisan install:api # Installs Sanctum + API routes
# Frontend (separate repo or directory)
npm create vue@latest frontend -- --typescript
cd frontend
npm install axios vue-router piniaAPI controller
use App\Http\Resources\ProjectResource;
class ProjectController extends Controller
{
public function index()
{
return ProjectResource::collection(
auth()->user()
->projects()
->latest()
->paginate(20)
);
}
}Vue page with Axios
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import axios from 'axios'
interface Project {
id: number
name: string
status: string
}
const projects = ref<Project[]>([])
onMounted(async () => {
const { data } = await axios.get('/api/projects')
projects.value = data.data
})
</script>
<template>
<ul>
<li v-for="project in projects" :key="project.id">
{{ project.name }} — {{ project.status }}
</li>
</ul>
</template>This works, but you are now maintaining two routers, two auth flows, CORS configuration, API versioning, and separate deployments. That is a meaningful cost.
Side-by-Side Comparison
| Criteria | Inertia + Vue | Livewire 4 | API + Vue SPA |
|---|---|---|---|
| Time to first feature | Fast (starter kit) | Fast (starter kit) | Slower (manual wiring) |
| UI complexity ceiling | High | Medium | High |
| SEO | SSR available | Server-rendered | Requires SSR setup |
| Auth complexity | Low (Fortify built in) | Low (Fortify built in) | Medium (Sanctum + SPA cookies) |
| Team skill requirement | PHP + Vue/TS | PHP + Blade | PHP + Vue/TS + API design |
| Mobile API reuse | Needs separate API routes | Needs separate API routes | Built in |
| Deployment | Single server | Single server | Two targets |
| Offline support | Limited | None | Full PWA possible |
| State management | Props + composables | Server state | Pinia / composables |
When to Pick Which Stack
Pick Inertia + Vue if you are building a web application where the backend and frontend are owned by the same team, you want the SPA feel without API overhead, and your team is comfortable with Vue and TypeScript. This is the default recommendation for most Laravel + Vue projects in 2026.
Pick Livewire if your team is PHP-first, the product is form and table heavy, and you do not need rich client-side interactivity. Livewire gets you to production faster when the UI is straightforward.
Pick API + Vue SPA if you need a shared API for mobile or third-party consumers, your frontend and backend teams deploy independently, or you require offline-first capability.
The hybrid option
These approaches are not mutually exclusive. A common 2026 pattern is to use Inertia for the main application, add a few Livewire components for admin-only pages, and expose a public API for mobile clients. Laravel does not force you into one lane.
Frequently Asked Questions
Can I use Vue without Inertia in Laravel 13?
Yes. You can install Vue via Vite in any Laravel project and use it as a traditional SPA that talks to a Laravel API. The starter kit just makes the Inertia path the easiest to scaffold.
Is Inertia.js the same as a single-page application?
Inertia gives you the feel of an SPA — no full page reloads, smooth transitions — but routing and controllers stay on the server. You do not write a separate API or manage client-side routing. It is a monolith that behaves like an SPA.
Does Livewire replace Vue?
Not exactly. Livewire replaces the need for Vue in many CRUD-oriented interfaces. But if you need complex client-side state, animations, or offline support, Vue (with or without Inertia) is still the better tool.
Can I add Inertia to an existing Laravel project?
Yes. You can install the inertiajs/inertia-laravel package and the @inertiajs/vue3 npm package into an existing project. The official Laravel docs cover the manual setup.
What about server-side rendering (SSR) with Inertia?
Inertia 2 supports SSR out of the box. You enable it in your Vite config and deploy a small Node.js process alongside your Laravel app. If you are upgrading, check our Inertia v3 beta breakdown for the latest SSR changes.
How does authentication differ between these stacks?
Both the Inertia and Livewire starter kits use Laravel Fortify with full session-based auth, including 2FA and email verification. The API SPA approach typically uses Laravel Sanctum with SPA cookie authentication or API tokens.
Where to Go from Here
- If you are upgrading an existing project, read our Laravel 13 upgrade guide for Vue teams
- For authentication deep-dives, see Laravel + Vue Auth with Sanctum: SPA Best Practices
- For production architecture tips, check 9 Production Patterns That Actually Scale
- For the latest Inertia changes, see our Inertia.js v3 Beta Breakdown