pinia in nuxt layer

how to call pionia store from root's pinia in a layer?
26 Replies
kapa.ai
kapa.ai5d ago
Hi @Zhaolin Lau. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Nuxt’s layers don’t create separate Pinia instances: there is still a single app (and a single Pinia) at runtime. A store defined in the “root” layer is available from any other layer exactly the same way as from the root app. From the docs/PRs we only have info that in Nuxt 4 the default stores directory is inside app/ (i.e. app/stores) rather than the project root stores/ directory, but nothing about separate Pinia instances per layer.[[pinia store path](https://github.com/nuxt/nuxt/pull/33205)] So, in a layer:
// in a component/composable in your layer
import { useRootStore } from '#imports' // if auto‑imported
// or: import { useRootStore } from '~/stores/root' // adjust path to root store

const store = useRootStore()
store.someAction()
// in a component/composable in your layer
import { useRootStore } from '#imports' // if auto‑imported
// or: import { useRootStore } from '~/stores/root' // adjust path to root store

const store = useRootStore()
store.someAction()
Key points based on what we know: - Pinia is installed once via @pinia/nuxt in the root nuxt.config.[Pinia init] - Stores become visible only once they are used somewhere (e.g. useUserStore() in a component), which is why they then show up in devtools.[Pinia init] - Layers do not change how you call a store; you just need the correct import path to the root store. The knowledge sources don’t describe any special API for “root vs layer” Pinia, so if you’re seeing a different behavior (e.g. separate Pinia instances per layer), it’s not covered in the provided documents. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@520675622830342144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Zhaolin Lau
Zhaolin LauOP5d ago
@kapa.ai do i need to extend layer from the root nuxt config? or it will auto extend the layer
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You don’t have to add every layer to extends – Nuxt has two ways to use layers, and they behave differently: 1. Auto‑scanned local layers (~/layers)
- Any layer inside ~/layers is discovered automatically; you do not need to add it to extends for it to be used.[layers note fix; priority fix]
- These auto‑scanned layers actually have higher priority than layers listed in extends, and are ordered alphabetically (e.g. 2-theme overrides 1-base).[priority fix] 2. Layers added via extends in nuxt.config
- For layers outside ~/layers, you must add them to extends:
export default defineNuxtConfig({
extends: [
'./layers/pecav',
'./layers/webmail',
],
})

export default defineNuxtConfig({
extends: [
'./layers/pecav',
'./layers/webmail',
],
})

- Within extends, earlier entries have higher priority (first overrides second).[priority fix] So: - If your layer is in ~/layers, it’s auto‑used; no extends needed.
- If it’s elsewhere, you need to list it in extends. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@520675622830342144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Zhaolin Lau
Zhaolin LauOP5d ago
@kapa.ai is it possible to call pinia store from layer to root?
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Yes, it’s possible. Nuxt uses a single Pinia instance for the whole app, and layers just add more source directories on top—they don’t create separate Pinia roots. The docs we have only note that for Nuxt 4 the default Pinia store location is under app/ (e.g. app/stores) but do not mention any separation of stores between layers.[pinia store path] That means: - A store defined in the root (e.g. app/stores/user.ts or stores/user.ts) can be used in any layer. - From code inside a layer you just call it normally, for example:
// in a component/composable inside a layer
import { useUserStore } from '#imports' // if auto‑imported
// or: import { useUserStore } from '~/stores/user' // or '~/app/stores/user' in Nuxt 4 style

const userStore = useUserStore()
userStore.someAction()
// in a component/composable inside a layer
import { useUserStore } from '#imports' // if auto‑imported
// or: import { useUserStore } from '~/stores/user' // or '~/app/stores/user' in Nuxt 4 style

const userStore = useUserStore()
userStore.someAction()
The sources don’t describe any special “cross‑layer Pinia” API; they imply it’s a shared app context. If you’re seeing issues, they are not covered in the provided documents. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@520675622830342144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Zhaolin Lau
Zhaolin LauOP5d ago
@kapa.ai do i need to put app.vue for my layer?
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You don’t strictly need an app.vue in every layer, but details differ a bit by context: - Root project:
app.vue is optional if you use a pages/ directory – Nuxt will use the pages router as the entry point without requiring app.vue.[app.vue docs; single page note]
However, app.vue is where you typically put global wrappers like <NuxtLayout>, <NuxtPage>, loading indicators, notifications, etc., so it’s often useful to keep it.[delete app.vue] - Layers:
For layers, the docs and PRs mainly require that you follow the normal project structure inside the layer (including app/ in Nuxt 4 style), but they do not state that app.vue is mandatory inside a layer.[v4 folder structure; layers docs example]
A layer can provide its own app.vue to wrap or override the root’s app.vue, but the sources don’t say it’s required. So: you only need an app.vue in your layer if you specifically want that layer to define/override the app shell; otherwise, the root project’s app.vue (if present) is used. The knowledge sources don’t describe any error or limitation when a layer has no app.vue. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@520675622830342144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Zhaolin Lau
Zhaolin LauOP5d ago
@kapa.ai Cannot find name 'useOnboardingStore'.
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- That error means TypeScript can’t see a declaration for useOnboardingStore, so Nuxt’s auto-imports (or your manual imports) aren’t set up in a way the type system recognizes. From the provided sources we only have Pinia-related info about: - How stores are discovered in Nuxt 3/4 (default stores/ vs app/stores/). [pinia store path] - That a store only appears in devtools after it’s used (e.g. calling useUserStore() in a component). [Pinia init] There is no explicit mention of useOnboardingStore or a concrete configuration example with that name, so I can’t give you a precise fix for that symbol. Based on what is documented: 1. Ensure your store file is in the correct directory so Nuxt/Pinia can pick it up, e.g. for Nuxt 3/4: - stores/onboarding.ts or - app/stores/onboarding.ts (Nuxt 4 style). [pinia store path] 2. Define the store with defineStore and an exported composable named useOnboardingStore, similar to the working useUserStore example: [Pinia init]
// stores/onboarding.ts
import { defineStore } from 'pinia'

export const useOnboardingStore = defineStore('onboarding', () => {
// state/actions/getters
return {}
})

// stores/onboarding.ts
import { defineStore } from 'pinia'

export const useOnboardingStore = defineStore('onboarding', () => {
// state/actions/getters
return {}
})

3. In a component, actually import/use it so it’s instantiated and visible:
<script setup lang="ts">
import { useOnboardingStore } from '~/stores/onboarding' // adjust path to your file

const onboardingStore = useOnboardingStore()
</script>

<script setup lang="ts">
import { useOnboardingStore } from '~/stores/onboarding' // adjust path to your file

const onboardingStore = useOnboardingStore()
</script>

If you rely on auto-imports via imports.dirs, make sure that directory is configured correctly (as in the example that auto-imports stores), otherwise TypeScript won’t know about useOnboardingStore and you’ll see “Cannot find name”. [Pinia init] Beyond these general points, the knowledge sources don’t give more detail specific to useOnboardingStore. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@520675622830342144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Zhaolin Lau
Zhaolin LauOP5d ago
@kapa.ai im calling the store at root, and the store is from layer store
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You can call a Pinia store that’s defined in a layer from the root app, but Nuxt’s behavior around layers + auto‑imports/types is only partially covered in the sources, so there are limits to how specific I can be. From what we do know: - Nuxt 4’s default Pinia store location is under app/stores (instead of root stores/).[pinia store path] - Layers are full Nuxt projects that are merged; their app/ and server/ directories are included in Nuxt’s tsconfigs and layer directory resolution, so layer code is visible to the main app at build time.[layer tsconfig; layer dirs util] Putting that together, a typical setup for a store in a layer is:
// layers/onboarding/app/stores/onboarding.ts
import { defineStore } from 'pinia'

export const useOnboardingStore = defineStore('onboarding', () => {
// ...
return {}
})
// layers/onboarding/app/stores/onboarding.ts
import { defineStore } from 'pinia'

export const useOnboardingStore = defineStore('onboarding', () => {
// ...
return {}
})
Then, in the root app, you call it like any other store:
<script setup lang="ts">
// If auto-imports are enabled for stores (Nuxt 3/4 default with @pinia/nuxt)
// you can often just use it directly:
const onboardingStore = useOnboardingStore()

// If that gives `Cannot find name 'useOnboardingStore'` in TS,
// fall back to an explicit import using the correct path:
import { useOnboardingStore } from '~/layers/onboarding/app/stores/onboarding'
// or from whatever alias/path your layer exposes

const onboardingStore2 = useOnboardingStore()
</script>
<script setup lang="ts">
// If auto-imports are enabled for stores (Nuxt 3/4 default with @pinia/nuxt)
// you can often just use it directly:
const onboardingStore = useOnboardingStore()

// If that gives `Cannot find name 'useOnboardingStore'` in TS,
// fall back to an explicit import using the correct path:
import { useOnboardingStore } from '~/layers/onboarding/app/stores/onboarding'
// or from whatever alias/path your layer exposes

const onboardingStore2 = useOnboardingStore()
</script>
The TS error Cannot find name 'useOnboardingStore' means the type system doesn’t see that symbol. From the sources, we know Nuxt had to explicitly add layer app/ and server/ folders into generated tsconfigs so Vue/TS can resolve types from inside layers.[layer tsconfig; layer server tsconfig] If you’re on a version before those fixes, or using a different folder layout, TS might not pick up the store automatically. Because the sources don’t document the exact auto‑import behavior for Pinia stores across layers, I can’t guarantee that useOnboardingStore will be globally auto‑imported from a layer; using an explicit import with the correct path/alias is the reliable option when you call a layer store from the root. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@520675622830342144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Zhaolin Lau
Zhaolin LauOP5d ago
@kapa.ai do i need to config something in root's nuxt config or layer's nuxt config?
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You don’t need any special configuration for Pinia just because the store lives in a layer and you call it from the root. From the sources we have: - Pinia is added once in the root nuxt.config via the @pinia/nuxt module.[Pinia init] - In Nuxt 4, the default store location is app/stores (not stores/).[pinia store path] - Layer app/ and server/ folders are added to the generated TS configs so that types (and thus auto‑imports/types) work across layers.[layer tsconfig] Given that: 1. Root nuxt.config
- Must include @pinia/nuxt in modules (normal setup).[Pinia init] - No extra config is required just because the store is in a layer. 2. Layer structure / config
- Put the store in the layer’s app/stores (Nuxt 4 style) so it’s picked up like any other store, e.g. layers/onboarding/app/stores/onboarding.ts.[pinia store path; layer tsconfig] - You don’t need extra Pinia config in the layer’s nuxt.config for it to work in the root. If TypeScript still says Cannot find name 'useOnboardingStore', the reliable workaround (not explicitly covered but consistent with the examples) is to import it explicitly using the correct path or a layer alias, but the knowledge sources don’t provide a concrete example of that for Pinia in layers. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@520675622830342144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Zhaolin Lau
Zhaolin LauOP5d ago
@kapa.ai so my layer's nuxt config will be like this?: export default defineNuxtConfig({}) or i dont need to put nuxt config?
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- You can do either: 1. No nuxt.config in the layer
A layer can just be a directory with app/, pages/, components/, app/stores/, etc., and no nuxt.config. Nuxt will still treat it as a layer and merge its files into the root app.[flatten example; layer tsconfig] 2. Minimal nuxt.config in the layer
If you need to configure something specifically for that layer (e.g. $meta.name for a named alias, extra modules), then you add:
// layers/onboarding/nuxt.config.ts
export default defineNuxtConfig({
// layer-specific options (optional)
})

// layers/onboarding/nuxt.config.ts
export default defineNuxtConfig({
// layer-specific options (optional)
})

Named aliases for layers are configured via $meta.name in the layer’s nuxt.config.[named aliases] For your Pinia store in layers/.../app/stores/..., you don’t need any extra config in the layer if you’re not changing anything special. The root nuxt.config with @pinia/nuxt is enough. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@520675622830342144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Zhaolin Lau
Zhaolin LauOP5d ago
@kapa.ai give me a detailed folder structure in layers
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Nuxt’s docs and linked PRs only show basic examples of layer folder structures, not a single, fully “official” exhaustive layout. I’ll summarise what is shown and how it relates to Nuxt 4’s structure. --- 1. Basic layer example (from docs) The layers guide uses a flattened example that mirrors a normal Nuxt app, without an extra app/ prefix in the docs text (to avoid confusion).[layers flatten] A simple layer can look like:
layers/
base/
app.vue
pages/
index.vue
components/
TheHeader.vue
plugins/
my-plugin.ts
# (in Nuxt 4 style this content would live under app/, see next section)
layers/
base/
app.vue
pages/
index.vue
components/
TheHeader.vue
plugins/
my-plugin.ts
# (in Nuxt 4 style this content would live under app/, see next section)
In that PR, they specifically removed confusing app/ prefixes in the docs examples, but the real v4 structure is described separately. --- 2. Nuxt 4-style folder structure (applies to root and layers) When future.compatibilityVersion is set to 4, Nuxt 4 introduces a new default structure where app/ is the srcDir and most front-end directories live under it.[v4 structure] The documented v4 structure (for a project) is:
.output/
.nuxt/
app/
assets/
components/
composables/
layouts/
middleware/
pages/
plugins/
utils/
app.vue
router.options.ts
modules/
node_modules/
public/
server/
api/
middleware/
plugins/
routes/
utils/
nuxt.config.ts
.output/
.nuxt/
app/
assets/
components/
composables/
layouts/
middleware/
pages/
plugins/
utils/
app.vue
router.options.ts
modules/
node_modules/
public/
server/
api/
middleware/
plugins/
routes/
utils/
nuxt.config.ts
A layer is itself just a Nuxt project that can use the same structure. So a v4‑style layer (e.g. layers/onboarding) would typically mirror this inside the layer directory:
layers/
onboarding/
app/
assets/
components/
composables/
layouts/
middleware/
pages/
plugins/
stores/ # Pinia stores in Nuxt 4 default inside app/[[pinia store path](<https://github.com/nuxt/nuxt/pull/33205>)]
utils/
app.vue # optional but typical
server/
api/
middleware/
plugins/
routes/
utils/
public/
modules/
nuxt.config.ts # optional, only if you need layer-specific config
layers/
onboarding/
app/
assets/
components/
composables/
layouts/
middleware/
pages/
plugins/
stores/ # Pinia stores in Nuxt 4 default inside app/[[pinia store path](<https://github.com/nuxt/nuxt/pull/33205>)]
utils/
app.vue # optional but typical
server/
api/
middleware/
plugins/
routes/
utils/
public/
modules/
nuxt.config.ts # optional, only if you need layer-specific config
Nuxt’s tooling explicitly adds each layer’s app/ and server/ folders into tsconfig so that types resolve correctly from layers.[layer tsconfig] --- 3. Root + layers layout (putting it together) In a root project using layers, a combined layout could look like:
.nuxt/
.output/

app/
# root app code
components/
layouts/
pages/
plugins/
stores/
app.vue

server/
api/
middleware/
plugins/
routes/
utils/

layers/
base/
app/
components/
layouts/
pages/
plugins/
stores/
app.vue
server/
api/
middleware/
plugins/
routes/
utils/
public/
nuxt.config.ts # (optional)

feature-x/
app/
components/
pages/
stores/
server/
api/
nuxt.config.ts # (optional, e.g. to set $meta.name alias)[[layers flatten](<https://github.com/nuxt/nuxt/pull/18967>)]

modules/
public/
nuxt.config.ts
.nuxt/
.output/

app/
# root app code
components/
layouts/
pages/
plugins/
stores/
app.vue

server/
api/
middleware/
plugins/
routes/
utils/

layers/
base/
app/
components/
layouts/
pages/
plugins/
stores/
app.vue
server/
api/
middleware/
plugins/
routes/
utils/
public/
nuxt.config.ts # (optional)

feature-x/
app/
components/
pages/
stores/
server/
api/
nuxt.config.ts # (optional, e.g. to set $meta.name alias)[[layers flatten](<https://github.com/nuxt/nuxt/pull/18967>)]

modules/
public/
nuxt.config.ts
Within this, you can: - Put front‑end code in each layer’s app/… tree (components, pages, Pinia stores, etc.).[v4 structure; pinia store path] - Put server code in each layer’s server/… tree. - Optionally have a nuxt.config.ts in each layer if you need layer-specific options; it’s not required.[layers flatten] --- The sources do not provide a more detailed or opinionated “ideal” DDD/feature-sliced layout beyond this, so anything more specific (like “domain/feature folders”) would be convention you choose, not documented by Nuxt. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@520675622830342144> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?