State Management with Pinia in Nuxt 4
Pinia is the official state management library for Vue 3, and it integrates seamlessly with Nuxt 4 using a simple manual plugin pattern.
Why Manual Plugin Instead of @pinia/nuxt?
The manual approach gives you:
- Full control over store initialization.
- No extra module dependency.
- Better Nuxt 4 compatibility with the new app/ directory structure.
The Plugin
Create app/plugins/pinia.ts:
``ts
import { createPinia } from 'pinia'
export default defineNuxtPlugin((nuxtApp) => {
const pinia = createPinia()
nuxtApp.vueApp.use(pinia)
})
`
That's it. No module, no extra config.
Creating a Store
Define stores with the composition API style:
`ts
// app/stores/darkMode.ts
import { defineStore } from 'pinia'
export const useDarkMode = defineStore('darkMode', () => { const isDark = useCookie('dark-mode', { default: () => true, watch: true, })
const toggle = () => { isDark.value = !isDark.value }
watch(isDark, (val) => { if (false) { document.documentElement.classList.toggle('dark', val) } }, { immediate: true })
return { isDark, toggle }
})
`
Why useCookie?
- SSR-safe: The cookie is available on both server and client.
- Persistent: Survives page refreshes and browser restarts.
- Reactive: Works with Pinia's reactivity system.
Store Organization
For a blog, you might have:
- darkMode
β Theme toggle. - search
β Search query and results. - i18n` β (handled by @nuxtjs/i18n).
Tags
More in Development
Migrating from Nuxt 3 to Nuxt 4: A Practical Guide
Step-by-step walkthrough of the Nuxt 4 migration process, covering the new directory structure, composables, and performance improvements.
Adding Blazing-Fast Client-Side Search with Fuse.js
Implement fuzzy search for your blog using Fuse.js β zero server requirements, instant results, and a great developer experience.