@nuxt/docs 0.0.0 → 3.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.navigation.yml +2 -0
- package/1.getting-started/.navigation.yml +3 -0
- package/1.getting-started/01.introduction.md +81 -0
- package/1.getting-started/02.installation.md +109 -0
- package/1.getting-started/03.configuration.md +226 -0
- package/1.getting-started/04.views.md +163 -0
- package/1.getting-started/05.assets.md +48 -0
- package/1.getting-started/06.styling.md +565 -0
- package/1.getting-started/07.routing.md +149 -0
- package/1.getting-started/08.seo-meta.md +360 -0
- package/1.getting-started/09.transitions.md +473 -0
- package/1.getting-started/10.data-fetching.md +795 -0
- package/1.getting-started/11.state-management.md +223 -0
- package/1.getting-started/12.error-handling.md +233 -0
- package/1.getting-started/13.server.md +94 -0
- package/1.getting-started/14.layers.md +92 -0
- package/1.getting-started/15.prerendering.md +194 -0
- package/1.getting-started/16.deployment.md +130 -0
- package/1.getting-started/17.testing.md +728 -0
- package/1.getting-started/18.upgrade.md +997 -0
- package/2.guide/.navigation.yml +2 -0
- package/2.guide/0.index.md +22 -0
- package/2.guide/1.concepts/.navigation.yml +3 -0
- package/2.guide/1.concepts/1.auto-imports.md +205 -0
- package/2.guide/1.concepts/10.nuxt-lifecycle.md +141 -0
- package/2.guide/1.concepts/2.vuejs-development.md +103 -0
- package/2.guide/1.concepts/3.rendering.md +255 -0
- package/2.guide/1.concepts/4.server-engine.md +62 -0
- package/2.guide/1.concepts/5.modules.md +48 -0
- package/2.guide/1.concepts/7.esm.md +299 -0
- package/2.guide/1.concepts/8.typescript.md +97 -0
- package/2.guide/1.concepts/9.code-style.md +22 -0
- package/2.guide/2.directory-structure/.navigation.yml +3 -0
- package/2.guide/2.directory-structure/0.nuxt.md +20 -0
- package/2.guide/2.directory-structure/0.output.md +18 -0
- package/2.guide/2.directory-structure/1.assets.md +16 -0
- package/2.guide/2.directory-structure/1.components.md +608 -0
- package/2.guide/2.directory-structure/1.composables.md +121 -0
- package/2.guide/2.directory-structure/1.content.md +64 -0
- package/2.guide/2.directory-structure/1.layouts.md +180 -0
- package/2.guide/2.directory-structure/1.middleware.md +209 -0
- package/2.guide/2.directory-structure/1.modules.md +66 -0
- package/2.guide/2.directory-structure/1.node_modules.md +12 -0
- package/2.guide/2.directory-structure/1.pages.md +440 -0
- package/2.guide/2.directory-structure/1.plugins.md +299 -0
- package/2.guide/2.directory-structure/1.public.md +27 -0
- package/2.guide/2.directory-structure/1.server.md +546 -0
- package/2.guide/2.directory-structure/1.shared.md +104 -0
- package/2.guide/2.directory-structure/1.utils.md +49 -0
- package/2.guide/2.directory-structure/2.env.md +75 -0
- package/2.guide/2.directory-structure/2.gitignore.md +37 -0
- package/2.guide/2.directory-structure/2.nuxtignore.md +36 -0
- package/2.guide/2.directory-structure/2.nuxtrc.md +50 -0
- package/2.guide/2.directory-structure/3.app-config.md +177 -0
- package/2.guide/2.directory-structure/3.app.md +72 -0
- package/2.guide/2.directory-structure/3.error.md +55 -0
- package/2.guide/2.directory-structure/3.nuxt-config.md +34 -0
- package/2.guide/2.directory-structure/3.package.md +32 -0
- package/2.guide/2.directory-structure/3.tsconfig.md +24 -0
- package/2.guide/3.going-further/.navigation.yml +3 -0
- package/2.guide/3.going-further/1.experimental-features.md +689 -0
- package/2.guide/3.going-further/1.features.md +103 -0
- package/2.guide/3.going-further/1.internals.md +81 -0
- package/2.guide/3.going-further/10.runtime-config.md +174 -0
- package/2.guide/3.going-further/11.nightly-release-channel.md +68 -0
- package/2.guide/3.going-further/2.hooks.md +98 -0
- package/2.guide/3.going-further/3.modules.md +811 -0
- package/2.guide/3.going-further/4.kit.md +51 -0
- package/2.guide/3.going-further/6.nuxt-app.md +64 -0
- package/2.guide/3.going-further/7.layers.md +227 -0
- package/2.guide/3.going-further/9.debugging.md +115 -0
- package/2.guide/3.going-further/index.md +4 -0
- package/2.guide/4.recipes/.navigation.yml +3 -0
- package/2.guide/4.recipes/1.custom-routing.md +181 -0
- package/2.guide/4.recipes/2.vite-plugin.md +65 -0
- package/2.guide/4.recipes/3.custom-usefetch.md +125 -0
- package/2.guide/4.recipes/4.sessions-and-authentication.md +203 -0
- package/3.api/.navigation.yml +3 -0
- package/3.api/1.components/.navigation.yml +3 -0
- package/3.api/1.components/1.client-only.md +76 -0
- package/3.api/1.components/1.dev-only.md +51 -0
- package/3.api/1.components/1.nuxt-client-fallback.md +80 -0
- package/3.api/1.components/10.nuxt-picture.md +27 -0
- package/3.api/1.components/11.teleports.md +40 -0
- package/3.api/1.components/12.nuxt-route-announcer.md +56 -0
- package/3.api/1.components/13.nuxt-time.md +173 -0
- package/3.api/1.components/2.nuxt-page.md +154 -0
- package/3.api/1.components/3.nuxt-layout.md +156 -0
- package/3.api/1.components/4.nuxt-link.md +322 -0
- package/3.api/1.components/5.nuxt-loading-indicator.md +50 -0
- package/3.api/1.components/6.nuxt-error-boundary.md +65 -0
- package/3.api/1.components/7.nuxt-welcome.md +25 -0
- package/3.api/1.components/8.nuxt-island.md +70 -0
- package/3.api/1.components/9.nuxt-img.md +43 -0
- package/3.api/2.composables/.navigation.yml +3 -0
- package/3.api/2.composables/on-prehydrate.md +60 -0
- package/3.api/2.composables/use-app-config.md +19 -0
- package/3.api/2.composables/use-async-data.md +212 -0
- package/3.api/2.composables/use-cookie.md +233 -0
- package/3.api/2.composables/use-error.md +32 -0
- package/3.api/2.composables/use-fetch.md +217 -0
- package/3.api/2.composables/use-head-safe.md +55 -0
- package/3.api/2.composables/use-head.md +69 -0
- package/3.api/2.composables/use-hydration.md +68 -0
- package/3.api/2.composables/use-lazy-async-data.md +47 -0
- package/3.api/2.composables/use-lazy-fetch.md +55 -0
- package/3.api/2.composables/use-loading-indicator.md +77 -0
- package/3.api/2.composables/use-nuxt-app.md +294 -0
- package/3.api/2.composables/use-nuxt-data.md +112 -0
- package/3.api/2.composables/use-preview-mode.md +118 -0
- package/3.api/2.composables/use-request-event.md +23 -0
- package/3.api/2.composables/use-request-fetch.md +52 -0
- package/3.api/2.composables/use-request-header.md +34 -0
- package/3.api/2.composables/use-request-headers.md +37 -0
- package/3.api/2.composables/use-request-url.md +41 -0
- package/3.api/2.composables/use-response-header.md +48 -0
- package/3.api/2.composables/use-route-announcer.md +60 -0
- package/3.api/2.composables/use-route.md +52 -0
- package/3.api/2.composables/use-router.md +92 -0
- package/3.api/2.composables/use-runtime-config.md +142 -0
- package/3.api/2.composables/use-runtime-hook.md +43 -0
- package/3.api/2.composables/use-seo-meta.md +80 -0
- package/3.api/2.composables/use-server-seo-meta.md +27 -0
- package/3.api/2.composables/use-state.md +48 -0
- package/3.api/3.utils/$fetch.md +98 -0
- package/3.api/3.utils/.navigation.yml +3 -0
- package/3.api/3.utils/abort-navigation.md +73 -0
- package/3.api/3.utils/add-route-middleware.md +88 -0
- package/3.api/3.utils/call-once.md +92 -0
- package/3.api/3.utils/clear-error.md +29 -0
- package/3.api/3.utils/clear-nuxt-data.md +23 -0
- package/3.api/3.utils/clear-nuxt-state.md +23 -0
- package/3.api/3.utils/create-error.md +55 -0
- package/3.api/3.utils/define-nuxt-component.md +53 -0
- package/3.api/3.utils/define-nuxt-route-middleware.md +67 -0
- package/3.api/3.utils/define-page-meta.md +234 -0
- package/3.api/3.utils/define-route-rules.md +52 -0
- package/3.api/3.utils/navigate-to.md +230 -0
- package/3.api/3.utils/on-before-route-leave.md +11 -0
- package/3.api/3.utils/on-before-route-update.md +11 -0
- package/3.api/3.utils/on-nuxt-ready.md +25 -0
- package/3.api/3.utils/prefetch-components.md +28 -0
- package/3.api/3.utils/preload-components.md +23 -0
- package/3.api/3.utils/preload-route-components.md +41 -0
- package/3.api/3.utils/prerender-routes.md +46 -0
- package/3.api/3.utils/refresh-cookie.md +46 -0
- package/3.api/3.utils/refresh-nuxt-data.md +91 -0
- package/3.api/3.utils/reload-nuxt-app.md +74 -0
- package/3.api/3.utils/set-page-layout.md +24 -0
- package/3.api/3.utils/set-response-status.md +36 -0
- package/3.api/3.utils/show-error.md +31 -0
- package/3.api/3.utils/update-app-config.md +27 -0
- package/3.api/4.commands/.navigation.yml +3 -0
- package/3.api/4.commands/add.md +112 -0
- package/3.api/4.commands/analyze.md +41 -0
- package/3.api/4.commands/build-module.md +42 -0
- package/3.api/4.commands/build.md +46 -0
- package/3.api/4.commands/cleanup.md +38 -0
- package/3.api/4.commands/dev.md +59 -0
- package/3.api/4.commands/devtools.md +38 -0
- package/3.api/4.commands/generate.md +41 -0
- package/3.api/4.commands/info.md +33 -0
- package/3.api/4.commands/init.md +46 -0
- package/3.api/4.commands/module.md +84 -0
- package/3.api/4.commands/prepare.md +36 -0
- package/3.api/4.commands/preview.md +43 -0
- package/3.api/4.commands/typecheck.md +42 -0
- package/3.api/4.commands/upgrade.md +37 -0
- package/3.api/5.kit/.navigation.yml +3 -0
- package/3.api/5.kit/1.modules.md +172 -0
- package/3.api/5.kit/10.runtime-config.md +27 -0
- package/3.api/5.kit/10.templates.md +283 -0
- package/3.api/5.kit/11.nitro.md +409 -0
- package/3.api/5.kit/12.resolving.md +268 -0
- package/3.api/5.kit/13.logging.md +65 -0
- package/3.api/5.kit/14.builder.md +491 -0
- package/3.api/5.kit/15.examples.md +41 -0
- package/3.api/5.kit/2.programmatic.md +125 -0
- package/3.api/5.kit/3.compatibility.md +230 -0
- package/3.api/5.kit/4.autoimports.md +144 -0
- package/3.api/5.kit/5.components.md +127 -0
- package/3.api/5.kit/6.context.md +130 -0
- package/3.api/5.kit/7.pages.md +295 -0
- package/3.api/5.kit/8.layout.md +80 -0
- package/3.api/5.kit/9.plugins.md +263 -0
- package/3.api/6.advanced/.navigation.yml +1 -0
- package/3.api/6.advanced/1.hooks.md +105 -0
- package/3.api/6.advanced/2.import-meta.md +60 -0
- package/3.api/6.nuxt-config.md +12 -0
- package/3.api/index.md +31 -0
- package/5.community/.navigation.yml +3 -0
- package/5.community/2.getting-help.md +48 -0
- package/5.community/3.reporting-bugs.md +50 -0
- package/5.community/4.contribution.md +205 -0
- package/5.community/5.framework-contribution.md +142 -0
- package/5.community/6.roadmap.md +79 -0
- package/5.community/7.changelog.md +92 -0
- package/6.bridge/.navigation.yml +3 -0
- package/6.bridge/1.overview.md +137 -0
- package/6.bridge/10.configuration.md +96 -0
- package/6.bridge/2.typescript.md +46 -0
- package/6.bridge/3.bridge-composition-api.md +132 -0
- package/6.bridge/4.plugins-and-middleware.md +65 -0
- package/6.bridge/5.nuxt3-compatible-api.md +204 -0
- package/6.bridge/6.meta.md +117 -0
- package/6.bridge/7.runtime-config.md +38 -0
- package/6.bridge/8.nitro.md +102 -0
- package/6.bridge/9.vite.md +37 -0
- package/7.migration/.navigation.yml +3 -0
- package/7.migration/1.overview.md +24 -0
- package/7.migration/10.bundling.md +28 -0
- package/7.migration/11.server.md +17 -0
- package/7.migration/2.configuration.md +240 -0
- package/7.migration/20.module-authors.md +94 -0
- package/7.migration/3.auto-imports.md +18 -0
- package/7.migration/4.meta.md +127 -0
- package/7.migration/5.plugins-and-middleware.md +80 -0
- package/7.migration/6.pages-and-layouts.md +233 -0
- package/7.migration/7.component-options.md +156 -0
- package/7.migration/8.runtime-config.md +58 -0
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/package.json +16 -4
- package/dist/.gitkeep +0 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'State Management'
|
|
3
|
+
description: Nuxt provides powerful state management libraries and the useState composable to create a reactive and SSR-friendly shared state.
|
|
4
|
+
navigation.icon: i-lucide-database
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Nuxt provides the [`useState`](/docs/api/composables/use-state) composable to create a reactive and SSR-friendly shared state across components.
|
|
8
|
+
|
|
9
|
+
[`useState`](/docs/api/composables/use-state) is an SSR-friendly [`ref`](https://vuejs.org/api/reactivity-core.html#ref) replacement. Its value will be preserved after server-side rendering (during client-side hydration) and shared across all components using a unique key.
|
|
10
|
+
|
|
11
|
+
:video-accordion{title="Watch a video from Alexander Lichter about why and when to use useState" videoId="mv0WcBABcIk"}
|
|
12
|
+
|
|
13
|
+
::important
|
|
14
|
+
Because the data inside [`useState`](/docs/api/composables/use-state) will be serialized to JSON, it is important that it does not contain anything that cannot be serialized, such as classes, functions or symbols.
|
|
15
|
+
::
|
|
16
|
+
|
|
17
|
+
::read-more{to="/docs/api/composables/use-state"}
|
|
18
|
+
Read more about `useState` composable.
|
|
19
|
+
::
|
|
20
|
+
|
|
21
|
+
## Best Practices
|
|
22
|
+
|
|
23
|
+
::warning
|
|
24
|
+
Never define `const state = ref()` outside of `<script setup>` or `setup()` function.<br>
|
|
25
|
+
For example, doing `export myState = ref({})` would result in state shared across requests on the server and can lead to memory leaks.
|
|
26
|
+
::
|
|
27
|
+
|
|
28
|
+
::tip{icon="i-lucide-circle-check"}
|
|
29
|
+
Instead use `const useX = () => useState('x')`
|
|
30
|
+
::
|
|
31
|
+
|
|
32
|
+
## Examples
|
|
33
|
+
|
|
34
|
+
### Basic Usage
|
|
35
|
+
|
|
36
|
+
In this example, we use a component-local counter state. Any other component that uses `useState('counter')` shares the same reactive state.
|
|
37
|
+
|
|
38
|
+
```vue twoslash [app.vue]
|
|
39
|
+
<script setup lang="ts">
|
|
40
|
+
const counter = useState('counter', () => Math.round(Math.random() * 1000))
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<div>
|
|
45
|
+
Counter: {{ counter }}
|
|
46
|
+
<button @click="counter++">
|
|
47
|
+
+
|
|
48
|
+
</button>
|
|
49
|
+
<button @click="counter--">
|
|
50
|
+
-
|
|
51
|
+
</button>
|
|
52
|
+
</div>
|
|
53
|
+
</template>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
:link-example{to="/docs/examples/features/state-management"}
|
|
57
|
+
|
|
58
|
+
::note
|
|
59
|
+
To globally invalidate cached state, see [`clearNuxtState`](/docs/api/utils/clear-nuxt-state) util.
|
|
60
|
+
::
|
|
61
|
+
|
|
62
|
+
### Initializing State
|
|
63
|
+
|
|
64
|
+
Most of the time, you will want to initialize your state with data that resolves asynchronously. You can use the [`app.vue`](/docs/guide/directory-structure/app) component with the [`callOnce`](/docs/api/utils/call-once) util to do so.
|
|
65
|
+
|
|
66
|
+
```vue twoslash [app.vue]
|
|
67
|
+
<script setup lang="ts">
|
|
68
|
+
const websiteConfig = useState('config')
|
|
69
|
+
|
|
70
|
+
await callOnce(async () => {
|
|
71
|
+
websiteConfig.value = await $fetch('https://my-cms.com/api/website-config')
|
|
72
|
+
})
|
|
73
|
+
</script>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
::tip
|
|
77
|
+
This is similar to the [`nuxtServerInit` action](https://v2.nuxt.com/docs/directory-structure/store/#the-nuxtserverinit-action) in Nuxt 2, which allows filling the initial state of your store server-side before rendering the page.
|
|
78
|
+
::
|
|
79
|
+
|
|
80
|
+
:read-more{to="/docs/api/utils/call-once"}
|
|
81
|
+
|
|
82
|
+
### Usage with Pinia
|
|
83
|
+
|
|
84
|
+
In this example, we leverage the [Pinia module](/modules/pinia) to create a global store and use it across the app.
|
|
85
|
+
|
|
86
|
+
::important
|
|
87
|
+
Make sure to install the Pinia module with `npx nuxi@latest module add pinia` or follow the [module's installation steps](https://pinia.vuejs.org/ssr/nuxt.html#Installation).
|
|
88
|
+
::
|
|
89
|
+
|
|
90
|
+
::code-group
|
|
91
|
+
```ts [stores/website.ts]
|
|
92
|
+
export const useWebsiteStore = defineStore('websiteStore', {
|
|
93
|
+
state: () => ({
|
|
94
|
+
name: '',
|
|
95
|
+
description: ''
|
|
96
|
+
}),
|
|
97
|
+
actions: {
|
|
98
|
+
async fetch() {
|
|
99
|
+
const infos = await $fetch('https://api.nuxt.com/modules/pinia')
|
|
100
|
+
|
|
101
|
+
this.name = infos.name
|
|
102
|
+
this.description = infos.description
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
```
|
|
107
|
+
```vue [app.vue]
|
|
108
|
+
<script setup lang="ts">
|
|
109
|
+
const website = useWebsiteStore()
|
|
110
|
+
|
|
111
|
+
await callOnce(website.fetch)
|
|
112
|
+
</script>
|
|
113
|
+
|
|
114
|
+
<template>
|
|
115
|
+
<main>
|
|
116
|
+
<h1>{{ website.name }}</h1>
|
|
117
|
+
<p>{{ website.description }}</p>
|
|
118
|
+
</main>
|
|
119
|
+
</template>
|
|
120
|
+
```
|
|
121
|
+
::
|
|
122
|
+
|
|
123
|
+
## Advanced Usage
|
|
124
|
+
|
|
125
|
+
::code-group
|
|
126
|
+
```ts [composables/locale.ts]
|
|
127
|
+
import type { Ref } from 'vue'
|
|
128
|
+
|
|
129
|
+
export const useLocale = () => {
|
|
130
|
+
return useState<string>('locale', () => useDefaultLocale().value)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const useDefaultLocale = (fallback = 'en-US') => {
|
|
134
|
+
const locale = ref(fallback)
|
|
135
|
+
if (import.meta.server) {
|
|
136
|
+
const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0]
|
|
137
|
+
if (reqLocale) {
|
|
138
|
+
locale.value = reqLocale
|
|
139
|
+
}
|
|
140
|
+
} else if (import.meta.client) {
|
|
141
|
+
const navLang = navigator.language
|
|
142
|
+
if (navLang) {
|
|
143
|
+
locale.value = navLang
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return locale
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export const useLocales = () => {
|
|
150
|
+
const locale = useLocale()
|
|
151
|
+
const locales = ref([
|
|
152
|
+
'en-US',
|
|
153
|
+
'en-GB',
|
|
154
|
+
...
|
|
155
|
+
'ja-JP-u-ca-japanese'
|
|
156
|
+
])
|
|
157
|
+
if (!locales.value.includes(locale.value)) {
|
|
158
|
+
locales.value.unshift(locale.value)
|
|
159
|
+
}
|
|
160
|
+
return locales
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export const useLocaleDate = (date: Ref<Date> | Date, locale = useLocale()) => {
|
|
164
|
+
return computed(() => new Intl.DateTimeFormat(locale.value, { dateStyle: 'full' }).format(unref(date)))
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
```vue [app.vue]
|
|
169
|
+
<script setup lang="ts">
|
|
170
|
+
const locales = useLocales()
|
|
171
|
+
const locale = useLocale()
|
|
172
|
+
const date = useLocaleDate(new Date('2016-10-26'))
|
|
173
|
+
</script>
|
|
174
|
+
|
|
175
|
+
<template>
|
|
176
|
+
<div>
|
|
177
|
+
<h1>Nuxt birthday</h1>
|
|
178
|
+
<p>{{ date }}</p>
|
|
179
|
+
<label for="locale-chooser">Preview a different locale</label>
|
|
180
|
+
<select id="locale-chooser" v-model="locale">
|
|
181
|
+
<option v-for="locale of locales" :key="locale" :value="locale">
|
|
182
|
+
{{ locale }}
|
|
183
|
+
</option>
|
|
184
|
+
</select>
|
|
185
|
+
</div>
|
|
186
|
+
</template>
|
|
187
|
+
```
|
|
188
|
+
::
|
|
189
|
+
|
|
190
|
+
:link-example{to="/docs/examples/advanced/locale"}
|
|
191
|
+
|
|
192
|
+
## Shared State
|
|
193
|
+
|
|
194
|
+
By using [auto-imported composables](/docs/guide/directory-structure/composables) we can define global type-safe states and import them across the app.
|
|
195
|
+
|
|
196
|
+
```ts twoslash [composables/states.ts]
|
|
197
|
+
export const useColor = () => useState<string>('color', () => 'pink')
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
```vue [app.vue]
|
|
201
|
+
<script setup lang="ts">
|
|
202
|
+
// ---cut-start---
|
|
203
|
+
const useColor = () => useState<string>('color', () => 'pink')
|
|
204
|
+
// ---cut-end---
|
|
205
|
+
const color = useColor() // Same as useState('color')
|
|
206
|
+
</script>
|
|
207
|
+
|
|
208
|
+
<template>
|
|
209
|
+
<p>Current color: {{ color }}</p>
|
|
210
|
+
</template>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
:video-accordion{title="Watch a video from Daniel Roe on how to deal with global state and SSR in Nuxt" videoId="dZSNW07sO-A"}
|
|
214
|
+
|
|
215
|
+
## Using third-party libraries
|
|
216
|
+
|
|
217
|
+
Nuxt **used to rely** on the Vuex library to provide global state management. If you are migrating from Nuxt 2, please head to [the migration guide](/docs/migration/configuration#vuex).
|
|
218
|
+
|
|
219
|
+
Nuxt is not opinionated about state management, so feel free to choose the right solution for your needs. There are multiple integrations with the most popular state management libraries, including:
|
|
220
|
+
|
|
221
|
+
- [Pinia](/modules/pinia) - the official Vue recommendation
|
|
222
|
+
- [Harlem](/modules/harlem) - immutable global state management
|
|
223
|
+
- [XState](/modules/xstate) - state machine approach with tools for visualizing and testing your state logic
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Error Handling'
|
|
3
|
+
description: 'Learn how to catch and handle errors in Nuxt.'
|
|
4
|
+
navigation.icon: i-lucide-bug-off
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Nuxt is a full-stack framework, which means there are several sources of unpreventable user runtime errors that can happen in different contexts:
|
|
8
|
+
|
|
9
|
+
- Errors during the Vue rendering lifecycle (SSR & CSR)
|
|
10
|
+
- Server and client startup errors (SSR + CSR)
|
|
11
|
+
- Errors during Nitro server lifecycle ([`server/`](/docs/guide/directory-structure/server) directory)
|
|
12
|
+
- Errors downloading JS chunks
|
|
13
|
+
|
|
14
|
+
::tip
|
|
15
|
+
**SSR** stands for **Server-Side Rendering** and **CSR** for **Client-Side Rendering**.
|
|
16
|
+
::
|
|
17
|
+
|
|
18
|
+
## Vue Errors
|
|
19
|
+
|
|
20
|
+
You can hook into Vue errors using [`onErrorCaptured`](https://vuejs.org/api/composition-api-lifecycle.html#onerrorcaptured).
|
|
21
|
+
|
|
22
|
+
In addition, Nuxt provides a [`vue:error`](/docs/api/advanced/hooks#app-hooks-runtime) hook that will be called if any errors propagate up to the top level.
|
|
23
|
+
|
|
24
|
+
If you are using an error reporting framework, you can provide a global handler through [`vueApp.config.errorHandler`](https://vuejs.org/api/application.html#app-config-errorhandler). It will receive all Vue errors, even if they are handled.
|
|
25
|
+
|
|
26
|
+
```ts twoslash [plugins/error-handler.ts]
|
|
27
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
28
|
+
nuxtApp.vueApp.config.errorHandler = (error, instance, info) => {
|
|
29
|
+
// handle error, e.g. report to a service
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Also possible
|
|
33
|
+
nuxtApp.hook('vue:error', (error, instance, info) => {
|
|
34
|
+
// handle error, e.g. report to a service
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
::note
|
|
40
|
+
Note that the `vue:error` hook is based on [`onErrorCaptured`](https://vuejs.org/api/composition-api-lifecycle.html#onerrorcaptured) lifecycle hook.
|
|
41
|
+
::
|
|
42
|
+
|
|
43
|
+
## Startup Errors
|
|
44
|
+
|
|
45
|
+
Nuxt will call the `app:error` hook if there are any errors in starting your Nuxt application.
|
|
46
|
+
|
|
47
|
+
This includes:
|
|
48
|
+
- running [Nuxt plugins](/docs/guide/directory-structure/plugins)
|
|
49
|
+
- processing `app:created` and `app:beforeMount` hooks
|
|
50
|
+
- rendering your Vue app to HTML (during SSR)
|
|
51
|
+
- mounting the app (on client-side), though you should handle this case with `onErrorCaptured` or with `vue:error`
|
|
52
|
+
- processing the `app:mounted` hook
|
|
53
|
+
|
|
54
|
+
## Nitro Server Errors
|
|
55
|
+
|
|
56
|
+
You cannot currently define a server-side handler for these errors, but can render an error page, see the [Render an Error Page](#error-page) section.
|
|
57
|
+
|
|
58
|
+
## Errors with JS Chunks
|
|
59
|
+
|
|
60
|
+
You might encounter chunk loading errors due to a network connectivity failure or a new deployment (which invalidates your old, hashed JS chunk URLs). Nuxt provides built-in support for handling chunk loading errors by performing a hard reload when a chunk fails to load during route navigation.
|
|
61
|
+
|
|
62
|
+
You can change this behavior by setting `experimental.emitRouteChunkError` to `false` (to disable hooking into these errors at all) or to `manual` if you want to handle them yourself. If you want to handle chunk loading errors manually, you can check out the [the automatic implementation](https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/plugins/chunk-reload.client.ts) for ideas.
|
|
63
|
+
|
|
64
|
+
## Error Page
|
|
65
|
+
|
|
66
|
+
::note
|
|
67
|
+
When Nuxt encounters a fatal error (any unhandled error on the server, or an error created with `fatal: true` on the client) it will either render a JSON response (if requested with `Accept: application/json` header) or trigger a full-screen error page.
|
|
68
|
+
::
|
|
69
|
+
|
|
70
|
+
An error may occur during the server lifecycle when:
|
|
71
|
+
- processing your Nuxt plugins
|
|
72
|
+
- rendering your Vue app into HTML
|
|
73
|
+
- a server API route throws an error
|
|
74
|
+
|
|
75
|
+
It can also occur on the client side when:
|
|
76
|
+
- processing your Nuxt plugins
|
|
77
|
+
- before mounting the application (`app:beforeMount` hook)
|
|
78
|
+
- mounting your app if the error was not handled with `onErrorCaptured` or `vue:error` hook
|
|
79
|
+
- the Vue app is initialized and mounted in browser (`app:mounted`).
|
|
80
|
+
|
|
81
|
+
::read-more{to="/docs/api/advanced/hooks"}
|
|
82
|
+
Discover all the Nuxt lifecycle hooks.
|
|
83
|
+
::
|
|
84
|
+
|
|
85
|
+
Customize the default error page by adding `~/error.vue` in the source directory of your application, alongside `app.vue`.
|
|
86
|
+
|
|
87
|
+
<!-- TODO:twoslash: Twoslash does not support tsconfig paths yet -->
|
|
88
|
+
|
|
89
|
+
```vue [error.vue]
|
|
90
|
+
<script setup lang="ts">
|
|
91
|
+
import type { NuxtError } from '#app'
|
|
92
|
+
|
|
93
|
+
const props = defineProps({
|
|
94
|
+
error: Object as () => NuxtError
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
const handleError = () => clearError({ redirect: '/' })
|
|
98
|
+
</script>
|
|
99
|
+
|
|
100
|
+
<template>
|
|
101
|
+
<div>
|
|
102
|
+
<h2>{{ error.statusCode }}</h2>
|
|
103
|
+
<button @click="handleError">Clear errors</button>
|
|
104
|
+
</div>
|
|
105
|
+
</template>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
::read-more{to="/docs/guide/directory-structure/error"}
|
|
109
|
+
Read more about `error.vue` and its uses.
|
|
110
|
+
::
|
|
111
|
+
|
|
112
|
+
For custom errors we highly recommend to use `onErrorCaptured` composable that can be called in a page/component setup function or `vue:error` runtime nuxt hook that can be configured in a nuxt plugin.
|
|
113
|
+
|
|
114
|
+
```ts twoslash [plugins/error-handler.ts]
|
|
115
|
+
export default defineNuxtPlugin(nuxtApp => {
|
|
116
|
+
nuxtApp.hook('vue:error', (err) => {
|
|
117
|
+
//
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
When you are ready to remove the error page, you can call the [`clearError`](/docs/api/utils/clear-error) helper function, which takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page).
|
|
123
|
+
|
|
124
|
+
::important
|
|
125
|
+
Make sure to check before using anything dependent on Nuxt plugins, such as `$route` or `useRouter`, as if a plugin threw an error, then it won't be re-run until you clear the error.
|
|
126
|
+
::
|
|
127
|
+
|
|
128
|
+
::note
|
|
129
|
+
Rendering an error page is an entirely separate page load, meaning any registered middleware will run again. You can use [`useError`](#useerror) in middleware to check if an error is being handled.
|
|
130
|
+
::
|
|
131
|
+
|
|
132
|
+
::note
|
|
133
|
+
If you are running on Node 16 and you set any cookies when rendering your error page, they will [overwrite cookies previously set](https://github.com/nuxt/nuxt/pull/20585). We recommend using a newer version of Node as Node 16 reached end-of-life in September 2023.
|
|
134
|
+
::
|
|
135
|
+
|
|
136
|
+
## Error Utils
|
|
137
|
+
|
|
138
|
+
### `useError`
|
|
139
|
+
|
|
140
|
+
```ts [TS Signature]
|
|
141
|
+
function useError (): Ref<Error | { url, statusCode, statusMessage, message, description, data }>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
This function will return the global Nuxt error that is being handled.
|
|
145
|
+
|
|
146
|
+
::read-more{to="/docs/api/composables/use-error"}
|
|
147
|
+
Read more about `useError` composable.
|
|
148
|
+
::
|
|
149
|
+
|
|
150
|
+
### `createError`
|
|
151
|
+
|
|
152
|
+
```ts [TS Signature]
|
|
153
|
+
function createError (err: string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Create an error object with additional metadata. You can pass a string to be set as the error `message` or an object containing error properties. It is usable in both the Vue and Server portions of your app, and is meant to be thrown.
|
|
157
|
+
|
|
158
|
+
If you throw an error created with `createError`:
|
|
159
|
+
- on server-side, it will trigger a full-screen error page which you can clear with [`clearError`](#clearerror).
|
|
160
|
+
- on client-side, it will throw a non-fatal error for you to handle. If you need to trigger a full-screen error page, then you can do this by setting `fatal: true`.
|
|
161
|
+
|
|
162
|
+
```vue twoslash [pages/movies/[slug\\].vue]
|
|
163
|
+
<script setup lang="ts">
|
|
164
|
+
const route = useRoute()
|
|
165
|
+
const { data } = await useFetch(`/api/movies/${route.params.slug}`)
|
|
166
|
+
|
|
167
|
+
if (!data.value) {
|
|
168
|
+
throw createError({
|
|
169
|
+
statusCode: 404,
|
|
170
|
+
statusMessage: 'Page Not Found'
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
</script>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
::read-more{to="/docs/api/utils/create-error"}
|
|
177
|
+
Read more about `createError` util.
|
|
178
|
+
::
|
|
179
|
+
|
|
180
|
+
### `showError`
|
|
181
|
+
|
|
182
|
+
```ts [TS Signature]
|
|
183
|
+
function showError (err: string | Error | { statusCode, statusMessage }): Error
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or `setup()` functions. It will trigger a full-screen error page which you can clear with [`clearError`](#clearerror).
|
|
187
|
+
|
|
188
|
+
It is recommended instead to use `throw createError()`.
|
|
189
|
+
|
|
190
|
+
::read-more{to="/docs/api/utils/show-error"}
|
|
191
|
+
Read more about `showError` util.
|
|
192
|
+
::
|
|
193
|
+
|
|
194
|
+
### `clearError`
|
|
195
|
+
|
|
196
|
+
```ts [TS Signature]
|
|
197
|
+
function clearError (options?: { redirect?: string }): Promise<void>
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
This function will clear the currently handled Nuxt error. It also takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page).
|
|
201
|
+
|
|
202
|
+
::read-more{to="/docs/api/utils/clear-error"}
|
|
203
|
+
Read more about `clearError` util.
|
|
204
|
+
::
|
|
205
|
+
|
|
206
|
+
## Render Error in Component
|
|
207
|
+
|
|
208
|
+
Nuxt also provides a [`<NuxtErrorBoundary>`](/docs/api/components/nuxt-error-boundary) component that allows you to handle client-side errors within your app, without replacing your entire site with an error page.
|
|
209
|
+
|
|
210
|
+
This component is responsible for handling errors that occur within its default slot. On client-side, it will prevent the error from bubbling up to the top level, and will render the `#error` slot instead.
|
|
211
|
+
|
|
212
|
+
The `#error` slot will receive `error` as a prop. (If you set `error = null` it will trigger re-rendering the default slot; you'll need to ensure that the error is fully resolved first or the error slot will just be rendered a second time.)
|
|
213
|
+
|
|
214
|
+
::tip
|
|
215
|
+
If you navigate to another route, the error will be cleared automatically.
|
|
216
|
+
::
|
|
217
|
+
|
|
218
|
+
```vue [pages/index.vue]
|
|
219
|
+
<template>
|
|
220
|
+
<!-- some content -->
|
|
221
|
+
<NuxtErrorBoundary @error="someErrorLogger">
|
|
222
|
+
<!-- You use the default slot to render your content -->
|
|
223
|
+
<template #error="{ error, clearError }">
|
|
224
|
+
You can display the error locally here: {{ error }}
|
|
225
|
+
<button @click="clearError">
|
|
226
|
+
This will clear the error.
|
|
227
|
+
</button>
|
|
228
|
+
</template>
|
|
229
|
+
</NuxtErrorBoundary>
|
|
230
|
+
</template>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
:link-example{to="/docs/examples/advanced/error-handling"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Server'
|
|
3
|
+
description: Build full-stack applications with Nuxt's server framework. You can fetch data from your database or another server, create APIs, or even generate static server-side content like a sitemap or a RSS feed - all from a single codebase.
|
|
4
|
+
navigation.icon: i-lucide-pc-case
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
:read-more{to="/docs/guide/directory-structure/server"}
|
|
8
|
+
|
|
9
|
+
## Powered by Nitro
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
Nuxt's server is [Nitro](https://github.com/nitrojs/nitro). It was originally created for Nuxt but is now part of [UnJS](https://unjs.io) and open for other frameworks - and can even be used on its own.
|
|
14
|
+
|
|
15
|
+
Using Nitro gives Nuxt superpowers:
|
|
16
|
+
|
|
17
|
+
- Full control of the server-side part of your app
|
|
18
|
+
- Universal deployment on any provider (many zero-config)
|
|
19
|
+
- Hybrid rendering
|
|
20
|
+
|
|
21
|
+
Nitro is internally using [h3](https://github.com/unjs/h3), a minimal H(TTP) framework built for high performance and portability.
|
|
22
|
+
|
|
23
|
+
:video-accordion{title="Watch a video from Alexander Lichter to understand the responsibilities of Nuxt and Nitro in your application" videoId="DkvgJa-X31k"}
|
|
24
|
+
|
|
25
|
+
## Server Endpoints & Middleware
|
|
26
|
+
|
|
27
|
+
You can easily manage the server-only part of your Nuxt app, from API endpoints to middleware.
|
|
28
|
+
|
|
29
|
+
Both endpoints and middleware can be defined like this:
|
|
30
|
+
|
|
31
|
+
```ts twoslash [server/api/test.ts]
|
|
32
|
+
export default defineEventHandler(async (event) => {
|
|
33
|
+
// ... Do whatever you want here
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
And you can directly return `text`, `json`, `html` or even a `stream`.
|
|
38
|
+
|
|
39
|
+
Out-of-the-box, it supports **hot module replacement** and **auto-import** like the other parts of your Nuxt application.
|
|
40
|
+
|
|
41
|
+
:read-more{to="/docs/guide/directory-structure/server"}
|
|
42
|
+
|
|
43
|
+
## Universal Deployment
|
|
44
|
+
|
|
45
|
+
Nitro offers the ability to deploy your Nuxt app anywhere, from a bare metal server to the edge network, with a start time of just a few milliseconds. That's fast!
|
|
46
|
+
|
|
47
|
+
:read-more{to="/blog/nuxt-on-the-edge"}
|
|
48
|
+
|
|
49
|
+
There are more than 15 presets to build your Nuxt app for different cloud providers and servers, including:
|
|
50
|
+
|
|
51
|
+
- [Cloudflare Workers](https://workers.cloudflare.com)
|
|
52
|
+
- [Netlify Functions](https://www.netlify.com/products/functions)
|
|
53
|
+
- [Vercel Edge Network](https://vercel.com/docs/edge-network)
|
|
54
|
+
|
|
55
|
+
Or for other runtimes:
|
|
56
|
+
|
|
57
|
+
::card-group
|
|
58
|
+
:card{icon="i-logos-deno" title="Deno" to="https://deno.land" target="_blank"}
|
|
59
|
+
:card{icon="i-logos-bun" title="Bun" to="https://bun.sh" target="_blank"}
|
|
60
|
+
::
|
|
61
|
+
|
|
62
|
+
:read-more{to="/docs/getting-started/deployment"}
|
|
63
|
+
|
|
64
|
+
## Hybrid Rendering
|
|
65
|
+
|
|
66
|
+
Nitro has a powerful feature called `routeRules` which allows you to define a set of rules to customize how each route of your Nuxt app is rendered (and more).
|
|
67
|
+
|
|
68
|
+
```ts twoslash [nuxt.config.ts]
|
|
69
|
+
export default defineNuxtConfig({
|
|
70
|
+
routeRules: {
|
|
71
|
+
// Generated at build time for SEO purpose
|
|
72
|
+
'/': { prerender: true },
|
|
73
|
+
// Cached for 1 hour
|
|
74
|
+
'/api/*': { cache: { maxAge: 60 * 60 } },
|
|
75
|
+
// Redirection to avoid 404
|
|
76
|
+
'/old-page': {
|
|
77
|
+
redirect: { to: '/new-page', statusCode: 302 }
|
|
78
|
+
}
|
|
79
|
+
// ...
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
::read-more{to="/docs/guide/concepts/rendering#hybrid-rendering"}
|
|
85
|
+
Learn about all available route rules are available to customize the rendering mode of your routes.
|
|
86
|
+
::
|
|
87
|
+
|
|
88
|
+
In addition, there are some route rules (for example, `ssr`, `appMiddleware`, and `noScripts`) that are Nuxt specific to change the behavior when rendering your pages to HTML.
|
|
89
|
+
|
|
90
|
+
Some route rules (`appMiddleware`, `redirect` and `prerender`) also affect client-side behavior.
|
|
91
|
+
|
|
92
|
+
Nitro is used to build the app for server side rendering, as well as pre-rendering.
|
|
93
|
+
|
|
94
|
+
:read-more{to="/docs/guide/concepts/rendering"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: 'Layers'
|
|
3
|
+
description: Nuxt provides a powerful system that allows you to extend the default files, configs, and much more.
|
|
4
|
+
navigation.icon: i-lucide-layers
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
One of the core features of Nuxt is the layers and extending support. You can extend a default Nuxt application to reuse components, utils, and configuration. The layers structure is almost identical to a standard Nuxt application which makes them easy to author and maintain.
|
|
8
|
+
|
|
9
|
+
## Use Cases
|
|
10
|
+
|
|
11
|
+
- Share reusable configuration presets across projects using `nuxt.config` and `app.config`
|
|
12
|
+
- Create a component library using [`components/`](/docs/guide/directory-structure/components) directory
|
|
13
|
+
- Create utility and composable library using [`composables/`](/docs/guide/directory-structure/composables) and [`utils/`](/docs/guide/directory-structure/utils) directories
|
|
14
|
+
- Create Nuxt module presets
|
|
15
|
+
- Share standard setup across projects
|
|
16
|
+
- Create Nuxt themes
|
|
17
|
+
- Enhance code organization by implementing a modular architecture and support Domain-Driven Design (DDD) pattern in large scale projects.
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
By default, any layers within your project in the `~~/layers` directory will be automatically registered as layers in your project.
|
|
22
|
+
|
|
23
|
+
::note
|
|
24
|
+
Layer auto-registration was introduced in Nuxt v3.12.0.
|
|
25
|
+
::
|
|
26
|
+
|
|
27
|
+
In addition, named layer aliases to the `srcDir` of each of these layers will automatically be created. For example, you will be able to access the `~~/layers/test` layer via `#layers/test`.
|
|
28
|
+
|
|
29
|
+
::note
|
|
30
|
+
Named layer aliases were introduced in Nuxt v3.16.0.
|
|
31
|
+
::
|
|
32
|
+
|
|
33
|
+
In addition, you can extend from a layer by adding the [extends](/docs/api/nuxt-config#extends) property to your [`nuxt.config`](/docs/guide/directory-structure/nuxt-config) file.
|
|
34
|
+
|
|
35
|
+
```ts [nuxt.config.ts]
|
|
36
|
+
export default defineNuxtConfig({
|
|
37
|
+
extends: [
|
|
38
|
+
'../base', // Extend from a local layer
|
|
39
|
+
'@my-themes/awesome', // Extend from an installed npm package
|
|
40
|
+
'github:my-themes/awesome#v1', // Extend from a git repository
|
|
41
|
+
]
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
You can also pass an authentication token if you are extending from a private GitHub repository:
|
|
46
|
+
|
|
47
|
+
```ts [nuxt.config.ts]
|
|
48
|
+
export default defineNuxtConfig({
|
|
49
|
+
extends: [
|
|
50
|
+
// per layer configuration
|
|
51
|
+
['github:my-themes/private-awesome', { auth: process.env.GITHUB_TOKEN }]
|
|
52
|
+
]
|
|
53
|
+
})
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
::tip
|
|
57
|
+
You can override a layer's alias by specifying it in the options next to the layer source.
|
|
58
|
+
|
|
59
|
+
```ts [nuxt.config.ts]
|
|
60
|
+
export default defineNuxtConfig({
|
|
61
|
+
extends: [
|
|
62
|
+
[
|
|
63
|
+
'github:my-themes/awesome',
|
|
64
|
+
{
|
|
65
|
+
meta: {
|
|
66
|
+
name: 'my-awesome-theme',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
]
|
|
71
|
+
})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
::
|
|
75
|
+
|
|
76
|
+
Nuxt uses [unjs/c12](https://c12.unjs.io) and [unjs/giget](https://giget.unjs.io) for extending remote layers. Check the documentation for more information and all available options.
|
|
77
|
+
|
|
78
|
+
::read-more{to="/docs/guide/going-further/layers"}
|
|
79
|
+
Read more about layers in the **Layer Author Guide**.
|
|
80
|
+
::
|
|
81
|
+
|
|
82
|
+
:video-accordion{title="Watch a video from Learn Vue about Nuxt Layers" videoId="lnFCM7c9f7I"}
|
|
83
|
+
|
|
84
|
+
:video-accordion{title="Watch a video from Alexander Lichter about Nuxt Layers" videoId="fr5yo3aVkfA"}
|
|
85
|
+
|
|
86
|
+
## Examples
|
|
87
|
+
|
|
88
|
+
::card-group
|
|
89
|
+
::card{icon="i-simple-icons-github" title="Content Wind" to="https://github.com/Atinux/content-wind" target="_blank"}
|
|
90
|
+
A lightweight Nuxt theme to build a Markdown driven website. Powered by Nuxt Content, TailwindCSS and Iconify.
|
|
91
|
+
::
|
|
92
|
+
::
|