@nuxt/docs 3.20.0 → 3.20.2

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 (208) hide show
  1. package/1.getting-started/01.introduction.md +1 -1
  2. package/1.getting-started/02.installation.md +2 -2
  3. package/1.getting-started/03.configuration.md +3 -3
  4. package/1.getting-started/04.views.md +5 -5
  5. package/1.getting-started/05.assets.md +7 -7
  6. package/1.getting-started/06.styling.md +3 -3
  7. package/1.getting-started/07.routing.md +8 -4
  8. package/1.getting-started/08.seo-meta.md +2 -2
  9. package/1.getting-started/09.transitions.md +6 -6
  10. package/1.getting-started/10.data-fetching.md +12 -12
  11. package/1.getting-started/11.state-management.md +2 -2
  12. package/1.getting-started/12.error-handling.md +3 -3
  13. package/1.getting-started/14.layers.md +31 -12
  14. package/1.getting-started/16.deployment.md +1 -1
  15. package/1.getting-started/17.testing.md +1 -1
  16. package/{2.guide/1.directory-structure → 2.directory-structure}/0.nuxt.md +1 -1
  17. package/{2.guide/1.directory-structure → 2.directory-structure}/0.output.md +1 -1
  18. package/{2.guide/1.directory-structure → 2.directory-structure}/1.assets.md +2 -2
  19. package/{2.guide/1.directory-structure → 2.directory-structure}/1.components.md +1 -1
  20. package/{2.guide/1.directory-structure → 2.directory-structure}/1.composables.md +2 -2
  21. package/{2.guide/1.directory-structure → 2.directory-structure}/1.content.md +2 -2
  22. package/{2.guide/1.directory-structure → 2.directory-structure}/1.layouts.md +2 -2
  23. package/{2.guide/1.directory-structure → 2.directory-structure}/1.middleware.md +1 -1
  24. package/{2.guide/1.directory-structure → 2.directory-structure}/1.modules.md +2 -2
  25. package/{2.guide/1.directory-structure → 2.directory-structure}/1.node_modules.md +2 -2
  26. package/{2.guide/1.directory-structure → 2.directory-structure}/1.pages.md +6 -6
  27. package/{2.guide/1.directory-structure → 2.directory-structure}/1.plugins.md +2 -2
  28. package/{2.guide/1.directory-structure → 2.directory-structure}/1.server.md +1 -1
  29. package/{2.guide/1.directory-structure → 2.directory-structure}/1.shared.md +2 -2
  30. package/{2.guide/1.directory-structure → 2.directory-structure}/1.utils.md +3 -3
  31. package/{2.guide/1.directory-structure → 2.directory-structure}/2.env.md +1 -1
  32. package/{2.guide/1.directory-structure → 2.directory-structure}/2.nuxtignore.md +1 -1
  33. package/{2.guide/1.directory-structure → 2.directory-structure}/2.nuxtrc.md +1 -1
  34. package/{2.guide/1.directory-structure → 2.directory-structure}/3.app.md +2 -2
  35. package/{2.guide/1.directory-structure → 2.directory-structure}/3.error.md +1 -3
  36. package/{2.guide/1.directory-structure → 2.directory-structure}/3.nuxt-config.md +1 -1
  37. package/{2.guide/1.directory-structure → 2.directory-structure}/3.tsconfig.md +23 -0
  38. package/2.directory-structure/index.md +61 -0
  39. package/{2.guide → 3.guide}/0.index.md +6 -9
  40. package/{2.guide/2.concepts → 3.guide/1.concepts}/1.auto-imports.md +4 -4
  41. package/{2.guide/2.concepts → 3.guide/1.concepts}/10.nuxt-lifecycle.md +3 -3
  42. package/{2.guide/2.concepts → 3.guide/1.concepts}/2.vuejs-development.md +3 -3
  43. package/{2.guide/2.concepts → 3.guide/1.concepts}/3.rendering.md +1 -1
  44. package/{2.guide/2.concepts → 3.guide/1.concepts}/4.server-engine.md +2 -2
  45. package/{2.guide/2.concepts → 3.guide/1.concepts}/5.modules.md +1 -1
  46. package/{2.guide/2.concepts → 3.guide/1.concepts}/8.typescript.md +2 -2
  47. package/{2.guide/2.concepts → 3.guide/1.concepts}/9.code-style.md +1 -1
  48. package/{2.guide/4.recipes → 3.guide/3.recipes}/1.custom-routing.md +1 -1
  49. package/{2.guide/4.recipes → 3.guide/3.recipes}/2.vite-plugin.md +3 -3
  50. package/{2.guide/4.recipes → 3.guide/3.recipes}/3.custom-usefetch.md +1 -1
  51. package/{2.guide/3.going-further → 3.guide/4.going-further}/1.experimental-features.md +6 -6
  52. package/{2.guide/3.going-further → 3.guide/4.going-further}/1.internals.md +2 -2
  53. package/{2.guide/3.going-further → 3.guide/4.going-further}/10.runtime-config.md +1 -1
  54. package/{2.guide/3.going-further → 3.guide/4.going-further}/2.hooks.md +2 -2
  55. package/{2.guide/3.going-further → 3.guide/4.going-further}/3.modules.md +3 -3
  56. package/{2.guide/3.going-further → 3.guide/4.going-further}/6.nuxt-app.md +1 -1
  57. package/{2.guide/3.going-further → 3.guide/4.going-further}/7.layers.md +41 -24
  58. package/{3.api → 4.api}/1.components/12.nuxt-route-announcer.md +1 -1
  59. package/{3.api → 4.api}/1.components/2.nuxt-page.md +1 -1
  60. package/{3.api → 4.api}/1.components/3.nuxt-layout.md +2 -2
  61. package/{3.api → 4.api}/1.components/5.nuxt-loading-indicator.md +1 -1
  62. package/{3.api → 4.api}/2.composables/use-async-data.md +76 -13
  63. package/{3.api → 4.api}/2.composables/use-cookie.md +1 -1
  64. package/{3.api → 4.api}/2.composables/use-fetch.md +1 -1
  65. package/{3.api → 4.api}/2.composables/use-head-safe.md +37 -20
  66. package/4.api/2.composables/use-head.md +169 -0
  67. package/{3.api → 4.api}/2.composables/use-hydration.md +24 -18
  68. package/4.api/2.composables/use-lazy-async-data.md +96 -0
  69. package/4.api/2.composables/use-lazy-fetch.md +111 -0
  70. package/{3.api → 4.api}/2.composables/use-nuxt-app.md +5 -5
  71. package/{3.api → 4.api}/2.composables/use-nuxt-data.md +1 -1
  72. package/{3.api → 4.api}/2.composables/use-request-fetch.md +1 -1
  73. package/{3.api → 4.api}/2.composables/use-response-header.md +1 -1
  74. package/{3.api → 4.api}/2.composables/use-route.md +1 -1
  75. package/{3.api → 4.api}/2.composables/use-router.md +1 -1
  76. package/{3.api → 4.api}/2.composables/use-runtime-hook.md +1 -1
  77. package/{3.api → 4.api}/3.utils/$fetch.md +1 -1
  78. package/{3.api → 4.api}/3.utils/abort-navigation.md +1 -1
  79. package/{3.api → 4.api}/3.utils/add-route-middleware.md +1 -1
  80. package/{3.api → 4.api}/3.utils/define-nuxt-plugin.md +1 -1
  81. package/{3.api → 4.api}/3.utils/define-nuxt-route-middleware.md +1 -1
  82. package/{3.api → 4.api}/3.utils/define-page-meta.md +5 -5
  83. package/{3.api → 4.api}/3.utils/navigate-to.md +1 -1
  84. package/{3.api → 4.api}/3.utils/refresh-cookie.md +2 -2
  85. package/{3.api → 4.api}/3.utils/update-app-config.md +1 -1
  86. package/{3.api → 4.api}/4.commands/module.md +2 -2
  87. package/{3.api → 4.api}/4.commands/prepare.md +1 -1
  88. package/{3.api → 4.api}/4.commands/preview.md +1 -1
  89. package/{3.api → 4.api}/4.commands/typecheck.md +1 -1
  90. package/{3.api → 4.api}/5.kit/1.modules.md +1 -1
  91. package/{3.api → 4.api}/5.kit/2.programmatic.md +2 -2
  92. package/{3.api → 4.api}/5.kit/5.components.md +1 -1
  93. package/{3.api → 4.api}/6.advanced/1.hooks.md +1 -1
  94. package/5.community/3.reporting-bugs.md +1 -1
  95. package/5.community/6.roadmap.md +6 -6
  96. package/5.community/7.changelog.md +10 -0
  97. package/6.bridge/1.overview.md +1 -1
  98. package/6.bridge/4.plugins-and-middleware.md +2 -2
  99. package/7.migration/2.configuration.md +1 -1
  100. package/7.migration/3.auto-imports.md +1 -1
  101. package/7.migration/6.pages-and-layouts.md +4 -4
  102. package/package.json +1 -1
  103. package/3.api/2.composables/use-head.md +0 -69
  104. package/3.api/2.composables/use-lazy-async-data.md +0 -47
  105. package/3.api/2.composables/use-lazy-fetch.md +0 -55
  106. /package/{2.guide/1.directory-structure → 2.directory-structure}/.navigation.yml +0 -0
  107. /package/{2.guide/1.directory-structure → 2.directory-structure}/1.public.md +0 -0
  108. /package/{2.guide/1.directory-structure → 2.directory-structure}/2.gitignore.md +0 -0
  109. /package/{2.guide/1.directory-structure → 2.directory-structure}/3.app-config.md +0 -0
  110. /package/{2.guide/1.directory-structure → 2.directory-structure}/3.package.md +0 -0
  111. /package/{2.guide → 3.guide}/.navigation.yml +0 -0
  112. /package/{2.guide/2.concepts → 3.guide/1.concepts}/.navigation.yml +0 -0
  113. /package/{2.guide/2.concepts → 3.guide/1.concepts}/7.esm.md +0 -0
  114. /package/{2.guide/5.best-practices → 3.guide/2.best-practices}/.navigation.yml +0 -0
  115. /package/{2.guide/5.best-practices → 3.guide/2.best-practices}/hydration.md +0 -0
  116. /package/{2.guide/5.best-practices → 3.guide/2.best-practices}/performance.md +0 -0
  117. /package/{2.guide/5.best-practices → 3.guide/2.best-practices}/plugins.md +0 -0
  118. /package/{2.guide/4.recipes → 3.guide/3.recipes}/.navigation.yml +0 -0
  119. /package/{2.guide/4.recipes → 3.guide/3.recipes}/4.sessions-and-authentication.md +0 -0
  120. /package/{2.guide/3.going-further → 3.guide/4.going-further}/.navigation.yml +0 -0
  121. /package/{2.guide/3.going-further → 3.guide/4.going-further}/1.events.md +0 -0
  122. /package/{2.guide/3.going-further → 3.guide/4.going-further}/1.features.md +0 -0
  123. /package/{2.guide/3.going-further → 3.guide/4.going-further}/11.nightly-release-channel.md +0 -0
  124. /package/{2.guide/3.going-further → 3.guide/4.going-further}/4.kit.md +0 -0
  125. /package/{2.guide/3.going-further → 3.guide/4.going-further}/9.debugging.md +0 -0
  126. /package/{2.guide/3.going-further → 3.guide/4.going-further}/index.md +0 -0
  127. /package/{3.api → 4.api}/.navigation.yml +0 -0
  128. /package/{3.api → 4.api}/1.components/.navigation.yml +0 -0
  129. /package/{3.api → 4.api}/1.components/1.client-only.md +0 -0
  130. /package/{3.api → 4.api}/1.components/1.dev-only.md +0 -0
  131. /package/{3.api → 4.api}/1.components/1.nuxt-client-fallback.md +0 -0
  132. /package/{3.api → 4.api}/1.components/10.nuxt-picture.md +0 -0
  133. /package/{3.api → 4.api}/1.components/11.teleports.md +0 -0
  134. /package/{3.api → 4.api}/1.components/13.nuxt-time.md +0 -0
  135. /package/{3.api → 4.api}/1.components/4.nuxt-link.md +0 -0
  136. /package/{3.api → 4.api}/1.components/6.nuxt-error-boundary.md +0 -0
  137. /package/{3.api → 4.api}/1.components/7.nuxt-welcome.md +0 -0
  138. /package/{3.api → 4.api}/1.components/8.nuxt-island.md +0 -0
  139. /package/{3.api → 4.api}/1.components/9.nuxt-img.md +0 -0
  140. /package/{3.api → 4.api}/2.composables/.navigation.yml +0 -0
  141. /package/{3.api → 4.api}/2.composables/on-prehydrate.md +0 -0
  142. /package/{3.api → 4.api}/2.composables/use-app-config.md +0 -0
  143. /package/{3.api → 4.api}/2.composables/use-error.md +0 -0
  144. /package/{3.api → 4.api}/2.composables/use-loading-indicator.md +0 -0
  145. /package/{3.api → 4.api}/2.composables/use-preview-mode.md +0 -0
  146. /package/{3.api → 4.api}/2.composables/use-request-event.md +0 -0
  147. /package/{3.api → 4.api}/2.composables/use-request-header.md +0 -0
  148. /package/{3.api → 4.api}/2.composables/use-request-headers.md +0 -0
  149. /package/{3.api → 4.api}/2.composables/use-request-url.md +0 -0
  150. /package/{3.api → 4.api}/2.composables/use-route-announcer.md +0 -0
  151. /package/{3.api → 4.api}/2.composables/use-runtime-config.md +0 -0
  152. /package/{3.api → 4.api}/2.composables/use-seo-meta.md +0 -0
  153. /package/{3.api → 4.api}/2.composables/use-server-seo-meta.md +0 -0
  154. /package/{3.api → 4.api}/2.composables/use-state.md +0 -0
  155. /package/{3.api → 4.api}/3.utils/.navigation.yml +0 -0
  156. /package/{3.api → 4.api}/3.utils/call-once.md +0 -0
  157. /package/{3.api → 4.api}/3.utils/clear-error.md +0 -0
  158. /package/{3.api → 4.api}/3.utils/clear-nuxt-data.md +0 -0
  159. /package/{3.api → 4.api}/3.utils/clear-nuxt-state.md +0 -0
  160. /package/{3.api → 4.api}/3.utils/create-error.md +0 -0
  161. /package/{3.api → 4.api}/3.utils/define-lazy-hydration-component.md +0 -0
  162. /package/{3.api → 4.api}/3.utils/define-nuxt-component.md +0 -0
  163. /package/{3.api → 4.api}/3.utils/define-route-rules.md +0 -0
  164. /package/{3.api → 4.api}/3.utils/on-before-route-leave.md +0 -0
  165. /package/{3.api → 4.api}/3.utils/on-before-route-update.md +0 -0
  166. /package/{3.api → 4.api}/3.utils/on-nuxt-ready.md +0 -0
  167. /package/{3.api → 4.api}/3.utils/prefetch-components.md +0 -0
  168. /package/{3.api → 4.api}/3.utils/preload-components.md +0 -0
  169. /package/{3.api → 4.api}/3.utils/preload-route-components.md +0 -0
  170. /package/{3.api → 4.api}/3.utils/prerender-routes.md +0 -0
  171. /package/{3.api → 4.api}/3.utils/refresh-nuxt-data.md +0 -0
  172. /package/{3.api → 4.api}/3.utils/reload-nuxt-app.md +0 -0
  173. /package/{3.api → 4.api}/3.utils/set-page-layout.md +0 -0
  174. /package/{3.api → 4.api}/3.utils/set-response-status.md +0 -0
  175. /package/{3.api → 4.api}/3.utils/show-error.md +0 -0
  176. /package/{3.api → 4.api}/4.commands/.navigation.yml +0 -0
  177. /package/{3.api → 4.api}/4.commands/add.md +0 -0
  178. /package/{3.api → 4.api}/4.commands/analyze.md +0 -0
  179. /package/{3.api → 4.api}/4.commands/build-module.md +0 -0
  180. /package/{3.api → 4.api}/4.commands/build.md +0 -0
  181. /package/{3.api → 4.api}/4.commands/cleanup.md +0 -0
  182. /package/{3.api → 4.api}/4.commands/dev.md +0 -0
  183. /package/{3.api → 4.api}/4.commands/devtools.md +0 -0
  184. /package/{3.api → 4.api}/4.commands/generate.md +0 -0
  185. /package/{3.api → 4.api}/4.commands/info.md +0 -0
  186. /package/{3.api → 4.api}/4.commands/init.md +0 -0
  187. /package/{3.api → 4.api}/4.commands/test.md +0 -0
  188. /package/{3.api → 4.api}/4.commands/upgrade.md +0 -0
  189. /package/{3.api → 4.api}/5.kit/.navigation.yml +0 -0
  190. /package/{3.api → 4.api}/5.kit/10.runtime-config.md +0 -0
  191. /package/{3.api → 4.api}/5.kit/10.templates.md +0 -0
  192. /package/{3.api → 4.api}/5.kit/11.nitro.md +0 -0
  193. /package/{3.api → 4.api}/5.kit/12.resolving.md +0 -0
  194. /package/{3.api → 4.api}/5.kit/13.logging.md +0 -0
  195. /package/{3.api → 4.api}/5.kit/14.builder.md +0 -0
  196. /package/{3.api → 4.api}/5.kit/15.examples.md +0 -0
  197. /package/{3.api → 4.api}/5.kit/16.layers.md +0 -0
  198. /package/{3.api → 4.api}/5.kit/3.compatibility.md +0 -0
  199. /package/{3.api → 4.api}/5.kit/4.autoimports.md +0 -0
  200. /package/{3.api → 4.api}/5.kit/6.context.md +0 -0
  201. /package/{3.api → 4.api}/5.kit/7.pages.md +0 -0
  202. /package/{3.api → 4.api}/5.kit/8.layout.md +0 -0
  203. /package/{3.api → 4.api}/5.kit/9.head.md +0 -0
  204. /package/{3.api → 4.api}/5.kit/9.plugins.md +0 -0
  205. /package/{3.api → 4.api}/6.advanced/.navigation.yml +0 -0
  206. /package/{3.api → 4.api}/6.advanced/2.import-meta.md +0 -0
  207. /package/{3.api → 4.api}/6.nuxt-config.md +0 -0
  208. /package/{3.api → 4.api}/index.md +0 -0
