Kritim Yantra
Jul 15, 2025
Imagine this: You're building a real-time dashboard with Laravel and Vue. Data flows everywhere—user preferences, API responses, UI state. How do you keep everything in sync without spaghetti code?
Enter Pinia �—the official Vue state management library that makes handling complex state simple and scalable.
In this guide, you’ll learn how to:
✅ Set up Laravel 12 + Vue 3 + Vite (optimized for speed)
✅ Integrate Pinia for flawless state management
✅ Build a real-world example (authentication + dynamic data)
(Already familiar? Jump to Step 2 for Pinia!)
composer create-project laravel/laravel laravel-pinia-spa
cd laravel-pinia-spa
npm install vue@next @vitejs/plugin-vue
npm install --save-dev vite laravel-vite-plugin
vite.config.js
)import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel(['resources/js/app.js']),
vue(),
],
});
resources/js/app.js
)import { createApp } from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
resources/views/welcome.blade.php
)<!DOCTYPE html>
<html>
<head>
@vite(['resources/js/app.js'])
</head>
<body>
<div id="app"></div>
</body>
</html>
🚀 Test it: Run npm run dev
and visit http://localhost:8000
.
npm install pinia
app.js
import { createApp } from 'vue';
import { createPinia } from 'pinia'; // <-- Add this
import App from './App.vue';
const app = createApp(App);
app.use(createPinia()); // <-- Use Pinia
app.mount('#app');
stores/counter.js
)import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
actions: {
increment() {
this.count++;
},
},
getters: {
doubleCount: (state) => state.count * 2,
},
});
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double: {{ counter.doubleCount }}</p>
<button @click="counter.increment()">+1</button>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter';
const counter = useCounterStore();
</script>
💡 Why Pinia?
✔ Simpler syntax than Vuex
✔ TypeScript support out of the box
✔ Devtools integration for debugging
stores/auth.js
)import { defineStore } from 'pinia';
import axios from 'axios';
export const useAuthStore = defineStore('auth', {
state: () => ({
user: null,
token: localStorage.getItem('token') || null,
}),
actions: {
async login(email, password) {
const res = await axios.post('/api/login', { email, password });
this.user = res.data.user;
this.token = res.data.token;
localStorage.setItem('token', this.token);
},
logout() {
this.user = null;
this.token = null;
localStorage.removeItem('token');
},
},
});
<script setup>
import { useAuthStore } from '@/stores/auth';
import { onMounted } from 'vue';
import { useRouter } from 'vue-router';
const auth = useAuthStore();
const router = useRouter();
onMounted(() => {
if (!auth.token) router.push('/login');
});
</script>
stores/posts.js
)import { defineStore } from 'pinia';
import axios from 'axios';
export const usePostsStore = defineStore('posts', {
state: () => ({
posts: [],
loading: false,
}),
actions: {
async fetchPosts() {
this.loading = true;
const res = await axios.get('/api/posts');
this.posts = res.data;
this.loading = false;
},
},
});
pinia-plugin-persistedstate
npm install pinia-plugin-persistedstate
Configure in app.js
:
import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
const pinia = createPinia();
pinia.use(piniaPluginPersistedstate);
app.use(pinia);
Make a store persistent:
defineStore('auth', {
persist: true, // <-- Add this
state: () => ({ ... }),
});
In your Blade file:
<script>
window.__INITIAL_STATE__ = @json(auth()->user() ? ['auth' => ['user' => auth()->user()]] : []);
</script>
Then in app.js
:
if (window.__INITIAL_STATE__) {
pinia.state.value = window.__INITIAL_STATE__;
}
You’ve now built a high-performance SPA with:
✅ Laravel 12 API backend
✅ Vue 3 + Vite for lightning-fast frontend
✅ Pinia for scalable state management
🚀 Try These Next:
💬 Let’s Discuss:
What’s your go-to state management solution in Vue? Pinia, Vuex, or something else?
✅ Yes! Install pinia@v2
for Vue 2 compatibility.
📌 Pinia is the official successor—simpler API, better TS support, no mutations!
⚡ Yes! Perfect for Nuxt.js or Laravel + Inertia SSR.
🔥 Your Turn: Share your Pinia experiences below! Struggles? Wins? Let’s chat. 👇
No comments yet. Be the first to comment!
Please log in to post a comment:
Sign in with Google