@nuxt/docs 4.0.1 → 4.0.3

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.
@@ -39,19 +39,19 @@ Open a terminal (if you're using [Visual Studio Code](https://code.visualstudio.
39
39
  ::code-group{sync="pm"}
40
40
 
41
41
  ```bash [npm]
42
- npm create nuxt <project-name>
42
+ npm create nuxt@latest <project-name>
43
43
  ```
44
44
 
45
45
  ```bash [yarn]
46
- yarn create nuxt <project-name>
46
+ yarn create nuxt@latest <project-name>
47
47
  ```
48
48
 
49
49
  ```bash [pnpm]
50
- pnpm create nuxt <project-name>
50
+ pnpm create nuxt@latest <project-name>
51
51
  ```
52
52
 
53
53
  ```bash [bun]
54
- bun create nuxt <project-name>
54
+ bun create nuxt@latest <project-name>
55
55
  ```
56
56
 
57
57
  ```bash [deno]
@@ -1072,7 +1072,16 @@ However, to take advantage of improved type checking, you can opt in to the new
1072
1072
  + "typecheck": "nuxt prepare && vue-tsc -b --noEmit"
1073
1073
  ```
1074
1074
 
1075
- 4. **Configure Node.js TypeScript options** if needed:
1075
+ 4. **Move all type augmentations into their appropriate context**:
1076
+ * If you are augmenting types for the app context, move the files to the `app/` directory.
1077
+ * If you are augmenting types for the server context, move the files to the `server/` directory.
1078
+ * If you are augmenting types that are **shared between the app and server**, move the files to the `shared/` directory.
1079
+
1080
+ ::warning
1081
+ Augmenting types from outside the `app/`, `server/`, or `shared/` directories will not work with the new project references setup.
1082
+ ::
1083
+
1084
+ 5. **Configure Node.js TypeScript options** if needed:
1076
1085
  <!-- @case-police-ignore tsConfig -->
1077
1086
 
1078
1087
  ```ts
@@ -1094,7 +1103,7 @@ However, to take advantage of improved type checking, you can opt in to the new
1094
1103
  })
1095
1104
  ```
1096
1105
 
1097
- 5. **Update any CI/build scripts** that run TypeScript checking to ensure they use the new project references approach.
1106
+ 6. **Update any CI/build scripts** that run TypeScript checking to ensure they use the new project references approach.
1098
1107
 
1099
1108
  The new configuration provides better type safety and IntelliSense for projects that opt in, while maintaining full backward compatibility for existing setups.
1100
1109
 
@@ -68,7 +68,7 @@ In Nuxt, there are three types of middleware:
68
68
  - **Named route middleware**
69
69
  - **Anonymous (or inline) route middleware**
70
70
 
71
- Nuxt automatically executes global middleware for first time enter to the application and every time before route navigation. Named and anonymous middleware are executed only on the routes specified in the middleware property of the page(route) meta defined in the corresponding page components.
71
+ Nuxt executes all global middleware on the initial page load (both on server and client) and then again before any client-side navigation. Named and anonymous middleware are executed only on the routes specified in the middleware property of the page(route) meta defined in the corresponding page components.
72
72
 
73
73
  For details about each type and examples, see the [Middleware documentation](/docs/guide/directory-structure/middleware).
74
74
 
@@ -108,6 +108,20 @@ Each of these files is configured to reference the appropriate dependencies and
108
108
  The project reference setup is handled automatically by Nuxt. You typically don't need to modify these configurations manually, but understanding how they work can help you troubleshoot type-checking issues.
109
109
  ::
110
110
 
111
+ ### Augmenting Types with Project References
112
+
113
+ Since the project is divided into **multiple type contexts**, it's important to **augment types within the correct context** to ensure they are properly recognized.
114
+
115
+ For example, if you want to augment types for the `app` context, the augmentation file should be placed in the `app/` directory.
116
+
117
+ Similarly:
118
+ - For the `server` context, place the augmentation file in the `server/` directory.
119
+ - For types that are **shared between the app and server**, place the file in the `shared/` directory.
120
+
121
+ ::warning
122
+ Augmenting types outside of these directories will not be recognized by TypeScript.
123
+ ::
124
+
111
125
  ## Strict Checks
112
126
 
113
127
  TypeScript comes with certain checks to give you more safety and analysis of your program.
@@ -26,8 +26,8 @@ Update `nuxt` dependency inside `package.json`:
26
26
  ```diff [package.json]
27
27
  {
28
28
  "devDependencies": {
29
- -- "nuxt": "^3.0.0"
30
- ++ "nuxt": "npm:nuxt-nightly@3x"
29
+ -- "nuxt": "^4.0.0"
30
+ ++ "nuxt": "npm:nuxt-nightly@latest"
31
31
  }
32
32
  }
33
33
  ```
@@ -41,8 +41,8 @@ Update `nuxt` dependency inside `package.json`:
41
41
  ```diff [package.json]
42
42
  {
43
43
  "devDependencies": {
44
- -- "nuxt": "npm:nuxt-nightly@3x"
45
- ++ "nuxt": "^3.0.0"
44
+ -- "nuxt": "npm:nuxt-nightly@latest"
45
+ ++ "nuxt": "^4.0.0"
46
46
  }
47
47
  }
48
48
  ```
@@ -0,0 +1,188 @@
1
+ ---
2
+ navigation.title: 'Nuxt and hydration'
3
+ title: Nuxt and hydration
4
+ description: Why fixing hydration issues is important
5
+ ---
6
+
7
+ When developing, you may face hydration issues. Don't ignore those warnings.
8
+
9
+ # Why is it important to fix them?
10
+
11
+ Hydration mismatches are not just warnings - they are indicators of serious problems that can break your application:
12
+
13
+ ## Performance Impact
14
+
15
+ - **Increased time to interactive**: Hydration errors force Vue to re-render the entire component tree, which will increase the time for your Nuxt app to become interactive
16
+ - **Poor user experience**: Users may see content flashing or unexpected layout shifts
17
+
18
+ ## Functionality Issues
19
+
20
+ - **Broken interactivity**: Event listeners may not attach properly, leaving buttons and forms non-functional
21
+ - **State inconsistencies**: Application state can become out of sync between what the user sees and what the application thinks is rendered
22
+ - **SEO problems**: Search engines may index different content than what users actually see
23
+
24
+ # How to detect them
25
+
26
+ ## Development Console Warnings
27
+
28
+ Vue will log hydration mismatch warnings in the browser console during development:
29
+
30
+ ![Screenshot of Vue hydration mismatch warning in the browser console](/assets/docs/best-practices/vue-console-hydration.png)
31
+
32
+ # Common reasons
33
+
34
+ ## Browser-only APIs in Server Context
35
+
36
+ **Problem**: Using browser-specific APIs during server-side rendering.
37
+
38
+ ```html
39
+ <template>
40
+ <div>User preference: {{ userTheme }}</div>
41
+ </template>
42
+
43
+ <script setup>
44
+ // This will cause hydration mismatch!
45
+ // localStorage doesn't exist on the server!
46
+ const userTheme = localStorage.getItem('theme') || 'light'
47
+ </script>
48
+ ```
49
+
50
+ **Solution**: You can use [`useCookie`](/docs/api/composables/use-cookie):
51
+
52
+ ```html
53
+ <template>
54
+ <div>User preference: {{ userTheme }}</div>
55
+ </template>
56
+
57
+ <script setup>
58
+ // This works on both server and client
59
+ const userTheme = useCookie('theme', { default: () => 'light' })
60
+ </script>
61
+ ```
62
+
63
+ ## Inconsistent Data
64
+
65
+ **Problem**: Different data between server and client.
66
+
67
+ ```html
68
+ <template>
69
+ <div>{{ Math.random() }}</div>
70
+ </template>
71
+ ```
72
+
73
+ **Solution**: Use SSR-friendly state:
74
+
75
+ ```html
76
+ <template>
77
+ <div>{{ state }}</div>
78
+ </template>
79
+
80
+ <script setup>
81
+ const state = useState('random', () => Math.random())
82
+ </script>
83
+ ```
84
+
85
+ ## Conditional Rendering Based on Client State
86
+
87
+ **Problem**: Using client-only conditions during SSR.
88
+
89
+ ```html
90
+ <template>
91
+ <div v-if="window?.innerWidth > 768">
92
+ Desktop content
93
+ </div>
94
+ </template>
95
+ ```
96
+
97
+ **Solution**: Use media queries or handle it client-side:
98
+
99
+ ```html
100
+ <template>
101
+ <div class="responsive-content">
102
+ <div class="hidden md:block">Desktop content</div>
103
+ <div class="md:hidden">Mobile content</div>
104
+ </div>
105
+ </template>
106
+ ```
107
+
108
+ ## Third-party Libraries with Side Effects
109
+
110
+ **Problem**: Libraries that modify the DOM or have browser dependencies (this happens a LOT with tag managers).
111
+
112
+ ```html
113
+ <script setup>
114
+ if (import.meta.client) {
115
+ const { default: SomeBrowserLibrary } = await import('browser-only-lib')
116
+ SomeBrowserLibrary.init()
117
+ }
118
+ </script>
119
+ ```
120
+
121
+ **Solution**: Initialise libraries after hydration has completed:
122
+
123
+ ```html
124
+ <script setup>
125
+ onMounted(async () => {
126
+ const { default: SomeBrowserLibrary } = await import('browser-only-lib')
127
+ SomeBrowserLibrary.init()
128
+ })
129
+ </script>
130
+ ```
131
+
132
+ ## Dynamic Content Based on Time
133
+
134
+ **Problem**: Content that changes based on current time.
135
+
136
+ ```html
137
+ <template>
138
+ <div>{{ greeting }}</div>
139
+ </template>
140
+
141
+ <script setup>
142
+ const hour = new Date().getHours()
143
+ const greeting = hour < 12 ? 'Good morning' : 'Good afternoon'
144
+ </script>
145
+ ```
146
+
147
+ **Solution**: Use [`NuxtTime`](/docs/api/components/nuxt-time) component or handle it client-side:
148
+
149
+ ```html
150
+ <template>
151
+ <div>
152
+ <NuxtTime :date="new Date()" format="HH:mm" />
153
+ </div>
154
+ </template>
155
+ ```
156
+
157
+ ```html
158
+ <template>
159
+ <div>
160
+ <ClientOnly>
161
+ {{ greeting }}
162
+ <template #fallback>
163
+ Hello!
164
+ </template>
165
+ </ClientOnly>
166
+ </div>
167
+ </template>
168
+
169
+ <script setup>
170
+ const greeting = ref('Hello!')
171
+
172
+ onMounted(() => {
173
+ const hour = new Date().getHours()
174
+ greeting.value = hour < 12 ? 'Good morning' : 'Good afternoon'
175
+ })
176
+ </script>
177
+ ```
178
+
179
+ ## In summary
180
+
181
+ 1. **Use SSR-friendly composables**: [`useFetch`](/docs/api/composables/use-fetch), [`useAsyncData`](/docs/api/composables/use-async-data), [`useState`](/docs/api/composables/use-state)
182
+ 2. **Wrap client-only code**: Use [`ClientOnly`](/docs/api/components/client-only) component for browser-specific content
183
+ 3. **Consistent data sources**: Ensure server and client uses the same data
184
+ 4. **Avoid side effects in setup**: Move browser-dependent code to `onMounted`
185
+
186
+ ::tip
187
+ You can read the [Vue documentation on SSR hydration mismatch](https://vuejs.org/guide/scaling-up/ssr.html#hydration-mismatch) for a better understanding of hydration.
188
+ ::
@@ -226,7 +226,7 @@ export default defineNuxtConfig({
226
226
 
227
227
  When not using `external`, `<NuxtLink>` supports all Vue Router's [`RouterLink` props](https://router.vuejs.org/api/interfaces/RouterLinkProps.html)
228
228
 
229
- - `to`: Any URL or a [route location object](https://router.vuejs.org/api/#RouteLocation) from Vue Router
229
+ - `to`: Any URL or a [route location object](https://router.vuejs.org/api/type-aliases/RouteLocation.html) from Vue Router
230
230
  - `custom`: Whether `<NuxtLink>` should wrap its content in an `<a>` element. It allows taking full control of how a link is rendered and how navigation works when it is clicked. Works the same as [Vue Router's `custom` prop](https://router.vuejs.org/api/interfaces/RouterLinkProps.html#Properties-custom)
231
231
  - `exactActiveClass`: A class to apply on exact active links. Works the same as [Vue Router's `exactActiveClass` prop](https://router.vuejs.org/api/interfaces/RouterLinkProps.html#Properties-exactActiveClass) on internal links. Defaults to Vue Router's default (`"router-link-exact-active"`)
232
232
  - `activeClass`: A class to apply on active links. Works the same as [Vue Router's `activeClass` prop](https://router.vuejs.org/api/interfaces/RouterLinkProps.html#Properties-activeClass) on internal links. Defaults to Vue Router's default (`"router-link-active"`)
@@ -49,4 +49,4 @@ Apart from dynamic parameters and query parameters, `useRoute()` also provides t
49
49
  Browsers don't send [URL fragments](https://url.spec.whatwg.org/#concept-url-fragment) (for example `#foo`) when making requests. So using `route.fullPath` in your template can trigger hydration issues because this will include the fragment on client but not the server.
50
50
  ::
51
51
 
52
- :read-more{icon="i-simple-icons-vuedotjs" to="https://router.vuejs.org/api/#RouteLocationNormalizedLoaded"}
52
+ :read-more{icon="i-simple-icons-vuedotjs" to="https://router.vuejs.org/api/type-aliases/RouteLocationNormalizedLoaded.html"}
@@ -28,7 +28,7 @@ interface RouteMiddleware {
28
28
 
29
29
  A function that takes two Vue Router's route location objects as parameters: the next route `to` as the first, and the current route `from` as the second.
30
30
 
31
- Learn more about available properties of `RouteLocationNormalized` in the **[Vue Router docs](https://router.vuejs.org/api/#RouteLocationNormalized)**.
31
+ Learn more about available properties of `RouteLocationNormalized` in the **[Vue Router docs](https://router.vuejs.org/api/type-aliases/RouteLocationNormalized.html)**.
32
32
 
33
33
  ## Examples
34
34
 
@@ -8,4 +8,4 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- :read-more{icon="i-simple-icons-vuedotjs" to="https://router.vuejs.org/api/#onBeforeRouteLeave" title="Vue Router Docs" target="_blank"}
11
+ :read-more{icon="i-simple-icons-vuedotjs" to="https://router.vuejs.org/api/functions/onBeforeRouteLeave.html" title="Vue Router Docs" target="_blank"}
@@ -8,4 +8,4 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- :read-more{icon="i-simple-icons-vuedotjs" to="https://router.vuejs.org/api/#onBeforeRouteUpdate" title="Vue Router Docs" target="_blank"}
11
+ :read-more{icon="i-simple-icons-vuedotjs" to="https://router.vuejs.org/api/functions/onBeforeRouteUpdate.html" title="Vue Router Docs" target="_blank"}
@@ -44,6 +44,12 @@ import type { ModuleDefinition, ModuleOptions, NuxtModule } from '@nuxt/schema'
44
44
  export function defineNuxtModule<TOptions extends ModuleOptions> (
45
45
  definition?: ModuleDefinition<TOptions, Partial<TOptions>, false> | NuxtModule<TOptions, Partial<TOptions>, false>,
46
46
  ): NuxtModule<TOptions, TOptions, false>
47
+
48
+ export function defineNuxtModule<TOptions extends ModuleOptions> (): {
49
+ with: <TOptionsDefaults extends Partial<TOptions>> (
50
+ definition: ModuleDefinition<TOptions, TOptionsDefaults, true> | NuxtModule<TOptions, TOptionsDefaults, true>
51
+ ) => NuxtModule<TOptions, TOptionsDefaults, true>
52
+ }
47
53
  ```
48
54
 
49
55
  ### Parameters
@@ -122,6 +128,49 @@ If the user tries to use your module with an incompatible Nuxt version, they wil
122
128
  - [nuxt] Nuxt version ^3.1.0 is required but currently using 3.0.0
123
129
  ```
124
130
 
131
+ #### Type Safety for Resolved Options with `.with()`
132
+
133
+ When you need type safety for your resolved/merged module options, you can use the `.with()` method. This enables TypeScript to properly infer the relationship between your module's defaults and the final resolved options that your setup function receives.
134
+
135
+ ```ts
136
+ import { defineNuxtModule } from '@nuxt/kit'
137
+
138
+ // Define your module options interface
139
+ interface ModuleOptions {
140
+ apiKey: string
141
+ baseURL: string
142
+ timeout?: number
143
+ retries?: number
144
+ }
145
+
146
+ export default defineNuxtModule<ModuleOptions>().with({
147
+ meta: {
148
+ name: '@nuxtjs/my-api',
149
+ configKey: 'myApi'
150
+ },
151
+ defaults: {
152
+ baseURL: 'https://api.example.com',
153
+ timeout: 5000,
154
+ retries: 3
155
+ },
156
+ setup(resolvedOptions, nuxt) {
157
+ // resolvedOptions is properly typed as:
158
+ // {
159
+ // apiKey: string // Required, no default provided
160
+ // baseURL: string // Required, has default value
161
+ // timeout: number // Optional, has default value
162
+ // retries: number // Optional, has default value
163
+ // }
164
+
165
+ console.log(resolvedOptions.baseURL) // ✅ TypeScript knows this is always defined
166
+ console.log(resolvedOptions.timeout) // ✅ TypeScript knows this is always defined
167
+ console.log(resolvedOptions.retries) // ✅ TypeScript knows this is always defined
168
+ }
169
+ })
170
+ ```
171
+
172
+ Without using `.with()`, the `resolvedOptions` parameter would be typed as the raw `ModuleOptions` interface, where `timeout` and `retries` could be `undefined` even when defaults are provided. The `.with()` method enables TypeScript to understand that default values make those properties non-optional in the resolved options.
173
+
125
174
  ## `installModule`
126
175
 
127
176
  Install specified Nuxt module programmatically. This is helpful when your module depends on other modules. You can pass the module options as an object to `inlineOptions` and they will be passed to the module's `setup` function.
@@ -19,7 +19,7 @@ You can improve your DX by defining additional aliases to access custom director
19
19
  "@@": "/<rootDir>",
20
20
  "#shared": "/<rootDir>/shared",
21
21
  "assets": "/<srcDir>/assets",
22
- "public": "/<srcDir>/public",
22
+ "public": "/<rootDir>/public",
23
23
  "#build": "/<rootDir>/.nuxt",
24
24
  "#internal/nuxt/paths": "/<rootDir>/.nuxt/paths.mjs"
25
25
  }
@@ -80,6 +80,24 @@ If we mark a PR as 'pending', that means we likely have another task to do in re
80
80
 
81
81
  We'll do our best to follow [our PR decision making flowchart](https://mermaid.live/view#pako:eNp9VE1v2kAQ_SsjXzBSEqlALlaUisSh0ACK2l4qcVm8Y9hi7672Iwly-O-ZtYPt5FAOCHbee_PmzdpVlCmOURLlhXrJ9sw4-JNuJNBnWs1UQafIQVjrERyWumAOv58-AJeXt29_0b7BXbWwwL0uRPa1vlZvcB_fF8oiMMmB2QM4BXkt3UoON7Lh3LWaDz2SVkK6QGt7DHvw0CKt5sxCKaQoWQEGtVHcZ04oGdw04LTVngW_LHOeFcURGGz97mw6PSv-iJdsi0UCA4nI7SfNwc3W3JZit3eQ1SZFDlKB15yswQ2MgbOjbYeatY3n8bcr-IWlekYYaJRcyB04I9gOB1CEfkF5dAVTzmFAtnqn4-bUYAiMMmHZgWhNPRhgus5mW2BATxq0NkIZ4Y4NbNjzE2ZchBzcHmGLe_ZMSKCcyRXyLrVFa_5n_PBK2xKy3kk9eOjULUdltk6C8kI-7NFDr8f4EVGDoqlp-wa4sJm3ltIMIuZ_mTQXJyTSkQZtunPqsKxShV9GKdkBYe1fHXjpbcjlvONlO9Kqx_M7YHmOmav_luxfE5zKwVs09hM5DLSupgYDlr5flDkwo7ykixKG-xDsUly1LZ-uY32dgDc7lG7YqwbNp0msJwmIUivjWFtfd-xRrEcJ7Omydz37qFplHOtxEp4GskI2qB5dRCWakglOz3oV8JuITJa4iRL6yZk5bKKNPBGOead-H2UWJc54vIiaW53SPgwrz4fIhVNm1bw76lfI6R2_MW21) when responding and reviewing to pull requests.
82
82
 
83
+ ### AI-Assisted Contributions
84
+
85
+ We welcome the thoughtful use of AI tools when contributing to Nuxt, yet ask all contributors to follow [two core principles](https://roe.dev/blog/using-ai-in-open-source).
86
+
87
+ #### Never let an LLM speak for you
88
+
89
+ * All comments, issues, and pull request descriptions should be written in your own voice
90
+ * We value clear, human communication over perfect grammar or spelling
91
+ * Avoid copy-pasting AI-generated summaries that don't reflect your own understanding
92
+
93
+ #### Never let an LLM think for you
94
+
95
+ * Feel free to use AI tools to generate code or explore ideas
96
+ * Only submit contributions you fully understand and can explain
97
+ * Contributions should reflect your own reasoning and problem-solving
98
+
99
+ Our aim is ensuring quality and maintaining the joy of collaborating and communicating with real people. If you have ideas for improving our policy on AI in the Nuxt community, we'd love to hear them! ❤️
100
+
83
101
  ### Create a Module
84
102
 
85
103
  If you've built something with Nuxt that's cool, why not [extract it into a module](/docs/guide/going-further/modules), so it can be shared with others? We have [many excellent modules already](/modules), but there's always room for more.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/docs",
3
- "version": "4.0.1",
3
+ "version": "4.0.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/nuxt.git",