@nuxt/docs-nightly 5.0.0-29741076.61a2183b → 5.0.0-29741325.e71f6f2a

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.
Files changed (60) hide show
  1. package/1.getting-started/07.routing.md +22 -0
  2. package/1.getting-started/08.seo-meta.md +19 -4
  3. package/1.getting-started/09.transitions.md +1 -1
  4. package/1.getting-started/10.data-fetching.md +3 -5
  5. package/1.getting-started/11.state-management.md +2 -2
  6. package/1.getting-started/14.layers.md +2 -2
  7. package/2.directory-structure/1.app/1.components.md +4 -0
  8. package/2.directory-structure/1.app/1.composables.md +2 -2
  9. package/2.directory-structure/1.server.md +7 -1
  10. package/2.directory-structure/1.shared.md +17 -1
  11. package/3.guide/1.concepts/2.nuxt-lifecycle.md +2 -2
  12. package/3.guide/1.concepts/3.auto-imports.md +1 -1
  13. package/3.guide/2.best-practices/hydration.md +4 -4
  14. package/3.guide/2.best-practices/performance.md +1 -1
  15. package/3.guide/2.best-practices/plugins.md +3 -3
  16. package/3.guide/3.ai/1.mcp.md +1 -1
  17. package/3.guide/3.ai/2.llms-txt.md +3 -3
  18. package/3.guide/4.modules/8.ecosystem.md +1 -1
  19. package/3.guide/5.recipes/1.custom-routing.md +1 -1
  20. package/3.guide/5.recipes/4.sessions-and-authentication.md +1 -1
  21. package/3.guide/6.going-further/1.experimental-features.md +8 -2
  22. package/4.api/1.components/1.client-only.md +2 -2
  23. package/4.api/1.components/13.nuxt-time.md +11 -11
  24. package/4.api/1.components/6.nuxt-error-boundary.md +5 -5
  25. package/4.api/1.components/8.nuxt-island.md +21 -0
  26. package/4.api/2.composables/on-prehydrate.md +12 -2
  27. package/4.api/2.composables/use-async-data.md +68 -68
  28. package/4.api/2.composables/use-cookie.md +6 -6
  29. package/4.api/2.composables/use-fetch.md +9 -9
  30. package/4.api/2.composables/use-head.md +1 -1
  31. package/4.api/2.composables/use-layout.md +4 -4
  32. package/4.api/2.composables/use-lazy-async-data.md +11 -5
  33. package/4.api/2.composables/use-lazy-fetch.md +13 -7
  34. package/4.api/2.composables/use-nuxt-app.md +6 -6
  35. package/4.api/2.composables/use-nuxt-data.md +7 -7
  36. package/4.api/2.composables/use-runtime-hook.md +2 -2
  37. package/4.api/3.utils/abort-navigation.md +1 -1
  38. package/4.api/3.utils/add-route-middleware.md +2 -2
  39. package/4.api/3.utils/define-nuxt-plugin.md +1 -1
  40. package/4.api/3.utils/define-nuxt-route-middleware.md +1 -1
  41. package/4.api/3.utils/define-page-meta.md +1 -1
  42. package/4.api/3.utils/refresh-nuxt-data.md +1 -1
  43. package/4.api/4.commands/init.md +1 -1
  44. package/4.api/4.commands/module.md +2 -2
  45. package/4.api/5.kit/1.modules.md +2 -2
  46. package/4.api/5.kit/10.templates.md +3 -3
  47. package/4.api/5.kit/12.nitro.md +5 -5
  48. package/4.api/5.kit/13.resolving.md +2 -2
  49. package/4.api/5.kit/14.logging.md +1 -1
  50. package/4.api/5.kit/15.builder.md +1 -1
  51. package/4.api/5.kit/17.layers.md +1 -1
  52. package/4.api/5.kit/5.components.md +1 -1
  53. package/4.api/5.kit/6.context.md +2 -2
  54. package/4.api/5.kit/9.head.md +1 -1
  55. package/4.api/5.kit/9.plugins.md +2 -2
  56. package/4.api/6.advanced/1.hooks.md +3 -3
  57. package/4.api/6.advanced/2.import-meta.md +3 -3
  58. package/5.community/4.contribution.md +10 -0
  59. package/6.bridge/10.configuration.md +1 -1
  60. package/package.json +1 -1
@@ -6,6 +6,28 @@ navigation.icon: i-lucide-milestone
6
6
 
7
7
  One core feature of Nuxt is the file system router. Every Vue file inside the [`app/pages/`](/docs/4.x/directory-structure/app/pages) directory creates a corresponding URL (or route) that displays the contents of the file. By using dynamic imports for each page, Nuxt leverages code-splitting to ship the minimum amount of JavaScript for the requested route.
8
8
 