@@ -117,7 +117,7 @@ Nuxt Modules come with a variety of powerful APIs and patterns allowing them to
117
117
  We can consider two kinds of Nuxt Modules:
118
118
 
119
119
  - published modules are distributed on npm - you can see a list of some community modules on [the Nuxt website](/modules).
120
- - "local" modules, they exist within a Nuxt project itself, either [inlined in Nuxt config](/docs/3.x/api/nuxt-config#modules) or as part of [the `modules` directory](/docs/3.x/guide/directory-structure/modules).
120
+ - "local" modules, they exist within a Nuxt project itself, either [inlined in Nuxt config](/docs/3.x/api/nuxt-config#modules) or as part of [the `modules` directory](/docs/3.x/directory-structure/modules).
121
121
 
122
122
  In either case, their anatomy is similar.
123
123
 
@@ -224,7 +224,7 @@ Modules, like everything in a Nuxt configuration, aren't included in your applic
224
224
  Inside the runtime directory, you can provide any kind of assets related to the Nuxt App:
225
225
  - Vue components
226
226
  - Composables
227
- - [Nuxt plugins](/docs/3.x/guide/directory-structure/plugins)
227
+ - [Nuxt plugins](/docs/3.x/directory-structure/plugins)
228
228
 
229
229
  To the [server engine](/docs/3.x/guide/concepts/server-engine), Nitro:
230
230
  - API routes
@@ -774,7 +774,7 @@ An example of such a workflow is available on [the module starter](https://githu
774
774
 
775
775
  Having a playground Nuxt application to test your module when developing it is really useful. [The module starter integrates one for that purpose](#how-to-develop).
776
776
 
777
- You can test your module with other Nuxt applications (applications that are not part of your module repository) locally. To do so, you can use [`npm pack`](https://docs.npmjs.com/cli/commands/npm-pack) command, or your package manager equivalent, to create a tarball from your module. Then in your test project, you can add your module to `package.json` packages as: `"my-module": "file:/path/to/tarball.tgz"`.
777
+ You can test your module with other Nuxt applications (applications that are not part of your module repository) locally. To do so, you can use [`npm pack`](https://docs.npmjs.com/cli/commands/npm-pack/) command, or your package manager equivalent, to create a tarball from your module. Then in your test project, you can add your module to `package.json` packages as: `"my-module": "file:/path/to/tarball.tgz"`.
778
778
 
779
779
  After that, you should be able to reference `my-module` like in any regular project.
780
780
 
@@ -23,7 +23,7 @@ Jump over the `NuxtApp` interface documentation.
23
23
 
24
24
  Many composables and utilities, both built-in and user-made, may require access to the Nuxt instance. This doesn't exist everywhere on your application, because a fresh instance is created on every request.
25
25
 
26
- Currently, the Nuxt context is only accessible in [plugins](/docs/3.x/guide/directory-structure/plugins), [Nuxt hooks](/docs/3.x/guide/going-further/hooks), [Nuxt middleware](/docs/3.x/guide/directory-structure/middleware) (if wrapped in `defineNuxtRouteMiddleware`), and [setup functions](https://vuejs.org/api/composition-api-setup.html) (in pages and components).
26
+ Currently, the Nuxt context is only accessible in [plugins](/docs/3.x/directory-structure/plugins), [Nuxt hooks](/docs/3.x/guide/going-further/hooks), [Nuxt middleware](/docs/3.x/directory-structure/middleware) (if wrapped in `defineNuxtRouteMiddleware`), and [setup functions](https://vuejs.org/api/composition-api-setup.html) (in pages and components).
27
27
 
28
28
  If a composable is called without access to the context, you may get an error stating that 'A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function.' In that case, you can also explicitly call functions within this context by using [`nuxtApp.runWithContext`](/docs/3.x/api/composables/use-nuxt-app#runwithcontext).
29
29
 
@@ -7,7 +7,7 @@ Nuxt layers are a powerful feature that you can use to share and reuse partial N
7
7
 
8
8
  :read-more{to="/docs/getting-started/layers"}
9
9
 
10
- A minimal Nuxt layer directory should contain a [`nuxt.config.ts`](/docs/3.x/guide/directory-structure/nuxt-config) file to indicate it is a layer.
10
+ A minimal Nuxt layer directory should contain a [`nuxt.config.ts`](/docs/3.x/directory-structure/nuxt-config) file to indicate it is a layer.
11
11
 
12
12
  ```ts [base/nuxt.config.ts]
13
13
  export default defineNuxtConfig({})
@@ -15,16 +15,16 @@ export default defineNuxtConfig({})
15
15
 
16
16
  Additionally, certain other files in the layer directory will be auto-scanned and used by Nuxt for the project extending this layer.
17
17
 
18
- - [`components/*`](/docs/3.x/guide/directory-structure/components) - Extend the default components
19
- - [`composables/*`](/docs/3.x/guide/directory-structure/composables) - Extend the default composables
20
- - [`layouts/*`](/docs/3.x/guide/directory-structure/layouts) - Extend the default layouts
21
- - [`middleware/*`](/docs/3.x/guide/directory-structure/middleware) - Extend the default middleware
22
- - [`pages/*`](/docs/3.x/guide/directory-structure/pages) - Extend the default pages
23
- - [`plugins/*`](/docs/3.x/guide/directory-structure/plugins) - Extend the default plugins
24
- - [`server/*`](/docs/3.x/guide/directory-structure/server) - Extend the default server endpoints & middleware
25
- - [`utils/*`](/docs/3.x/guide/directory-structure/utils) - Extend the default utils
26
- - [`nuxt.config.ts`](/docs/3.x/guide/directory-structure/nuxt-config)- Extend the default nuxt config
27
- - [`app.config.ts`](/docs/3.x/guide/directory-structure/app-config) - Extend the default app config
18
+ - [`components/*`](/docs/3.x/directory-structure/components) - Extend the default components
19
+ - [`composables/*`](/docs/3.x/directory-structure/composables) - Extend the default composables
20
+ - [`layouts/*`](/docs/3.x/directory-structure/layouts) - Extend the default layouts
21
+ - [`middleware/*`](/docs/3.x/directory-structure/middleware) - Extend the default middleware
22
+ - [`pages/*`](/docs/3.x/directory-structure/pages) - Extend the default pages
23
+ - [`plugins/*`](/docs/3.x/directory-structure/plugins) - Extend the default plugins
24
+ - [`server/*`](/docs/3.x/directory-structure/server) - Extend the default server endpoints & middleware
25
+ - [`utils/*`](/docs/3.x/directory-structure/utils) - Extend the default utils
26
+ - [`nuxt.config.ts`](/docs/3.x/directory-structure/nuxt-config)- Extend the default nuxt config
27
+ - [`app.config.ts`](/docs/3.x/directory-structure/app-config) - Extend the default app config
28
28
 
29
29
  ## Basic Example
30
30
 
@@ -68,29 +68,46 @@ Additionally, certain other files in the layer directory will be auto-scanned an
68
68
 
69
69
  ## Layer Priority
70
70
 
71
- When extending from multiple layers, it's important to understand the priority order:
71
+ When extending from multiple layers, it's important to understand the override order. Layers with **higher priority** override layers with lower priority when they define the same files or components.
72
72
 
73
- 1. **Layers in `extends`** - earlier entries have higher priority (first overrides second)
74
- 2. **Auto-scanned local layers** from `~~/layers` directory in alphabetical order (Z overrides A)
75
- 3. **Your project** has the highest priority in the stack - it will always override other layers
73
+ The priority order from highest to lowest is:
76
74
 
77
- For example:
75
+ 1. **Your project files** - always have the highest priority
76
+ 2. **Auto-scanned layers** from `~~/layers` directory - sorted alphabetically (Z has higher priority than A)
77
+ 3. **Layers in `extends`** config - first entry has higher priority than second
78
+
79
+ ### When to Use Each
80
+
81
+ - **`extends`** - Use for external dependencies (npm packages, remote repositories) or layers outside your project directory
82
+ - **`~~/layers` directory** - Use for local layers that are part of your project
83
+
84
+ ::tip
85
+ If you need to control the order of auto-scanned layers, you can prefix them with numbers: `~/layers/1.z-layer`, `~/layers/2.a-layer`. This way `2.a-layer` will have higher priority than `1.z-layer`.
86
+ ::
87
+
88
+ ### Example
78
89
 
79
90
  ```ts [nuxt.config.ts]
80
91
  export default defineNuxtConfig({
81
92
  extends: [
82
- // Highest priority (among extends)
83
- './layers/base',
84
- // Medium priority
85
- './layers/theme',
86
- // Lower priority
87
- './layers/custom',
93
+ // Local layer outside the project
94
+ '../base',
95
+ // NPM package
96
+ '@my-themes/awesome',
97
+ // Remote repository
98
+ 'github:my-themes/awesome#v1',
88
99
  ],
89
- // Your project has the highest priority
90
100
  })
91
101
  ```
92
102
 
93
- If you also have auto-scanned layers like `~~/layers/a` and `~~/layers/z`, the complete override order would be: `base` > `theme` > `custom` > `z` > `a` > your project.
103
+ If you also have `~~/layers/custom`, the priority order is:
104
+ - Your project files (highest)
105
+ - `~~/layers/custom`
106
+ - `../base`
107
+ - `@my-themes/awesome`
108
+ - `github:my-themes/awesome#v1` (lowest)
109
+
110
+ This means your project files will override any layer, and `~~/layers/custom` will override anything in `extends`.
94
111
 
95
112
  ## Starter Template
96
113
 
@@ -16,7 +16,7 @@ This component is available in Nuxt v3.12+.
16
16
 
17
17
  ## Usage
18
18
 
19
- Add `<NuxtRouteAnnouncer/>` in your [`app.vue`](/docs/3.x/guide/directory-structure/app) or [`layouts/`](/docs/3.x/guide/directory-structure/layouts) to enhance accessibility by informing assistive technologies about page title changes. This ensures that navigational changes are announced to users relying on screen readers.
19
+ Add `<NuxtRouteAnnouncer/>` in your [`app.vue`](/docs/3.x/directory-structure/app) or [`layouts/`](/docs/3.x/directory-structure/layouts) to enhance accessibility by informing assistive technologies about page title changes. This ensures that navigational changes are announced to users relying on screen readers.
20
20
 
21
21
  ```vue [app.vue]
22
22
  <template>
@@ -8,7 +8,7 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- `<NuxtPage>` is a built-in component that comes with Nuxt. It lets you display top-level or nested pages located in the [`pages/`](/docs/3.x/guide/directory-structure/pages) directory.
11
+ `<NuxtPage>` is a built-in component that comes with Nuxt. It lets you display top-level or nested pages located in the [`pages/`](/docs/3.x/directory-structure/pages) directory.
12
12
 
13
13
  ::note
14
14
  `<NuxtPage>` is a wrapper around [`<RouterView>`](https://router.vuejs.org/api/interfaces/RouterViewProps.html#interface-routerviewprops) from Vue Router. It should be used instead of `<RouterView>` because the former takes additional care of internal states. Otherwise, `useRoute()` may return incorrect paths.
@@ -22,7 +22,7 @@ You can use `<NuxtLayout />` component to activate the `default` layout on `app.
22
22
 
23
23
  ## Props
24
24
 
25
- - `name`: Specify a layout name to be rendered, can be a string, reactive reference or a computed property. It **must** match the name of the corresponding layout file in the [`layouts/`](/docs/3.x/guide/directory-structure/layouts) directory.
25
+ - `name`: Specify a layout name to be rendered, can be a string, reactive reference or a computed property. It **must** match the name of the corresponding layout file in the [`layouts/`](/docs/3.x/directory-structure/layouts) directory.
26
26
  - **type**: `string`
27
27
  - **default**: `default`
28
28
 
@@ -55,7 +55,7 @@ Please note the layout name is normalized to kebab-case, so if your layout file
55
55
  Read more about dynamic layouts.
56
56
  ::
57
57
 
58
- - `fallback`: If an invalid layout is passed to the `name` prop, no layout will be rendered. Specify a `fallback` layout to be rendered in this scenario. It **must** match the name of the corresponding layout file in the [`layouts/`](/docs/3.x/guide/directory-structure/layouts) directory.
58
+ - `fallback`: If an invalid layout is passed to the `name` prop, no layout will be rendered. Specify a `fallback` layout to be rendered in this scenario. It **must** match the name of the corresponding layout file in the [`layouts/`](/docs/3.x/directory-structure/layouts) directory.
59
59
  - **type**: `string`
60
60
  - **default**: `null`
61
61
 
@@ -10,7 +10,7 @@ links:
10
10
 
11
11
  ## Usage
12
12
 
13
- Add `<NuxtLoadingIndicator/>` in your [`app.vue`](/docs/3.x/guide/directory-structure/app) or [`layouts/`](/docs/3.x/guide/directory-structure/layouts).
13
+ Add `<NuxtLoadingIndicator/>` in your [`app.vue`](/docs/3.x/directory-structure/app) or [`layouts/`](/docs/3.x/directory-structure/layouts).
14
14
 
15
15
  ```vue [app.vue]
16
16
  <template>
@@ -18,9 +18,9 @@ Within your pages, components, and plugins you can use useAsyncData to get acces
18
18
 
19
19
  ```vue [pages/index.vue]
20
20
  <script setup lang="ts">
21
- const { data, status, error, refresh, clear } = await useAsyncData(
21
+ const { data, status, pending, error, refresh, clear } = await useAsyncData(
22
22
  'mountains',
23
- () => $fetch('https://api.nuxtjs.dev/mountains'),
23
+ (_nuxtApp, { signal }) => $fetch('https://api.nuxtjs.dev/mountains', { signal }),
24
24
  )
25
25
  </script>
26
26
  ```
@@ -30,7 +30,7 @@ If you're using a custom useAsyncData wrapper, do not await it in the composable
30
30
  ::
31
31
 
32
32
  ::note
33
- `data`, `status` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions.
33
+ `data`, `status`, `pending` and `error` are Vue refs and they should be accessed with `.value` when used within the `<script setup>`, while `refresh`/`execute` and `clear` are plain functions.
34
34
  ::
35
35
 
36
36
  ### Watch Params
@@ -42,10 +42,11 @@ The built-in `watch` option allows automatically rerunning the fetcher function
42
42
  const page = ref(1)
43
43
  const { data: posts } = await useAsyncData(
44
44
  'posts',
45
- () => $fetch('https://fakeApi.com/posts', {
45
+ (_nuxtApp, { signal }) => $fetch('https://fakeApi.com/posts', {
46
46
  params: {
47
47
  page: page.value,
48
48
  },
49
+ signal,
49
50
  }), {
50
51
  watch: [page],
51
52
  },
@@ -70,6 +71,64 @@ const { data: user } = useAsyncData(
70
71
  </script>
71
72
  ```
72
73
 
74
+ ### Make your `handler` abortable
75
+
76
+ You can make your `handler` function abortable by using the `signal` provided in the second argument. This is useful for cancelling requests when they are no longer needed, such as when a user navigates away from a page. `$fetch` natively supports abort signals.
77
+
78
+ ```ts
79
+ const { data, error } = await useAsyncData(
80
+ 'users',
81
+ (_nuxtApp, { signal }) => $fetch('/api/users', { signal }),
82
+ )
83
+
84
+ refresh() // will actually cancel the $fetch request (if dedupe: cancel)
85
+ refresh() // will actually cancel the $fetch request (if dedupe: cancel)
86
+ refresh()
87
+
88
+ clear() // will cancel the latest pending handler
89
+ ```
90
+
91
+ You can also pass an `AbortSignal` to the `refresh`/`execute` function to cancel individual requests manually.
92
+
93
+ ```ts
94
+ const { refresh } = await useAsyncData(
95
+ 'users',
96
+ (_nuxtApp, { signal }) => $fetch('/api/users', { signal }),
97
+ )
98
+ let abortController: AbortController | undefined
99
+
100
+ function handleUserAction () {
101
+ abortController = new AbortController()
102
+ refresh({ signal: abortController.signal })
103
+ }
104
+
105
+ function handleCancel () {
106
+ abortController?.abort() // aborts the ongoing refresh request
107
+ }
108
+ ```
109
+
110
+ If your `handler` function does not support abort signals, you can implement your own abort logic using the `signal` provided.
111
+
112
+ ```ts
113
+ const { data, error } = await useAsyncData(
114
+ 'users',
115
+ (_nuxtApp, { signal }) => {
116
+ return new Promise((resolve, reject) => {
117
+ signal?.addEventListener('abort', () => {
118
+ reject(new Error('Request aborted'))
119
+ })
120
+ return Promise.resolve(callback.call(this, yourHandler)).then(resolve, reject)
121
+ })
122
+ },
123
+ )
124
+ ```
125
+
126
+ The handler signal will be aborted when:
127
+
128
+ - A new request is made with `dedupe: 'cancel'`
129
+ - The `clear` function is called
130
+ - The `options.timeout` duration is exceeded
131
+
73
132
  ::warning
74
133
  [`useAsyncData`](/docs/3.x/api/composables/use-async-data) is a reserved function name transformed by the compiler, so you should not name your own function [`useAsyncData`](/docs/3.x/api/composables/use-async-data).
75
134
  ::
@@ -116,7 +175,7 @@ You can use `useLazyAsyncData` to have the same behavior as `lazy: true` with `u
116
175
 
117
176
  ### Shared State and Option Consistency
118
177
 
119
- When using the same key for multiple `useAsyncData` calls, they will share the same `data`, `error` and `status` refs. This ensures consistency across components but requires option consistency.
178
+ When using the same key for multiple `useAsyncData` calls, they will share the same `data`, `error`, `status` and `pending` refs. This ensures consistency across components but requires option consistency.
120
179
 
121
180
  The following options **must be consistent** across all calls with the same key:
122
181
  - `handler` function
@@ -135,12 +194,12 @@ The following options **can differ** without triggering warnings:
135
194
 
136
195
  ```ts
137
196
  // ❌ This will trigger a development warning
138
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
139
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true })
197
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: false })
198
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { deep: true })
140
199
 
141
200
  // ✅ This is allowed
142
- const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: true })
143
- const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { immediate: false })
201
+ const { data: users1 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: true })
202
+ const { data: users2 } = useAsyncData('users', (_nuxtApp, { signal }) => $fetch('/api/users', { signal }), { immediate: false })
144
203
  ```
145
204
 
146
205
  ::tip
@@ -159,6 +218,7 @@ Keyed state created using `useAsyncData` can be retrieved across your Nuxt appli
159
218
  - `pending`: the request is in progress
160
219
  - `success`: the request has completed successfully
161
220
  - `error`: the request has failed
221
+ - `pending`: a `Ref<boolean>` that is `true` while the request is in progress.
162
222
  - `clear`: a function that can be used to set `data` to `undefined` (or the value of `options.default()` if provided), set `error` to `null`, set `status` to `idle`, and mark any currently pending requests as cancelled.
163
223
 
164
224
  By default, Nuxt waits until a `refresh` is finished before it can be executed again.
@@ -170,14 +230,16 @@ If you have not fetched data on the server (for example, with `server: false`),
170
230
  ## Type
171
231
 
172
232
  ```ts [Signature]
233
+ export type AsyncDataHandler<ResT> = (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<ResT>
234
+
173
235
  export function useAsyncData<DataT, DataE> (
174
- handler: (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<DataT>,
175
- options?: AsyncDataOptions<DataT>
236
+ handler: AsyncDataHandler<DataT>,
237
+ options?: AsyncDataOptions<DataT>,
176
238
  ): AsyncData<DataT, DataE>
177
239
  export function useAsyncData<DataT, DataE> (
178
240
  key: MaybeRefOrGetter<string>,
179
- handler: (nuxtApp: NuxtApp, options: { signal: AbortSignal }) => Promise<DataT>,
180
- options?: AsyncDataOptions<DataT>
241
+ handler: AsyncDataHandler<DataT>,
242
+ options?: AsyncDataOptions<DataT>,
181
243
  ): Promise<AsyncData<DataT, DataE>>
182
244
 
183
245
  type AsyncDataOptions<DataT> = {
@@ -206,6 +268,7 @@ type AsyncData<DataT, ErrorT> = {
206
268
  clear: () => void
207
269
  error: Ref<ErrorT | null>
208
270
  status: Ref<AsyncDataRequestStatus>
271
+ pending: Ref<boolean>
209
272
  }
210
273
 
211
274
  interface AsyncDataExecuteOptions {
@@ -42,7 +42,7 @@ export interface CookieRef<T> extends Ref<T> {}
42
42
 
43
43
  export function useCookie<T = string | null | undefined> (
44
44
  name: string,
45
- options?: CookieOptions<T>
45
+ options?: CookieOptions<T>,
46
46
  ): CookieRef<T>
47
47
  ```
48
48
 
@@ -128,7 +128,7 @@ searchQuery.value = 'new search'
128
128
  ```ts [Signature]
129
129
  export function useFetch<DataT, ErrorT> (
130
130
  url: string | Request | Ref<string | Request> | (() => string | Request),
131
- options?: UseFetchOptions<DataT>
131
+ options?: UseFetchOptions<DataT>,
132
132
  ): Promise<AsyncData<DataT, ErrorT>>
133
133
 
134
134
  type UseFetchOptions<DataT> = {
@@ -8,28 +8,12 @@ links:
8
8
  size: xs
9
9
  ---
10
10
 
11
- The `useHeadSafe` composable is a wrapper around the [`useHead`](/docs/3.x/api/composables/use-head) composable that restricts the input to only allow safe values.
12
-
13
11
  ## Usage
14
12
 
15
- You can pass all the same values as [`useHead`](/docs/3.x/api/composables/use-head)
16
-
17
- ```ts
18
- useHeadSafe({
19
- script: [
20
- { id: 'xss-script', innerHTML: 'alert("xss")' },
21
- ],
22
- meta: [
23
- { 'http-equiv': 'refresh', 'content': '0;javascript:alert(1)' },
24
- ],
25
- })
26
- // Will safely generate
27
- // <script id="xss-script"></script>
28
- // <meta content="0;javascript:alert(1)">
29
- ```
13
+ The `useHeadSafe` composable is a wrapper around the [`useHead`](/docs/3.x/api/composables/use-head) composable that restricts the input to only allow safe values. This is the recommended way to manage head data when working with user input, as it prevents XSS attacks by sanitizing potentially dangerous attributes.
30
14
 
31
- ::read-more{to="https://unhead.unjs.io/docs/typescript/head/api/composables/use-head-safe" target="_blank"}
32
- Read more on the `Unhead` documentation.
15
+ ::warning
16
+ When using `useHeadSafe`, potentially dangerous attributes like `innerHTML` in scripts or `http-equiv` in meta tags are automatically stripped out to prevent XSS attacks. Use this composable whenever you're working with user-generated content.
33
17
  ::
34
18
 
35
19
  ## Type
@@ -38,7 +22,9 @@ Read more on the `Unhead` documentation.
38
22
  export function useHeadSafe (input: MaybeComputedRef<HeadSafe>): void
39
23
  ```
40
24
 
41
- The list of allowed values is:
25
+ ### Allowed Attributes
26
+
27
+ The following attributes are whitelisted for each head element type:
42
28
 
43
29
  ```ts
44
30
  const WhitelistAttributes = {
@@ -53,3 +39,34 @@ const WhitelistAttributes = {
53
39
  ```
54
40
 
55
41
  See [@unhead/vue](https://github.com/unjs/unhead/blob/main/packages/vue/src/types/safeSchema.ts) for more detailed types.
42
+
43
+ ## Parameters
44
+
45
+ `input`: A `MaybeComputedRef<HeadSafe>` object containing head data. You can pass all the same values as [`useHead`](/docs/3.x/api/composables/use-head), but only safe attributes will be rendered.
46
+
47
+ ## Return Values
48
+
49
+ This composable does not return any value.
50
+
51
+ ## Example
52
+
53
+ ```vue [app/pages/user-profile.vue]
54
+ <script setup lang="ts">
55
+ // User-generated content that might contain malicious code
56
+ const userBio = ref('<script>alert("xss")<' + '/script>')
57
+
58
+ useHeadSafe({
59
+ title: `User Profile`,
60
+ meta: [
61
+ {
62
+ name: 'description',
63
+ content: userBio.value, // Safely sanitized
64
+ },
65
+ ],
66
+ })
67
+ </script>
68
+ ```
69
+
70
+ ::read-more{to="https://unhead.unjs.io/docs/typescript/head/api/composables/use-head-safe" target="_blank"}
71
+ Read more on the `Unhead` documentation.
72
+ ::
@@ -0,0 +1,169 @@
1
+ ---
2
+ title: useHead
3
+ description: useHead customizes the head properties of individual pages of your Nuxt app.
4
+ links:
5
+ - label: Source
6
+ icon: i-simple-icons-github
7
+ to: https://github.com/unjs/unhead/blob/main/packages/vue/src/composables.ts
8
+ size: xs
9
+ ---
10
+
11
+ ## Usage
12
+
13
+ The `useHead` composable allows you to manage your head tags in a programmatic and reactive way, powered by [Unhead](https://unhead.unjs.io). It lets you customize the meta tags, links, scripts, and other elements in the `<head>` section of your HTML document.
14
+
15
+ ```vue [app/app.vue]
16
+ <script setup lang="ts">
17
+ useHead({
18
+ title: 'My App',
19
+ meta: [
20
+ { name: 'description', content: 'My amazing site.' },
21
+ ],
22
+ bodyAttrs: {
23
+ class: 'test',
24
+ },
25
+ script: [{ innerHTML: 'console.log(\'Hello world\')' }],
26
+ })
27
+ </script>
28
+ ```
29
+
30
+ ::warning
31
+ If the data comes from a user or other untrusted source, we recommend you check out [`useHeadSafe`](/docs/3.x/api/composables/use-head-safe).
32
+ ::
33
+
34
+ ::note
35
+ The properties of `useHead` can be dynamic, accepting `ref`, `computed` and `reactive` properties. The `meta` parameter can also accept a function returning an object to make the entire object reactive.
36
+ ::
37
+
38
+ ## Type
39
+
40
+ ```ts [Signature]
41
+ export function useHead (meta: MaybeComputedRef<MetaObject>): void
42
+
43
+ interface MetaObject {
44
+ title?: string
45
+ titleTemplate?: string | ((title?: string) => string)
46
+ base?: Base
47
+ link?: Link[]
48
+ meta?: Meta[]
49
+ style?: Style[]
50
+ script?: Script[]
51
+ noscript?: Noscript[]
52
+ htmlAttrs?: HtmlAttributes
53
+ bodyAttrs?: BodyAttributes
54
+ }
55
+ ```
56
+
57
+ See [@unhead/schema](https://github.com/unjs/unhead/blob/main/packages/vue/src/types/schema.ts) for more detailed types.
58
+
59
+ ## Parameters
60
+
61
+ `meta`: An object accepting head metadata properties to customize the page's `<head>` section. All properties support reactive values (`ref`, `computed`, `reactive`) or can be a function returning the metadata object.
62
+
63
+ | Property | Type | Description |
64
+ | --- | --- | --- |
65
+ | `title` | `string` | Sets the page title. |
66
+ | `titleTemplate` | `string \| ((title?: string) => string)` | Configures a dynamic template to customize the page title. Can be a string with `%s` placeholder or a function. |
67
+ | `base` | `Base` | Sets the `<base>` tag for the document. |
68
+ | `link` | `Link[]` | Array of link objects. Each element is mapped to a `<link>` tag, where object properties correspond to HTML attributes. |
69
+ | `meta` | `Meta[]` | Array of meta objects. Each element is mapped to a `<meta>` tag, where object properties correspond to HTML attributes. |
70
+ | `style` | `Style[]` | Array of style objects. Each element is mapped to a `<style>` tag, where object properties correspond to HTML attributes. |
71
+ | `script` | `Script[]` | Array of script objects. Each element is mapped to a `<script>` tag, where object properties correspond to HTML attributes. |
72
+ | `noscript` | `Noscript[]` | Array of noscript objects. Each element is mapped to a `<noscript>` tag, where object properties correspond to HTML attributes. |
73
+ | `htmlAttrs` | `HtmlAttributes` | Sets attributes of the `<html>` tag. Each object property is mapped to the corresponding attribute. |
74
+ | `bodyAttrs` | `BodyAttributes` | Sets attributes of the `<body>` tag. Each object property is mapped to the corresponding attribute. |
75
+
76
+ ## Return Values
77
+
78
+ This composable does not return any value. It registers the head metadata with Unhead, which manages the actual DOM updates.
79
+
80
+ ## Examples
81
+
82
+ ### Basic Meta Tags
83
+
84
+ ```vue [app/pages/about.vue]
85
+ <script setup lang="ts">
86
+ useHead({
87
+ title: 'About Us',
88
+ meta: [
89
+ { name: 'description', content: 'Learn more about our company' },
90
+ { property: 'og:title', content: 'About Us' },
91
+ { property: 'og:description', content: 'Learn more about our company' },
92
+ ],
93
+ })
94
+ </script>
95
+ ```
96
+
97
+ ### Reactive Meta Tags
98
+
99
+ ```vue [app/pages/profile.vue]
100
+ <script setup lang="ts">
101
+ const profile = ref({ name: 'John Doe' })
102
+
103
+ useHead({
104
+ title: computed(() => profile.value.name),
105
+ meta: [
106
+ {
107
+ name: 'description',
108
+ content: computed(() => `Profile page for ${profile.value.name}`),
109
+ },
110
+ ],
111
+ })
112
+ </script>
113
+ ```
114
+
115
+ ### Using a Function for Full Reactivity
116
+
117
+ ```vue [app/pages/dynamic.vue]
118
+ <script setup lang="ts">
119
+ const count = ref(0)
120
+
121
+ useHead(() => ({
122
+ title: `Count: ${count.value}`,
123
+ meta: [
124
+ { name: 'description', content: `Current count is ${count.value}` },
125
+ ],
126
+ }))
127
+ </script>
128
+ ```
129
+
130
+ ### Adding External Scripts and Styles
131
+
132
+ ```vue [app/pages/external.vue]
133
+ <script setup lang="ts">
134
+ useHead({
135
+ link: [
136
+ {
137
+ rel: 'stylesheet',
138
+ href: 'https://cdn.example.com/styles.css',
139
+ },
140
+ ],
141
+ script: [
142
+ {
143
+ src: 'https://cdn.example.com/script.js',
144
+ async: true,
145
+ },
146
+ ],
147
+ })
148
+ </script>
149
+ ```
150
+
151
+ ### Body and HTML Attributes
152
+
153
+ ```vue [app/pages/themed.vue]
154
+ <script setup lang="ts">
155
+ const isDark = ref(true)
156
+
157
+ useHead({
158
+ htmlAttrs: {
159
+ lang: 'en',
160
+ class: computed(() => isDark.value ? 'dark' : 'light'),
161
+ },
162
+ bodyAttrs: {
163
+ class: 'themed-page',
164
+ },
165
+ })
166
+ </script>
167
+ ```
168
+
169
+ :read-more{to="/docs/3.x/getting-started/seo-meta"}