9
+ ::note
10
+ Code-splitting is enabled by default and is recommended for most apps. If you have a specific reason to ship a single bundle instead, you can disable it in your [`nuxt.config`](/docs/4.x/api/nuxt-config):
11
+
12
+ ```ts [nuxt.config.ts]
13
+ export default defineNuxtConfig({
14
+ vite: {
15
+ $client: {
16
+ build: {
17
+ rolldownOptions: {
18
+ output: {
19
+ codeSplitting: false,
20
+ },
21
+ },
22
+ },
23
+ },
24
+ },
25
+ })
26
+ ```
27
+
28
+ This ships all JavaScript in a single file. It is rarely beneficial — it usually increases the initial download, even on slow connections — so only disable code-splitting if you have measured that it helps your case.
29
+ ::
30
+
9
31
  ## Pages
10
32
 
11
33
  Nuxt routing is based on [vue-router](https://router.vuejs.org) and generates the routes from every component created in the [`app/pages/` directory](/docs/4.x/directory-structure/app/pages), based on their filename.
@@ -33,9 +33,24 @@ export default defineNuxtConfig({
33
33
  })
34
34
  ```
35
35
 
36
+ ::note
37
+ When you set [`app.cdnURL`](/docs/4.x/api/nuxt-config#cdnurl), assets in your [`public/`](/docs/4.x/directory-structure/public) directory (including `favicon.ico`) are served from that CDN. Nuxt resolves public assets against `cdnURL`, falling back to `app.baseURL`. However, a static `app.head` link such as `href: '/favicon.ico'` above is a literal path and is **not** resolved against `cdnURL`. To point the favicon at the resolved location, build the `href` from runtime config with [`useHead()`](/docs/4.x/api/composables/use-head) in `app.vue`:
38
+
39
+ ```vue [app/app.vue]
40
+ <script setup lang="ts">
41
+ const { cdnURL, baseURL } = useRuntimeConfig().app
42
+ useHead({
43
+ link: [
44
+ { rel: 'icon', type: 'image/x-icon', href: `${cdnURL || baseURL}favicon.ico` },
45
+ ],
46
+ })
47
+ </script>
48
+ ```
49
+ ::
50
+
36
51
  You can also provide any of the keys listed below in [Types](/docs/4.x/getting-started/seo-meta#types).
37
52
 
38
- ### Defaults Tags
53
+ ### Default Tags
39
54
 
40
55
  Some tags are provided by Nuxt by default to ensure your website works well out of the box.
41
56
 
@@ -142,7 +157,7 @@ If you need to duplicate tags across client-server boundaries, apply a `key` att
142
157
 
143
158
  Below are the non-reactive types used for [`useHead`](/docs/4.x/api/composables/use-head), [`app.head`](/docs/4.x/api/nuxt-config#head) and components.
144
159
 
145
- ```ts
160
+ ```ts [Types]
146
161
  interface MetaObject {
147
162
  title?: string
148
163
  titleTemplate?: string | ((title?: string) => string)
@@ -231,7 +246,7 @@ If you want to use a function (for full control), then this cannot be set in you
231
246
 
232
247
  Now, if you set the title to `My Page` with [`useHead`](/docs/4.x/api/composables/use-head) on another page of your site, the title would appear as 'My Page - Site Title' in the browser tab. You could also pass `null` to default to 'Site Title'.
233
248
 
234
- ### Template Params
249
+ ### Template Parameters
235
250
 
236
251
  You can use `templateParams` to provide additional placeholders in your `titleTemplate` besides the default `%s`. This allows for more dynamic title generation.
237
252
 
@@ -273,7 +288,7 @@ useHead({
273
288
  </script>
274
289
  ```
275
290
 
276
- ## Examples
291
+ ## Example
277
292
 
278
293
  ### With `definePageMeta`
279
294
 
@@ -418,7 +418,7 @@ When `<NuxtPage />` is used in `app.vue`, transitions can be configured with the
418
418
  Remember, this page transition cannot be overridden with `definePageMeta` on individual pages.
419
419
  ::
420
420
 
421
- ## View Transitions API (experimental)
421
+ ## View Transitions API (Experimental)
422
422
 
423
423
  Nuxt ships with an experimental implementation of the [**View Transitions API**](https://developer.chrome.com/docs/web-platform/view-transitions) (see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API)). This is an exciting new way to implement native browser transitions which (among other things) have the ability to transition between unrelated elements on different pages.
424
424
 
@@ -14,7 +14,7 @@ In a nutshell:
14
14
 
15
15
  Both `useFetch` and `useAsyncData` share a common set of options and patterns that we will detail in the last sections.
16
16
 
17
- ## The need for `useFetch` and `useAsyncData`
17
+ ## The Need for `useFetch` and `useAsyncData`
18
18
 
19
19
  Nuxt is a framework which can run isomorphic (or universal) code in both server and client environments. If the [`$fetch` function](/docs/4.x/api/utils/dollarfetch) is used to perform data fetching in the setup function of a Vue component, this may cause data to be fetched twice, once on the server (to render the HTML) and once again on the client (when the HTML is hydrated). This can cause hydration issues, increase the time to interactivity and cause unpredictable behavior.
20
20
 
@@ -546,8 +546,6 @@ const id = ref(null)
546
546
  const { data, status } = useLazyFetch(() => `/api/users/${id.value}`, {
547
547
  immediate: false,
548
548
  })
549
-
550
- const pending = computed(() => status.value === 'pending')
551
549
  </script>
552
550
 
553
551
  <template>
@@ -556,14 +554,14 @@ const pending = computed(() => status.value === 'pending')
556
554
  <input
557
555
  v-model="id"
558
556
  type="number"
559
- :disabled="pending"
557
+ :disabled="status === 'pending'"
560
558
  >
561
559
 
562
560
  <div v-if="status === 'idle'">
563
561
  Type a user ID
564
562
  </div>
565
563
 
566
- <div v-else-if="pending">
564
+ <div v-else-if="status === 'pending'">
567
565
  Loading ...
568
566
  </div>
569
567
 
@@ -29,7 +29,7 @@ For example, doing `export myState = ref({})` would result in state shared acros
29
29
  Instead use `const useX = () => useState('x')`
30
30
  ::
31
31
 
32
- ## Examples
32
+ ## Example
33
33
 
34
34
  ### Basic Usage
35
35
 
@@ -219,7 +219,7 @@ const color = useColor() // Same as useState('color')
219
219
 
220
220
  :video-accordion{title="Watch a video from Daniel Roe on how to deal with global state and SSR in Nuxt" videoId="dZSNW07sO-A"}
221
221
 
222
- ## Using third-party libraries
222
+ ## Using Third-Party Libraries
223
223
 
224
224
  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/4.x/migration/configuration#vuex).
225
225
 
@@ -132,7 +132,7 @@ This pattern is useful for creating base layers with defaults that can be progre
132
132
  - **`~~/layers` directory** - Use for local layers that are part of your project
133
133
  - **`extends`** - Use for external dependencies (npm packages, remote repositories) or layers outside your project directory
134
134
 
135
- ### Full Example with extends
135
+ ### Full Example with `extends`
136
136
 
137
137
  ```ts [nuxt.config.ts]
138
138
  export default defineNuxtConfig({
@@ -163,7 +163,7 @@ Read more about layers in the **Layer Author Guide**.
163
163
 
164
164
  :video-accordion{title="Watch a video from Alexander Lichter about Nuxt Layers" videoId="fr5yo3aVkfA"}
165
165
 
166
- ## Examples
166
+ ## Example
167
167
 
168
168
  ::card-group
169
169
  ::card{icon="i-simple-icons-github" title="Content Wind" to="https://github.com/Atinux/content-wind" target="_blank"}
@@ -543,6 +543,10 @@ You can partially hydrate a component by setting a `nuxt-client` attribute on th
543
543
  This only works within a server component. Slots for client components are working only with `experimental.componentIsland.selectiveClient` set to `'deep'` and since they are rendered server-side, they are not interactive once client-side.
544
544
  ::
545
545
 
546
+ ::warning
547
+ Use `nuxt-client` only on local `.vue` SFCs. Built-ins like [`<NuxtLink>`](/docs/4.x/api/components/nuxt-link) skip the islands transform. After client navigation you may see `Failed to locate Teleport target`, or the link disappears with no error. Wrap the built-in in your own `.vue` file and put `nuxt-client` on that wrapper, or drop `nuxt-client` from the built-in. See [#29251](https://github.com/nuxt/nuxt/issues/29251) and [#26002](https://github.com/nuxt/nuxt/issues/26002).
548
+ ::
549
+
546
550
  #### Server Component Context
547
551
 
548
552
  When rendering a server-only or island component, `<NuxtIsland>` makes a fetch request which comes back with a `NuxtIslandResponse`. (This is an internal request if rendered on the server, or a request that you can see in the network tab if it's rendering on client-side navigation.)
@@ -56,7 +56,7 @@ Be aware that you have to run [`nuxt prepare`](/docs/4.x/api/commands/prepare),
56
56
  If you create a composable without having the dev server running, TypeScript will throw an error, such as `Cannot find name 'useBar'.`
57
57
  ::
58
58
 
59
- ## Examples
59
+ ## Example
60
60
 
61
61
  ### Nested Composables
62
62
 
@@ -69,7 +69,7 @@ export const useFoo = () => {
69
69
  }
70
70
  ```
71
71
 
72
- ### Access plugin injections
72
+ ### Access Plugin Injections
73
73
 
74
74
  You can access [plugin injections](/docs/4.x/directory-structure/app/plugins#providing-helpers) from composables:
75
75
 
@@ -7,7 +7,7 @@ navigation.icon: i-vscode-icons-folder-type-server
7
7
 
8
8
  Nuxt automatically scans files inside these directories to register API and server handlers with Hot Module Replacement (HMR) support.
9
9
 
10
- ```bash [Directory structure]
10
+ ```bash [Directory Structure]
11
11
  -| server/
12
12
  ---| api/
13
13
  -----| hello.ts # /api/hello
@@ -21,6 +21,12 @@ Each file should export a default function defined with `defineEventHandler()` o
21
21
 
22
22
  The handler can directly return JSON data, a `Promise`, or a `Response` object.
23
23
 
24
+ ::important
25
+ Do not import Vue app code (components, composables, or other app-only utilities) in your server routes or utilities, and do not import server-only code in your app.
26
+ ::
27
+
28
+ :read-more{to="/docs/4.x/directory-structure/shared#why-you-cannot-mix-vue-and-nitro-code" title="Why You Cannot Mix Vue and Nitro Code"}
29
+
24
30
  ```ts twoslash [server/api/hello.ts]
25
31
  import { defineEventHandler } from 'nitro/h3'
26
32
 
@@ -15,6 +15,22 @@ The `shared/` directory is available in Nuxt v3.14+.
15
15
  Code in the `shared/` directory cannot import any Vue or Nitro code.
16
16
  ::
17
17
 
18
+ ## Why You Cannot Mix Vue and Nitro Code
19
+
20
+ Nuxt builds two separate bundles: the Vue app (client and server-side rendering) and the Nitro server (API routes, server middleware, server plugins). They are bundled independently and run in different contexts. Code in the `shared/` directory is used in both bundles, so it cannot import from either.
21
+
22
+ ### Vue App Code in Nitro
23
+
24
+ Components and composables need the Vue app runtime and often the Nuxt context (for example `useNuxtApp()` or `useRoute()`), neither of which exists in Nitro. Importing them into server code can cause build or runtime errors, and can pull the Vue app's dependencies into your server bundle.
25
+
26
+ ### Nitro Code in the Vue App
27
+
28
+ Server-only code (such as Node APIs, Nitro utilities, or server route handlers) must not run in the browser. Importing it into your app can break the client build, cause runtime errors in the browser, or leak server logic into the client bundle.
29
+
30
+ ### Type-Only Imports
31
+
32
+ `import type` is erased at compile time and does not pull runtime code into the other bundle, so importing only types across the boundary may appear to work. Even so, keep shared types (such as API response types) in `shared/types/`, where they are auto-imported in both contexts. This keeps the boundary clear, avoids accidentally turning a type import into a value import later, and matches Nuxt's separate [type contexts](/docs/4.x/guide/concepts/typescript#project-references) for app, server, and shared code.
33
+
18
34
  :video-accordion{title="Watch a video from Vue School on sharing utils and types between app and server" videoId="nnAR-MO3q5M"}
19
35
 
20
36
  ## Usage
@@ -82,7 +98,7 @@ The way `shared/utils` and `shared/types` auto-imports work and are scanned is i
82
98
 
83
99
  Any other files you create in the `shared/` folder must be manually imported using the `#shared` alias (automatically configured by Nuxt):
84
100
 
85
- ```ts
101
+ ```ts [Importing From #shared]
86
102
  // For files directly in the shared directory
87
103
  import capitalize from '#shared/capitalize'
88
104
 
@@ -5,7 +5,7 @@ description: "Understanding the lifecycle of Nuxt applications can help you gain
5
5
 
6
6
  The goal of this chapter is to provide a high-level overview of the different parts of the framework, their execution order, and how they work together.
7
7
 
8
- ## Server lifecycle
8
+ ## Server Lifecycle
9
9
 
10
10
  On the server, the following steps are executed for every initial request to your application:
11
11
 
@@ -109,7 +109,7 @@ Before finalizing and sending the HTML, Nitro will call the [`render:html`](/doc
109
109
 
110
110
  ::
111
111
 
112
- ## Client lifecycle
112
+ ## Client Lifecycle
113
113
 
114
114
  This part of the lifecycle is fully executed in the browser, no matter which Nuxt mode you've chosen.
115
115
 
@@ -179,7 +179,7 @@ export default defineNuxtConfig({
179
179
  })
180
180
  ```
181
181
 
182
- ## Auto-import from Third-Party Packages
182
+ ## Auto-Import from Third-Party Packages
183
183
 
184
184
  Nuxt also allows auto-importing from third-party packages.
185
185
 
@@ -6,7 +6,7 @@ description: Why fixing hydration issues is important
6
6
 
7
7
  When developing, you may face hydration issues. Don't ignore those warnings.
8
8
 
9
- ## Why is it important to fix them?
9
+ ## Why Is It Important to Fix Them?
10
10
 
11
11
  Hydration mismatches are not just warnings - they are indicators of serious problems that can break your application:
12
12
 
@@ -21,7 +21,7 @@ Hydration mismatches are not just warnings - they are indicators of serious prob
21
21
  - **State inconsistencies**: Application state can become out of sync between what the user sees and what the application thinks is rendered
22
22
  - **SEO problems**: Search engines may index different content than what users actually see
23
23
 
24
- ## How to detect them
24
+ ## How to Detect Them
25
25
 
26
26
  ### Development Console Warnings
27
27
 
@@ -29,7 +29,7 @@ Vue will log hydration mismatch warnings in the browser console during developme
29
29
 
30
30
  ![Screenshot of Vue hydration mismatch warning in the browser console](/assets/docs/best-practices/vue-console-hydration.png)
31
31
 
32
- ## Common reasons
32
+ ## Common Reasons
33
33
 
34
34
  ### Browser-only APIs in Server Context
35
35
 
@@ -176,7 +176,7 @@ onMounted(() => {
176
176
  </script>
177
177
  ```
178
178
 
179
- ## In summary
179
+ ## In Summary
180
180
 
181
181
  1. **Use SSR-friendly composables**: [`useFetch`](/docs/4.x/api/composables/use-fetch), [`useAsyncData`](/docs/4.x/api/composables/use-async-data), [`useState`](/docs/4.x/api/composables/use-state)
182
182
  2. **Wrap client-only code**: Use [`ClientOnly`](/docs/4.x/api/components/client-only) component for browser-specific content
@@ -264,7 +264,7 @@ It provides both lab and field data about a page. Lab data is useful for debuggi
264
264
 
265
265
  Each test can be run from different locations around the world, on real browsers, over any number of customizable network conditions.
266
266
 
267
- ## Common problems
267
+ ## Common Problems
268
268
 
269
269
  When building more complex Nuxt applications, you will probably encounter some of the problems listed below. Understanding these problems and fixing them will help you improve performance of your website.
270
270
 
@@ -6,15 +6,15 @@ description: Best practices when using Nuxt plugins.
6
6
 
7
7
  Plugins in Nuxt allow you to extend your application with additional functionality. However, improper use can lead to performance bottlenecks. This guide outlines best practices to optimize your Nuxt plugins.
8
8
 
9
- ## Avoid costly plugin setup
9
+ ## Avoid Costly Plugin Setup
10
10
 
11
11
  A large number of plugins can cause performance issues, especially if they require expensive computations or take too long to initialize. Since plugins run during the hydration phase, inefficient setups can block rendering and degrade the user experience.
12
12
 
13
- ## Use Composition whenever possible
13
+ ## Use Composition Whenever Possible
14
14
 
15
15
  Whenever possible, favor composition over plugins. Just like in Vue, many utilities and composables can be used directly without the need for a plugin. This keeps your project lightweight and improves maintainability.
16
16
 
17
- ## If `async`, enable `parallel`
17
+ ## If `async`, Enable `parallel`
18
18
 
19
19
  By default, all plugins loads synchronously.
20
20
  When defining asynchronous plugins, setting `parallel: true` allows multiple plugins to load concurrently, improving performance by preventing blocking operations.
@@ -4,7 +4,7 @@ description: Use Nuxt documentation in your AI assistants with Model Context Pro
4
4
  navigation.title: MCP Server
5
5
  ---
6
6
 
7
- ## What is MCP?
7
+ ## What Is MCP?
8
8
 
9
9
  MCP (Model Context Protocol) is a standardized protocol that enables AI assistants to access external data sources and tools. Nuxt provides an MCP server that allows AI assistants like Claude Code, Cursor, and Windsurf to access documentation, blog posts, and deployment guides directly.
10
10
 
@@ -4,13 +4,13 @@ description: How to get AI tools like Cursor, Windsurf, GitHub Copilot, ChatGPT,
4
4
  navigation.title: LLMs.txt
5
5
  ---
6
6
 
7
- ## What is LLMs.txt?
7
+ ## What Is LLMs.txt?
8
8
 
9
9
  LLMs.txt is a structured documentation format specifically designed for large language models (LLMs). Nuxt provides LLMs.txt files that contain comprehensive information about the framework, making it easy for AI tools to understand and assist with Nuxt development.
10
10
 
11
11
  These files are optimized for AI consumption and contain structured information about concepts, APIs, usage patterns, and best practices.
12
12
 
13
- ## Available routes
13
+ ## Available Routes
14
14
 
15
15
  We provide LLMs.txt routes to help AI tools access our documentation:
16
16
 
@@ -25,7 +25,7 @@ We provide LLMs.txt routes to help AI tools access our documentation:
25
25
  Use `/llms-full.txt` only if you need comprehensive implementation details and your AI tool supports large contexts (200K+ tokens).
26
26
  ::
27
27
 
28
- ## Important usage notes
28
+ ## Important Usage Notes
29
29
 
30
30
  ::warning{icon="i-lucide-alert-triangle"}
31
31
  **@-symbol must be typed manually** - When using tools like Cursor or Windsurf, the `@` symbol must be typed by hand in the chat interface. Copy-pasting breaks the tool's ability to recognize it as a context reference.
@@ -23,7 +23,7 @@ Watch Vue School video about Nuxt module types.
23
23
 
24
24
  Any community modules are welcome to be listed on [the module list](/modules). To be listed, [open an issue in the nuxt/modules](https://github.com/nuxt/modules/issues/new?template=module_request.yml) repository. The Nuxt team can help you to apply best practices before listing.
25
25
 
26
- ## Join nuxt-modules
26
+ ## Join `nuxt-modules`
27
27
 
28
28
  By moving your modules to [nuxt-modules](https://github.com/nuxt-modules), there is always someone else to help, and this way, we can join forces to make one perfect solution.
29
29
 
@@ -3,7 +3,7 @@ title: "Custom Routing"
3
3
  description: "In Nuxt, your routing is defined by the structure of your files inside the pages directory. However, since it uses vue-router under the hood, Nuxt offers you several ways to add custom routes in your project."
4
4
  ---
5
5
 
6
- ## Adding custom routes
6
+ ## Adding Custom Routes
7
7
 
8
8
  In Nuxt, your routing is defined by the structure of your files inside the [app/pages directory](/docs/4.x/directory-structure/app/pages). However, since it uses [vue-router](https://router.vuejs.org) under the hood, Nuxt offers you several ways to add custom routes in your project.
9
9
 
@@ -9,7 +9,7 @@ In this recipe we'll be setting up authentication in a full-stack Nuxt app using
9
9
 
10
10
  The module uses secured & sealed cookies to store session data, so you don't need to setup a database to store session data.
11
11
 
12
- ## Install nuxt-auth-utils
12
+ ## Install `nuxt-auth-utils`
13
13
 
14
14
  Install the `nuxt-auth-utils` module using the `nuxt` CLI.
15
15
 
@@ -334,6 +334,10 @@ export default defineNuxtConfig({
334
334
 
335
335
  :read-more{to="/docs/4.x/directory-structure/app/components#server-components"}
336
336
 
337
+ ::note
338
+ Skip `nuxt-client` on non-SFC components such as [`<NuxtLink>`](/docs/4.x/api/components/nuxt-link). See [Client components within server components](/docs/4.x/directory-structure/app/components#client-components-within-server-components).
339
+ ::
340
+
337
341
  ::read-more{icon="i-simple-icons-github" to="https://github.com/nuxt/nuxt/issues/19772" target="_blank"}
338
342
  You can follow the server components roadmap on GitHub.
339
343
  ::
@@ -911,9 +915,11 @@ export default defineNuxtConfig({
911
915
 
912
916
  ## pendingWhenIdle
913
917
 
914
- For `useAsyncData` and `useFetch`, whether `pending` should be `true` when data has not yet started to be fetched.
918
+ `pendingWhenIdle` controls the `pending` ref returned by `useAsyncData` and `useFetch`.
915
919
 
916
- This flag is disabled by default, but you can enable this feature:
920
+ When `pendingWhenIdle` is `false` (the default), `pending` is `true` while a request is in flight and matches `status === 'pending'`. While `status` is `idle`, `pending` stays `false`. You can see this with `{ immediate: false }`, or with `{ server: false }` during server rendering.
921
+
922
+ Set `pendingWhenIdle: true` so `pending` is also `true` when `status` is `idle` and no cached data is available. Use `status` when your loading UI needs to distinguish `idle` from an in-flight request.
917
923
 
918
924
  ```ts twoslash [nuxt.config.ts]
919
925
  export default defineNuxtConfig({
@@ -19,7 +19,7 @@ The content of the default slot will be tree-shaken out of the server build. (Th
19
19
  - `placeholderTag` | `fallbackTag`: specify a tag to be rendered server-side.
20
20
  - `placeholder` | `fallback`: specify a content to be rendered server-side.
21
21
 
22
- ```vue
22
+ ```vue [app/pages/example.vue]
23
23
  <template>
24
24
  <div>
25
25
  <Sidebar />
@@ -55,7 +55,7 @@ The content of the default slot will be tree-shaken out of the server build. (Th
55
55
  </template>
56
56
  ```
57
57
 
58
- ## Examples
58
+ ## Example
59
59
 
60
60
  ### Accessing HTML Elements
61
61
 
@@ -18,7 +18,7 @@ The `<NuxtTime>` component lets you display dates and times in a locale-friendly
18
18
 
19
19
  You can use the `<NuxtTime>` component anywhere in your app:
20
20
 
21
- ```vue
21
+ ```vue [app/app.vue]
22
22
  <template>
23
23
  <NuxtTime :datetime="Date.now()" />
24
24
  </template>
@@ -36,7 +36,7 @@ The date and time value to display. You can provide:
36
36
  - A timestamp (number)
37
37
  - An ISO-formatted date string
38
38
 
39
- ```vue
39
+ ```vue [app/app.vue]
40
40
  <template>
41
41
  <NuxtTime :datetime="Date.now()" />
42
42
  <NuxtTime :datetime="new Date()" />
@@ -52,7 +52,7 @@ The date and time value to display. You can provide:
52
52
 
53
53
  The [BCP 47 language tag](https://datatracker.ietf.org/doc/html/rfc5646) for formatting (e.g., 'en-US', 'fr-FR', 'ja-JP'):
54
54
 
55
- ```vue
55
+ ```vue [app/app.vue]
56
56
  <template>
57
57
  <NuxtTime
58
58
  :datetime="Date.now()"
@@ -65,7 +65,7 @@ The [BCP 47 language tag](https://datatracker.ietf.org/doc/html/rfc5646) for for
65
65
 
66
66
  The component accepts any property from the [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) options:
67
67
 
68
- ```vue
68
+ ```vue [app/app.vue]
69
69
  <template>
70
70
  <NuxtTime
71
71
  :datetime="Date.now()"
@@ -88,7 +88,7 @@ This would output something like: "April 22, 2025, 08:30 AM"
88
88
 
89
89
  Enables relative time formatting using the Intl.RelativeTimeFormat API:
90
90
 
91
- ```vue
91
+ ```vue [app/app.vue]
92
92
  <template>
93
93
  <!-- Shows something like "5 minutes ago" -->
94
94
  <NuxtTime
@@ -106,7 +106,7 @@ When `relative` is set to `true`, the component also accepts properties from [In
106
106
  Due to `style` being a reserved prop, `relativeStyle` prop is used instead.
107
107
  ::
108
108
 
109
- ```vue
109
+ ```vue [app/app.vue]
110
110
  <template>
111
111
  <NuxtTime
112
112
  :datetime="Date.now() - 3 * 24 * 60 * 60 * 1000"
@@ -119,11 +119,11 @@ Due to `style` being a reserved prop, `relativeStyle` prop is used instead.
119
119
 
120
120
  This would output something like: "3 days ago" or "last Friday" depending on the `numeric` setting.
121
121
 
122
- ## Examples
122
+ ## Example
123
123
 
124
124
  ### Basic Usage
125
125
 
126
- ```vue
126
+ ```vue [app/app.vue]
127
127
  <template>
128
128
  <NuxtTime :datetime="Date.now()" />
129
129
  </template>
@@ -131,7 +131,7 @@ This would output something like: "3 days ago" or "last Friday" depending on the
131
131
 
132
132
  ### Custom Formatting
133
133
 
134
- ```vue
134
+ ```vue [app/app.vue]
135
135
  <template>
136
136
  <NuxtTime
137
137
  :datetime="Date.now()"
@@ -149,7 +149,7 @@ This would output something like: "3 days ago" or "last Friday" depending on the
149
149
 
150
150
  ### Relative Time
151
151
 
152
- ```vue
152
+ ```vue [app/app.vue]
153
153
  <template>
154
154
  <div>
155
155
  <p>
@@ -179,7 +179,7 @@ This would output something like: "3 days ago" or "last Friday" depending on the
179
179
 
180
180
  ### With Custom Locale
181
181
 
182
- ```vue
182
+ ```vue [app/app.vue]
183
183
  <template>
184
184
  <div>
185
185
  <NuxtTime
@@ -16,7 +16,7 @@ The `<NuxtErrorBoundary>` uses Vue's [`onErrorCaptured`](https://vuejs.org/api/c
16
16
 
17
17
  - `@error`: Event emitted when the default slot of the component throws an error.
18
18
 
19
- ```vue
19
+ ```vue [app/app.vue]
20
20
  <template>
21
21
  <NuxtErrorBoundary @error="logSomeError">
22
22
  <!-- ... -->
@@ -28,7 +28,7 @@ The `<NuxtErrorBoundary>` uses Vue's [`onErrorCaptured`](https://vuejs.org/api/c
28
28
 
29
29
  - `#error`: Specify a fallback content to display in case of error.
30
30
 
31
- ```vue
31
+ ```vue [app/app.vue]
32
32
  <template>
33
33
  <NuxtErrorBoundary>
34
34
  <!-- ... -->
@@ -45,13 +45,13 @@ The `<NuxtErrorBoundary>` uses Vue's [`onErrorCaptured`](https://vuejs.org/api/c
45
45
 
46
46
  :read-more{to="/docs/4.x/getting-started/error-handling"}
47
47
 
48
- ## Examples
48
+ ## Example
49
49
 
50
- ### Accessing `error` and `clearError` in script
50
+ ### Accessing `error` and `clearError` in Script
51
51
 
52
52
  You can access `error` and `clearError` properties within the component's script as below:
53
53
 
54
- ```vue
54
+ ```vue [app/app.vue]
55
55
  <template>
56
56
  <NuxtErrorBoundary ref="errorBoundary">
57
57
  <!-- ... -->
@@ -56,6 +56,27 @@ Component props and context are sent as GET query parameters to enable caching.
56
56
  By default, component islands are scanned from the `~/components/islands/` directory. So the `~/components/islands/MyIsland.vue` component could be rendered with `<NuxtIsland name="MyIsland" />`.
57
57
  ::
58
58
 
59
+ ## Known Limitations
60
+
61
+ ### `useId` in island and server components
62
+
63
+ Each island is rendered in its own Vue app on the server, so Vue's [`useId`](https://vuejs.org/api/composition-api-helpers#useid) counter restarts for every island. Ids generated inside an island can therefore collide with ids generated by other islands on the same page, or by the rest of your app.
64
+
65
+ **Workaround**: set a distinct [`idPrefix`](https://vuejs.org/api/application#app-config-idprefix) on the island's Vue app from a server plugin, based on the island context id:
66
+
67
+ ```ts [plugins/island-id-prefix.server.ts]
68
+ export default defineNuxtPlugin((nuxtApp) => {
69
+ const islandContext = nuxtApp.ssrContext?.islandContext
70
+ if (islandContext) {
71
+ nuxtApp.vueApp.config.idPrefix = `${islandContext.id}-v`
72
+ }
73
+ })
74
+ ```
75
+
76
+ - **Identical islands still share the same ids.** Two instances of the same island rendered with the same name, props and context share a single server render (and payload entry), so their HTML — including any `useId`-generated ids — is identical, and the island context id used as prefix is the same. This results in duplicated `id` attributes in the DOM, which can break `aria-*` references and `<label for>` associations between the two instances. There is currently no workaround for this case.
77
+
78
+ - **`useId` does not work in interactive components inside islands.** A component loaded with the [`nuxt-client` attribute](/docs/4.x/directory-structure/app/components#client-components-within-server-components) is server-rendered inside the island's app but hydrated by the main client app, so `useId` returns different values on the server and on the client, causing a hydration mismatch.
79
+
59
80
  ## Slots
60
81
 
61
82
  Slots can be passed to an island component if declared.
@@ -20,7 +20,7 @@ This is an advanced utility and should be used with care. For example, [`nuxt-ti
20
20
 
21
21
  ## Usage
22
22
 
23
- Call `onPrehydrate` in the setup function of a Vue component (e.g., in `<script setup>`) or in a plugin. It only has an effect when called on the server and will not be included in your client build.
23
+ Call `onPrehydrate` in the setup function of a Vue component (e.g., in `<script setup>`) or in a plugin. The call itself only has an effect when made on the server and is stripped from your client build. The callback you pass, however, is serialized and inlined into the HTML, so it runs in the **browser** immediately before Nuxt hydrates. This means it can access browser globals like `window` and the DOM.
24
24
 
25
25
  ## Type
26
26
 
@@ -47,8 +47,8 @@ export function onPrehydrate (callback: string | ((el: HTMLElement) => void), ke
47
47
  <script setup lang="ts">
48
48
  declare const window: Window
49
49
  // ---cut---
50
- // Run code before Nuxt hydrates
51
50
  onPrehydrate(() => {
51
+ // Runs in the browser, right before Nuxt hydrates
52
52
  console.log(window)
53
53
  })
54
54
 
@@ -68,3 +68,13 @@ const prehydrateId = onPrehydrate((el) => {})
68
68
  </div>
69
69
  </template>
70
70
  ```
71
+
72
+ Under the hood, the callback is stringified and minified at build time, then inlined as a `<script>` tag in the server-rendered HTML, just before the closing `</body>` tag. For the example above, the rendered HTML includes something like:
73
+
74
+ ```html
75
+ <div data-prehydrate-id=":b3qlvSiBeH:"> Hi there </div>
76
+ <script>(()=>{console.log(window)})()</script>
77
+ <script>document.querySelectorAll('[data-prehydrate-id*=":b3qlvSiBeH:"]').forEach(el=>{console.log(el.outerHTML)})</script>
78
+ ```
79
+
80
+ When the callback accepts an `el` parameter, the component's root element is tagged with a `data-prehydrate-id` attribute so the inlined script can find it.