@nuxt/docs-nightly 4.3.0-29356103.2f7957ac → 4.3.0-29430616.754c35a4

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 (250) hide show
  1. package/1.getting-started/01.introduction.md +1 -1
  2. package/1.getting-started/02.installation.md +4 -6
  3. package/1.getting-started/03.configuration.md +27 -27
  4. package/1.getting-started/04.views.md +5 -5
  5. package/1.getting-started/05.assets.md +8 -8
  6. package/1.getting-started/06.styling.md +15 -15
  7. package/1.getting-started/07.routing.md +10 -6
  8. package/1.getting-started/08.seo-meta.md +3 -3
  9. package/1.getting-started/09.transitions.md +10 -10
  10. package/1.getting-started/10.data-fetching.md +16 -16
  11. package/1.getting-started/11.state-management.md +3 -3
  12. package/1.getting-started/12.error-handling.md +6 -6
  13. package/1.getting-started/13.server.md +6 -6
  14. package/1.getting-started/14.layers.md +32 -13
  15. package/1.getting-started/16.deployment.md +1 -1
  16. package/1.getting-started/17.testing.md +36 -5
  17. package/1.getting-started/18.upgrade.md +43 -35
  18. package/{2.guide/1.directory-structure → 2.directory-structure}/0.nuxt.md +1 -1
  19. package/{2.guide/1.directory-structure → 2.directory-structure}/0.output.md +1 -1
  20. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/1.assets.md +2 -2
  21. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/1.components.md +6 -6
  22. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/1.composables.md +2 -2
  23. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/1.layouts.md +3 -3
  24. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/1.middleware.md +5 -5
  25. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/1.pages.md +17 -17
  26. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/1.plugins.md +3 -7
  27. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/1.utils.md +3 -3
  28. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/3.app.md +4 -4
  29. package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/3.error.md +1 -3
  30. package/{2.guide/1.directory-structure → 2.directory-structure}/1.content.md +2 -2
  31. package/{2.guide/1.directory-structure → 2.directory-structure}/1.modules.md +2 -2
  32. package/{2.guide/1.directory-structure → 2.directory-structure}/1.node_modules.md +2 -2
  33. package/{2.guide/1.directory-structure → 2.directory-structure}/1.public.md +1 -1
  34. package/{2.guide/1.directory-structure → 2.directory-structure}/1.server.md +7 -7
  35. package/{2.guide/1.directory-structure → 2.directory-structure}/1.shared.md +3 -3
  36. package/{2.guide/1.directory-structure → 2.directory-structure}/2.env.md +2 -2
  37. package/{2.guide/1.directory-structure → 2.directory-structure}/2.nuxtignore.md +1 -1
  38. package/{2.guide/1.directory-structure → 2.directory-structure}/2.nuxtrc.md +1 -1
  39. package/{2.guide/1.directory-structure → 2.directory-structure}/3.nuxt-config.md +1 -1
  40. package/{2.guide/1.directory-structure → 2.directory-structure}/3.package.md +1 -1
  41. package/2.directory-structure/3.tsconfig.md +69 -0
  42. package/2.directory-structure/index.md +61 -0
  43. package/{2.guide → 3.guide}/0.index.md +10 -7
  44. package/{2.guide/2.concepts/3.rendering.md → 3.guide/1.concepts/1.rendering.md} +4 -30
  45. package/{2.guide/2.concepts/2.vuejs-development.md → 3.guide/1.concepts/10.vuejs-development.md} +7 -6
  46. package/{2.guide/2.concepts/10.nuxt-lifecycle.md → 3.guide/1.concepts/2.nuxt-lifecycle.md} +32 -25
  47. package/{2.guide/2.concepts/1.auto-imports.md → 3.guide/1.concepts/3.auto-imports.md} +7 -7
  48. package/{2.guide/2.concepts → 3.guide/1.concepts}/4.server-engine.md +3 -3
  49. package/{2.guide/2.concepts → 3.guide/1.concepts}/5.modules.md +2 -2
  50. package/{2.guide/2.concepts → 3.guide/1.concepts}/7.esm.md +3 -2
  51. package/{2.guide/2.concepts → 3.guide/1.concepts}/8.typescript.md +15 -38
  52. package/{2.guide/2.concepts → 3.guide/1.concepts}/9.code-style.md +1 -1
  53. package/{2.guide/5.best-practices → 3.guide/2.best-practices}/hydration.md +1 -1
  54. package/{2.guide/5.best-practices → 3.guide/2.best-practices}/performance.md +2 -2
  55. package/3.guide/3.ai/.navigation.yml +3 -0
  56. package/3.guide/3.ai/1.mcp.md +255 -0
  57. package/3.guide/3.ai/2.llms-txt.md +65 -0
  58. package/3.guide/4.modules/.navigation.yml +3 -0
  59. package/3.guide/4.modules/1.getting-started.md +103 -0
  60. package/3.guide/4.modules/2.module-anatomy.md +138 -0
  61. package/3.guide/4.modules/3.recipes-basics.md +299 -0
  62. package/3.guide/4.modules/4.recipes-advanced.md +231 -0
  63. package/3.guide/4.modules/5.testing.md +76 -0
  64. package/3.guide/4.modules/6.best-practices.md +104 -0
  65. package/3.guide/4.modules/7.ecosystem.md +32 -0
  66. package/3.guide/4.modules/index.md +36 -0
  67. package/{2.guide/4.recipes → 3.guide/5.recipes}/1.custom-routing.md +5 -5
  68. package/{2.guide/4.recipes → 3.guide/5.recipes}/2.vite-plugin.md +1 -1
  69. package/{2.guide/4.recipes → 3.guide/5.recipes}/3.custom-usefetch.md +1 -1
  70. package/{2.guide/4.recipes → 3.guide/5.recipes}/4.sessions-and-authentication.md +1 -1
  71. package/{2.guide/3.going-further → 3.guide/6.going-further}/1.events.md +2 -3
  72. package/{2.guide/3.going-further → 3.guide/6.going-further}/1.experimental-features.md +10 -10
  73. package/{2.guide/3.going-further → 3.guide/6.going-further}/1.features.md +1 -1
  74. package/{2.guide/3.going-further → 3.guide/6.going-further}/1.internals.md +5 -4
  75. package/{2.guide/3.going-further → 3.guide/6.going-further}/10.runtime-config.md +2 -2
  76. package/{2.guide/3.going-further → 3.guide/6.going-further}/2.hooks.md +3 -3
  77. package/{2.guide/3.going-further → 3.guide/6.going-further}/4.kit.md +1 -1
  78. package/{2.guide/3.going-further → 3.guide/6.going-further}/6.nuxt-app.md +5 -5
  79. package/{2.guide/3.going-further → 3.guide/6.going-further}/7.layers.md +42 -25
  80. package/{2.guide/3.going-further → 3.guide/6.going-further}/9.debugging.md +1 -1
  81. package/{3.api → 4.api}/1.components/10.nuxt-picture.md +1 -1
  82. package/{3.api → 4.api}/1.components/11.teleports.md +1 -1
  83. package/{3.api → 4.api}/1.components/12.nuxt-route-announcer.md +1 -3
  84. package/{3.api → 4.api}/1.components/13.nuxt-time.md +0 -2
  85. package/{3.api → 4.api}/1.components/2.nuxt-page.md +3 -3
  86. package/{3.api → 4.api}/1.components/3.nuxt-layout.md +5 -5
  87. package/{3.api → 4.api}/1.components/4.nuxt-link.md +11 -11
  88. package/{3.api → 4.api}/1.components/5.nuxt-loading-indicator.md +1 -1
  89. package/{3.api → 4.api}/1.components/6.nuxt-error-boundary.md +1 -1
  90. package/{3.api → 4.api}/1.components/7.nuxt-welcome.md +2 -2
  91. package/{3.api → 4.api}/2.composables/use-app-config.md +1 -1
  92. package/{3.api → 4.api}/2.composables/use-async-data.md +76 -13
  93. package/4.api/2.composables/use-cookie.md +183 -0
  94. package/{3.api → 4.api}/2.composables/use-fetch.md +33 -33
  95. package/{3.api → 4.api}/2.composables/use-head-safe.md +37 -20
  96. package/4.api/2.composables/use-head.md +184 -0
  97. package/{3.api → 4.api}/2.composables/use-hydration.md +24 -18
  98. package/4.api/2.composables/use-lazy-async-data.md +96 -0
  99. package/4.api/2.composables/use-lazy-fetch.md +111 -0
  100. package/{3.api → 4.api}/2.composables/use-nuxt-app.md +7 -7
  101. package/{3.api → 4.api}/2.composables/use-nuxt-data.md +1 -1
  102. package/{3.api → 4.api}/2.composables/use-request-fetch.md +1 -1
  103. package/{3.api → 4.api}/2.composables/use-response-header.md +1 -1
  104. package/{3.api → 4.api}/2.composables/use-route-announcer.md +0 -2
  105. package/{3.api → 4.api}/2.composables/use-route.md +2 -2
  106. package/4.api/2.composables/use-router.md +94 -0
  107. package/{3.api → 4.api}/2.composables/use-runtime-config.md +1 -1
  108. package/{3.api → 4.api}/2.composables/use-runtime-hook.md +1 -1
  109. package/{3.api → 4.api}/2.composables/use-state.md +1 -1
  110. package/{3.api → 4.api}/3.utils/$fetch.md +1 -1
  111. package/{3.api → 4.api}/3.utils/abort-navigation.md +3 -3
  112. package/{3.api → 4.api}/3.utils/add-route-middleware.md +1 -1
  113. package/{3.api → 4.api}/3.utils/call-once.md +0 -2
  114. package/{3.api → 4.api}/3.utils/define-lazy-hydration-component.md +4 -4
  115. package/{3.api → 4.api}/3.utils/define-nuxt-component.md +1 -1
  116. package/4.api/3.utils/define-nuxt-plugin.md +102 -0
  117. package/{3.api → 4.api}/3.utils/define-nuxt-route-middleware.md +2 -2
  118. package/{3.api → 4.api}/3.utils/define-page-meta.md +14 -14
  119. package/{3.api → 4.api}/3.utils/navigate-to.md +15 -15
  120. package/{3.api → 4.api}/3.utils/on-before-route-leave.md +1 -1
  121. package/{3.api → 4.api}/3.utils/on-before-route-update.md +1 -1
  122. package/{3.api → 4.api}/3.utils/refresh-cookie.md +1 -3
  123. package/{3.api → 4.api}/3.utils/update-app-config.md +2 -2
  124. package/{3.api → 4.api}/4.commands/add.md +11 -11
  125. package/4.api/4.commands/analyze.md +42 -0
  126. package/4.api/4.commands/build-module.md +42 -0
  127. package/4.api/4.commands/build.md +47 -0
  128. package/{3.api → 4.api}/4.commands/cleanup.md +6 -6
  129. package/4.api/4.commands/dev.md +60 -0
  130. package/{3.api → 4.api}/4.commands/devtools.md +7 -7
  131. package/4.api/4.commands/generate.md +42 -0
  132. package/4.api/4.commands/info.md +33 -0
  133. package/4.api/4.commands/init.md +50 -0
  134. package/4.api/4.commands/module.md +84 -0
  135. package/4.api/4.commands/prepare.md +41 -0
  136. package/4.api/4.commands/preview.md +44 -0
  137. package/4.api/4.commands/test.md +40 -0
  138. package/4.api/4.commands/typecheck.md +44 -0
  139. package/4.api/4.commands/upgrade.md +37 -0
  140. package/{3.api → 4.api}/5.kit/1.modules.md +18 -18
  141. package/{3.api → 4.api}/5.kit/10.templates.md +23 -23
  142. package/{3.api → 4.api}/5.kit/11.nitro.md +35 -35
  143. package/{3.api → 4.api}/5.kit/14.builder.md +21 -21
  144. package/{3.api → 4.api}/5.kit/16.layers.md +12 -12
  145. package/{3.api → 4.api}/5.kit/2.programmatic.md +2 -2
  146. package/{3.api → 4.api}/5.kit/4.autoimports.md +18 -18
  147. package/4.api/5.kit/5.components.md +146 -0
  148. package/4.api/6.advanced/1.hooks.md +105 -0
  149. package/{3.api → 4.api}/6.nuxt-config.md +29 -28
  150. package/5.community/3.reporting-bugs.md +1 -1
  151. package/5.community/4.contribution.md +4 -4
  152. package/5.community/5.framework-contribution.md +8 -8
  153. package/5.community/6.roadmap.md +25 -25
  154. package/5.community/7.changelog.md +10 -0
  155. package/6.bridge/1.overview.md +1 -1
  156. package/6.bridge/2.typescript.md +1 -1
  157. package/6.bridge/3.bridge-composition-api.md +1 -1
  158. package/6.bridge/4.plugins-and-middleware.md +2 -2
  159. package/7.migration/11.server.md +1 -1
  160. package/7.migration/2.configuration.md +5 -5
  161. package/7.migration/20.module-authors.md +3 -3
  162. package/7.migration/3.auto-imports.md +1 -1
  163. package/7.migration/5.plugins-and-middleware.md +2 -2
  164. package/7.migration/6.pages-and-layouts.md +6 -6
  165. package/README.md +1 -1
  166. package/package.json +1 -1
  167. package/2.guide/1.directory-structure/3.tsconfig.md +0 -38
  168. package/2.guide/3.going-further/3.modules.md +0 -901
  169. package/3.api/2.composables/use-cookie.md +0 -183
  170. package/3.api/2.composables/use-head.md +0 -69
  171. package/3.api/2.composables/use-lazy-async-data.md +0 -47
  172. package/3.api/2.composables/use-lazy-fetch.md +0 -55
  173. package/3.api/2.composables/use-router.md +0 -94
  174. package/3.api/3.utils/define-nuxt-plugin.md +0 -102
  175. package/3.api/4.commands/analyze.md +0 -42
  176. package/3.api/4.commands/build-module.md +0 -42
  177. package/3.api/4.commands/build.md +0 -47
  178. package/3.api/4.commands/dev.md +0 -60
  179. package/3.api/4.commands/generate.md +0 -42
  180. package/3.api/4.commands/info.md +0 -33
  181. package/3.api/4.commands/init.md +0 -50
  182. package/3.api/4.commands/module.md +0 -84
  183. package/3.api/4.commands/prepare.md +0 -41
  184. package/3.api/4.commands/preview.md +0 -44
  185. package/3.api/4.commands/test.md +0 -40
  186. package/3.api/4.commands/typecheck.md +0 -44
  187. package/3.api/4.commands/upgrade.md +0 -37
  188. package/3.api/5.kit/5.components.md +0 -146
  189. package/3.api/6.advanced/1.hooks.md +0 -105
  190. /package/{2.guide/1.directory-structure → 2.directory-structure}/.navigation.yml +0 -0
  191. /package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/.navigation.yml +0 -0
  192. /package/{2.guide/1.directory-structure → 2.directory-structure}/1.app/3.app-config.md +0 -0
  193. /package/{2.guide/1.directory-structure → 2.directory-structure}/2.gitignore.md +0 -0
  194. /package/{2.guide → 3.guide}/.navigation.yml +0 -0
  195. /package/{2.guide/2.concepts → 3.guide/1.concepts}/.navigation.yml +0 -0
  196. /package/{2.guide/5.best-practices → 3.guide/2.best-practices}/.navigation.yml +0 -0
  197. /package/{2.guide/5.best-practices → 3.guide/2.best-practices}/plugins.md +0 -0
  198. /package/{2.guide/4.recipes → 3.guide/5.recipes}/.navigation.yml +0 -0
  199. /package/{2.guide/3.going-further → 3.guide/6.going-further}/.navigation.yml +0 -0
  200. /package/{2.guide/3.going-further → 3.guide/6.going-further}/11.nightly-release-channel.md +0 -0
  201. /package/{2.guide/3.going-further → 3.guide/6.going-further}/index.md +0 -0
  202. /package/{3.api → 4.api}/.navigation.yml +0 -0
  203. /package/{3.api → 4.api}/1.components/.navigation.yml +0 -0
  204. /package/{3.api → 4.api}/1.components/1.client-only.md +0 -0
  205. /package/{3.api → 4.api}/1.components/1.dev-only.md +0 -0
  206. /package/{3.api → 4.api}/1.components/1.nuxt-client-fallback.md +0 -0
  207. /package/{3.api → 4.api}/1.components/8.nuxt-island.md +0 -0
  208. /package/{3.api → 4.api}/1.components/9.nuxt-img.md +0 -0
  209. /package/{3.api → 4.api}/2.composables/.navigation.yml +0 -0
  210. /package/{3.api → 4.api}/2.composables/on-prehydrate.md +0 -0
  211. /package/{3.api → 4.api}/2.composables/use-error.md +0 -0
  212. /package/{3.api → 4.api}/2.composables/use-loading-indicator.md +0 -0
  213. /package/{3.api → 4.api}/2.composables/use-preview-mode.md +0 -0
  214. /package/{3.api → 4.api}/2.composables/use-request-event.md +0 -0
  215. /package/{3.api → 4.api}/2.composables/use-request-header.md +0 -0
  216. /package/{3.api → 4.api}/2.composables/use-request-headers.md +0 -0
  217. /package/{3.api → 4.api}/2.composables/use-request-url.md +0 -0
  218. /package/{3.api → 4.api}/2.composables/use-seo-meta.md +0 -0
  219. /package/{3.api → 4.api}/2.composables/use-server-seo-meta.md +0 -0
  220. /package/{3.api → 4.api}/3.utils/.navigation.yml +0 -0
  221. /package/{3.api → 4.api}/3.utils/clear-error.md +0 -0
  222. /package/{3.api → 4.api}/3.utils/clear-nuxt-data.md +0 -0
  223. /package/{3.api → 4.api}/3.utils/clear-nuxt-state.md +0 -0
  224. /package/{3.api → 4.api}/3.utils/create-error.md +0 -0
  225. /package/{3.api → 4.api}/3.utils/define-route-rules.md +0 -0
  226. /package/{3.api → 4.api}/3.utils/on-nuxt-ready.md +0 -0
  227. /package/{3.api → 4.api}/3.utils/prefetch-components.md +0 -0
  228. /package/{3.api → 4.api}/3.utils/preload-components.md +0 -0
  229. /package/{3.api → 4.api}/3.utils/preload-route-components.md +0 -0
  230. /package/{3.api → 4.api}/3.utils/prerender-routes.md +0 -0
  231. /package/{3.api → 4.api}/3.utils/refresh-nuxt-data.md +0 -0
  232. /package/{3.api → 4.api}/3.utils/reload-nuxt-app.md +0 -0
  233. /package/{3.api → 4.api}/3.utils/set-page-layout.md +0 -0
  234. /package/{3.api → 4.api}/3.utils/set-response-status.md +0 -0
  235. /package/{3.api → 4.api}/3.utils/show-error.md +0 -0
  236. /package/{3.api → 4.api}/4.commands/.navigation.yml +0 -0
  237. /package/{3.api → 4.api}/5.kit/.navigation.yml +0 -0
  238. /package/{3.api → 4.api}/5.kit/10.runtime-config.md +0 -0
  239. /package/{3.api → 4.api}/5.kit/12.resolving.md +0 -0
  240. /package/{3.api → 4.api}/5.kit/13.logging.md +0 -0
  241. /package/{3.api → 4.api}/5.kit/15.examples.md +0 -0
  242. /package/{3.api → 4.api}/5.kit/3.compatibility.md +0 -0
  243. /package/{3.api → 4.api}/5.kit/6.context.md +0 -0
  244. /package/{3.api → 4.api}/5.kit/7.pages.md +0 -0
  245. /package/{3.api → 4.api}/5.kit/8.layout.md +0 -0
  246. /package/{3.api → 4.api}/5.kit/9.head.md +0 -0
  247. /package/{3.api → 4.api}/5.kit/9.plugins.md +0 -0
  248. /package/{3.api → 4.api}/6.advanced/.navigation.yml +0 -0
  249. /package/{3.api → 4.api}/6.advanced/2.import-meta.md +0 -0
  250. /package/{3.api → 4.api}/index.md +0 -0
@@ -1,901 +0,0 @@
1
- ---
2
- title: "Module Author Guide"
3
- description: "Learn how to create a Nuxt Module to integrate, enhance or extend any Nuxt applications."
4
- image: '/socials/module-author-guide.jpg'
5
- ---
6
-
7
- Nuxt's [configuration](/docs/4.x/api/nuxt-config) and [hooks](/docs/4.x/guide/going-further/hooks) systems make it possible to customize every aspect of Nuxt and add any integration you might need (Vue plugins, CMS, server routes, components, logging, etc.).
8
-
9
- **Nuxt Modules** are functions that sequentially run when starting Nuxt in development mode using `nuxt dev` or building a project for production with `nuxt build`.
10
- With modules, you can encapsulate, properly test, and share custom solutions as npm packages without adding unnecessary boilerplate to your project, or requiring changes to Nuxt itself.
11
-
12
- ## Quick Start
13
-
14
- We recommend you get started with Nuxt Modules using our [starter template](https://github.com/nuxt/starter/tree/module):
15
-
16
- ::code-group{sync="pm"}
17
-
18
- ```bash [npm]
19
- npm create nuxt -- -t module my-module
20
- ```
21
-
22
- ```bash [yarn]
23
- yarn create nuxt -t module my-module
24
- ```
25
-
26
- ```bash [pnpm]
27
- pnpm create nuxt -t module my-module
28
- ```
29
-
30
- ```bash [bun]
31
- bun create nuxt -- -t module my-module
32
- ```
33
- ::
34
-
35
- This will create a `my-module` project with all the boilerplate necessary to develop and publish your module.
36
-
37
- **Next steps:**
38
-
39
- 1. Open `my-module` in your IDE of choice
40
- 2. Install dependencies using your favorite package manager
41
- 3. Prepare local files for development using `npm run dev:prepare`
42
- 4. Follow this document to learn more about Nuxt Modules
43
-
44
- ### Using the Starter
45
-
46
- Learn how to perform basic tasks with the module starter.
47
-
48
- ::tip{icon="i-lucide-video" to="https://vueschool.io/lessons/navigating-the-official-starter-template?friend=nuxt" target="_blank"}
49
- Watch Vue School video about Nuxt module starter template.
50
- ::
51
-
52
- #### How to Develop
53
-
54
- While your module source code lives inside the `src` directory, in most cases, to develop a module, you need a Nuxt application. That's what the `playground` directory is about. It's a Nuxt application you can tinker with that is already configured to run with your module.
55
-
56
- You can interact with the playground like with any Nuxt application.
57
-
58
- - Launch its development server with `npm run dev`, it should reload itself as you make changes to your module in the `src` directory
59
- - Build it with `npm run dev:build`
60
-
61
- ::note
62
- All other `nuxt` commands can be used against the `playground` directory (e.g. `nuxt <COMMAND> playground`). Feel free to declare additional `dev:*` scripts within your `package.json` referencing them for convenience.
63
- ::
64
-
65
- #### How to Test
66
-
67
- The module starter comes with a basic test suite:
68
-
69
- - A linter powered by [ESLint](https://eslint.org), run it with `npm run lint`
70
- - A test runner powered by [Vitest](https://vitest.dev), run it with `npm run test` or `npm run test:watch`
71
-
72
- ::tip
73
- Feel free to augment this default test strategy to better suit your needs.
74
- ::
75
-
76
- #### How to Build
77
-
78
- Nuxt Modules come with their own builder provided by [`@nuxt/module-builder`](https://github.com/nuxt/module-builder#readme). This builder doesn't require any configuration on your end, supports TypeScript, and makes sure your assets are properly bundled to be distributed to other Nuxt applications.
79
-
80
- You can build your module by running `npm run prepack`.
81
-
82
- ::tip
83
- While building your module can be useful in some cases, most of the time you won't need to build it on your own: the `playground` takes care of it while developing, and the release script also has you covered when publishing.
84
- ::
85
-
86
- #### How to Publish
87
-
88
- ::important
89
- Before publishing your module to npm, makes sure you have an [npmjs.com](https://www.npmjs.com) account and that you're authenticated to it locally with `npm login`.
90
- ::
91
-
92
- While you can publish your module by bumping its version and using the `npm publish` command, the module starter comes with a release script that helps you make sure you publish a working version of your module to npm and more.
93
-
94
- To use the release script, first, commit all your changes (we recommend you follow [Conventional Commits](https://www.conventionalcommits.org) to also take advantage of automatic version bump and changelog update), then run the release script with `npm run release`.
95
-
96
- When running the release script, the following will happen:
97
-
98
- - First, it will run your test suite by:
99
- - Running the linter (`npm run lint`)
100
- - Running unit, integration, and e2e tests (`npm run test`)
101
- - Building the module (`npm run prepack`)
102
- - Then, if your test suite went well, it will proceed to publish your module by:
103
- - Bumping your module version and generating a changelog according to your Conventional Commits
104
- - Publishing the module to npm (for that purpose, the module will be built again to ensure its updated version number is taken into account in the published artifact)
105
- - Pushing a git tag representing the newly published version to your git remote origin
106
-
107
- ::tip
108
- As with other scripts, feel free to fine-tune the default `release` script in your `package.json` to better suit your needs.
109
- ::
110
-
111
- ## Developing Modules
112
-
113
- Nuxt Modules come with a variety of powerful APIs and patterns allowing them to alter a Nuxt application in pretty much any way possible. This section teaches you how to take advantage of those.
114
-
115
- ### Module Anatomy
116
-
117
- We can consider two kinds of Nuxt Modules:
118
-
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/4.x/api/nuxt-config#modules) or as part of [the `modules` directory](/docs/4.x/guide/directory-structure/modules).
121
-
122
- In either case, their anatomy is similar.
123
-
124
- #### Module Definition
125
-
126
- ::note
127
- When using the starter, your module definition is available at `src/module.ts`.
128
- ::
129
-
130
- The module definition is the entry point of your module. It's what gets loaded by Nuxt when your module is referenced within a Nuxt configuration.
131
-
132
- At a low level, a Nuxt Module definition is a simple, potentially asynchronous, function accepting inline user options and a `nuxt` object to interact with Nuxt.
133
-
134
- ```ts
135
- export default function (inlineOptions, nuxt) {
136
- // You can do whatever you like here..
137
- console.log(inlineOptions.token) // `123`
138
- console.log(nuxt.options.dev) // `true` or `false`
139
- nuxt.hook('ready', (nuxt) => {
140
- console.log('Nuxt is ready')
141
- })
142
- }
143
- ```
144
-
145
- You can get type-hint support for this function using the higher-level `defineNuxtModule` helper provided by [Nuxt Kit](/docs/4.x/guide/going-further/kit).
146
-
147
- ```ts
148
- import { defineNuxtModule } from '@nuxt/kit'
149
-
150
- export default defineNuxtModule((options, nuxt) => {
151
- nuxt.hook('pages:extend', (pages) => {
152
- console.log(`Discovered ${pages.length} pages`)
153
- })
154
- })
155
- ```
156
-
157
- However, **we do not recommend** using this low-level function definition. Instead, to define a module, **we recommend** using the object-syntax with `meta` property to identify your module, especially when publishing to npm.
158
-
159
- This helper makes writing Nuxt modules more straightforward by implementing many common patterns needed by modules, guaranteeing future compatibility and improving the experience for both module authors and users.
160
-
161
- ```ts
162
- import { defineNuxtModule } from '@nuxt/kit'
163
-
164
- export default defineNuxtModule({
165
- meta: {
166
- // Usually the npm package name of your module
167
- name: '@nuxtjs/example',
168
- // The key in `nuxt.config` that holds your module options
169
- configKey: 'sample',
170
- // Compatibility constraints
171
- compatibility: {
172
- // Semver version of supported nuxt versions
173
- nuxt: '>=3.0.0',
174
- },
175
- },
176
- // Default configuration options for your module, can also be a function returning those
177
- defaults: {},
178
- // Shorthand sugar to register Nuxt hooks
179
- hooks: {},
180
- // Configuration for other modules - this does not ensure the module runs before
181
- // your module, but it allows you to change the other module's configuration before it runs
182
- moduleDependencies: {
183
- 'some-module': {
184
- // You can specify a version constraint for the module. If the user has a different
185
- // version installed, Nuxt will throw an error on startup.
186
- version: '>=2',
187
- // By default moduleDependencies will be added to the list of modules to be installed
188
- // by Nuxt unless `optional` is set.
189
- optional: true,
190
- // Any configuration that should override `nuxt.options`.
191
- overrides: {},
192
- // Any configuration that should be set. It will override module defaults but
193
- // will not override any configuration set in `nuxt.options`.
194
- defaults: {},
195
- },
196
- },
197
- // The function holding your module logic, it can be asynchronous
198
- setup (moduleOptions, nuxt) {
199
- // ...
200
- },
201
- })
202
- ```
203
-
204
- Ultimately `defineNuxtModule` returns a wrapper function with the lower level `(inlineOptions, nuxt)` module signature. This wrapper function applies defaults and other necessary steps before calling your `setup` function:
205
-
206
- - Support `defaults` and `meta.configKey` for automatically merging module options
207
- - Type hints and automated type inference
208
- - Add shims for basic Nuxt 2 compatibility
209
- - Ensure module gets installed only once using a unique key computed from `meta.name` or `meta.configKey`
210
- - Automatically register Nuxt hooks
211
- - Automatically check for compatibility issues based on module meta
212
- - Expose `getOptions` and `getMeta` for internal usage of Nuxt
213
- - Ensuring backward and upward compatibility as long as the module is using `defineNuxtModule` from the latest version of `@nuxt/kit`
214
- - Integration with module builder tooling
215
-
216
- #### Runtime Directory
217
-
218
- ::note
219
- When using the starter, the runtime directory is available at `src/runtime`.
220
- ::
221
-
222
- Modules, like everything in a Nuxt configuration, aren't included in your application runtime. However, you might want your module to provide, or inject runtime code to the application it's installed on. That's what the runtime directory enables you to do.
223
-
224
- Inside the runtime directory, you can provide any kind of assets related to the Nuxt App:
225
- - Vue components
226
- - Composables
227
- - [Nuxt plugins](/docs/4.x/guide/directory-structure/plugins)
228
-
229
- To the [server engine](/docs/4.x/guide/concepts/server-engine), Nitro:
230
- - API routes
231
- - Middlewares
232
- - Nitro plugins
233
-
234
- Or any other kind of asset you want to inject in users' Nuxt applications:
235
- - Stylesheets
236
- - 3D models
237
- - Images
238
- - etc.
239
-
240
- You'll then be able to inject all those assets inside the application from your [module definition](/docs/4.x/guide/going-further/modules#module-definition).
241
-
242
- ::tip
243
- Learn more about asset injection in [the recipes section](/docs/4.x/guide/going-further/modules#recipes).
244
- ::
245
-
246
- ::warning
247
- Published modules cannot leverage auto-imports for assets within their runtime directory. Instead, they have to import them explicitly from `#imports` or alike.
248
- :br :br
249
- Indeed, auto-imports are not enabled for files within `node_modules` (the location where a published module will eventually live) for performance reasons.
250
- ::
251
-
252
- ### Tooling
253
-
254
- Modules come with a set of first-party tools to help you with their development.
255
-
256
- #### `@nuxt/module-builder`
257
-
258
- [Nuxt Module Builder](https://github.com/nuxt/module-builder#readme) is a zero-configuration build tool taking care of all the heavy lifting to build and ship your module. It ensures proper compatibility of your module build artifact with Nuxt applications.
259
-
260
- #### `@nuxt/kit`
261
-
262
- [Nuxt Kit](/docs/4.x/guide/going-further/kit) provides composable utilities to help your module interact with Nuxt applications. It's recommended to use Nuxt Kit utilities over manual alternatives whenever possible to ensure better compatibility and code readability of your module.
263
-
264
- :read-more{to="/docs/4.x/guide/going-further/kit"}
265
-
266
- #### `@nuxt/test-utils`
267
-
268
- [Nuxt Test Utils](/docs/4.x/getting-started/testing) is a collection of utilities to help set up and run Nuxt applications within your module tests.
269
-
270
- ### Recipes
271
-
272
- Find here common patterns used to author modules.
273
-
274
- #### Altering Nuxt Configuration
275
-
276
- Nuxt configuration can be read and altered by modules. Here's an example of a module enabling an experimental feature.
277
-
278
- ```js
279
- import { defineNuxtModule } from '@nuxt/kit'
280
-
281
- export default defineNuxtModule({
282
- setup (options, nuxt) {
283
- // We create the `experimental` object if it doesn't exist yet
284
- nuxt.options.experimental ||= {}
285
- nuxt.options.experimental.componentIslands = true
286
- },
287
- })
288
- ```
289
-
290
- When you need to handle more complex configuration alterations, you should consider using [defu](https://github.com/unjs/defu).
291
-
292
- ::tip{icon="i-lucide-video" to="https://vueschool.io/lessons/extending-and-altering-nuxt-configuration-and-options?friend=nuxt" target="_blank"}
293
- Watch Vue School video about altering Nuxt configuration.
294
- ::
295
-
296
- #### Exposing Options to Runtime
297
-
298
- Because modules aren't part of the application runtime, their options aren't either. However, in many cases, you might need access to some of these module options within your runtime code. We recommend exposing the needed config using Nuxt's [`runtimeConfig`](/docs/4.x/api/nuxt-config#runtimeconfig).
299
-
300
- <!-- TODO: Update after #18466 (or equivalent) -->
301
-
302
- ```js
303
- import { defineNuxtModule } from '@nuxt/kit'
304
- import { defu } from 'defu'
305
-
306
- export default defineNuxtModule({
307
- setup (options, nuxt) {
308
- nuxt.options.runtimeConfig.public.myModule = defu(nuxt.options.runtimeConfig.public.myModule, {
309
- foo: options.foo,
310
- })
311
- },
312
- })
313
- ```
314
-
315
- Note that we use [`defu`](https://github.com/unjs/defu) to extend the public runtime configuration the user provides instead of overwriting it.
316
-
317
- You can then access your module options in a plugin, component, the application like any other runtime configuration:
318
-
319
- ```js
320
- import { useRuntimeConfig } from '@nuxt/kit'
321
-
322
- const options = useRuntimeConfig().public.myModule
323
- ```
324
-
325
- ::warning
326
- Be careful not to expose any sensitive module configuration on the public runtime config, such as private API keys, as they will end up in the public bundle.
327
- ::
328
-
329
- :read-more{to="/docs/4.x/guide/going-further/runtime-config"}
330
-
331
- ::tip{icon="i-lucide-video" to="https://vueschool.io/lessons/passing-and-exposing-module-options?friend=nuxt" target="_blank"}
332
- Watch Vue School video about passing and exposing Nuxt module options.
333
- ::
334
-
335
- #### Injecting Plugins With `addPlugin`
336
-
337
- Plugins are a common way for a module to add runtime logic. You can use the `addPlugin` utility to register them from your module.
338
-
339
- ```js
340
- import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
341
-
342
- export default defineNuxtModule({
343
- setup (options, nuxt) {
344
- // Create resolver to resolve relative paths
345
- const resolver = createResolver(import.meta.url)
346
-
347
- addPlugin(resolver.resolve('./runtime/plugin'))
348
- },
349
- })
350
- ```
351
-
352
- :read-more{to="/docs/4.x/guide/going-further/kit"}
353
-
354
- #### Injecting Vue Components With `addComponent`
355
-
356
- If your module should provide Vue components, you can use the `addComponent` utility to add them as auto-imports for Nuxt to resolve.
357
-
358
- ```ts twoslash
359
- import { addComponent, createResolver, defineNuxtModule, useRuntimeConfig } from '@nuxt/kit'
360
-
361
- export default defineNuxtModule({
362
- setup (options, nuxt) {
363
- const resolver = createResolver(import.meta.url)
364
-
365
- // From the runtime directory
366
- addComponent({
367
- name: 'MySuperComponent', // name of the component to be used in vue templates
368
- export: 'MySuperComponent', // (optional) if the component is a named (rather than default) export
369
- filePath: resolver.resolve('runtime/components/MySuperComponent.vue'),
370
- })
371
-
372
- // From a library
373
- addComponent({
374
- name: 'MyAwesomeComponent', // name of the component to be used in vue templates
375
- export: 'MyAwesomeComponent', // (optional) if the component is a named (rather than default) export
376
- filePath: '@vue/awesome-components',
377
- })
378
- },
379
- })
380
- ```
381
-
382
- Alternatively, you can add an entire directory by using `addComponentsDir`.
383
-
384
- ```ts
385
- import { addComponentsDir, defineNuxtModule } from '@nuxt/kit'
386
-
387
- export default defineNuxtModule({
388
- setup (options, nuxt) {
389
- const resolver = createResolver(import.meta.url)
390
-
391
- addComponentsDir({
392
- path: resolver.resolve('runtime/components'),
393
- })
394
- },
395
- })
396
- ```
397
-
398
- #### Injecting Composables With `addImports` and `addImportsDir`
399
-
400
- If your module should provide composables, you can use the `addImports` utility to add them as auto-imports for Nuxt to resolve.
401
-
402
- ```ts
403
- import { addImports, createResolver, defineNuxtModule } from '@nuxt/kit'
404
-
405
- export default defineNuxtModule({
406
- setup (options, nuxt) {
407
- const resolver = createResolver(import.meta.url)
408
-
409
- addImports({
410
- name: 'useComposable', // name of the composable to be used
411
- as: 'useComposable',
412
- from: resolver.resolve('runtime/composables/useComposable'), // path of composable
413
- })
414
- },
415
- })
416
- ```
417
-
418
- Alternatively, you can add an entire directory by using `addImportsDir`.
419
-
420
- ```ts
421
- import { addImportsDir, createResolver, defineNuxtModule } from '@nuxt/kit'
422
-
423
- export default defineNuxtModule({
424
- setup (options, nuxt) {
425
- const resolver = createResolver(import.meta.url)
426
-
427
- addImportsDir(resolver.resolve('runtime/composables'))
428
- },
429
- })
430
- ```
431
-
432
- #### Injecting Server Routes With `addServerHandler`
433
-
434
- ```ts
435
- import { addServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'
436
-
437
- export default defineNuxtModule({
438
- setup (options, nuxt) {
439
- const resolver = createResolver(import.meta.url)
440
-
441
- addServerHandler({
442
- route: '/api/hello',
443
- handler: resolver.resolve('./runtime/server/api/hello/index.get'),
444
- })
445
- },
446
- })
447
- ```
448
-
449
- You can also add a dynamic server route:
450
-
451
- ```ts
452
- import { addServerHandler, createResolver, defineNuxtModule } from '@nuxt/kit'
453
-
454
- export default defineNuxtModule({
455
- setup (options, nuxt) {
456
- const resolver = createResolver(import.meta.url)
457
-
458
- addServerHandler({
459
- route: '/api/hello/:name',
460
- handler: resolver.resolve('./runtime/server/api/hello/[name].get'),
461
- })
462
- },
463
- })
464
- ```
465
-
466
- #### Injecting Other Assets
467
-
468
- If your module should provide other kinds of assets, they can also be injected. Here's a simple example module injecting a stylesheet through Nuxt's `css` array.
469
-
470
- ```js
471
- import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
472
-
473
- export default defineNuxtModule({
474
- setup (options, nuxt) {
475
- const resolver = createResolver(import.meta.url)
476
-
477
- nuxt.options.css.push(resolver.resolve('./runtime/style.css'))
478
- },
479
- })
480
- ```
481
-
482
- And a more advanced one, exposing a folder of assets through [Nitro](/docs/4.x/guide/concepts/server-engine)'s `publicAssets` option:
483
-
484
- ```js
485
- import { createResolver, defineNuxtModule } from '@nuxt/kit'
486
-
487
- export default defineNuxtModule({
488
- setup (options, nuxt) {
489
- const resolver = createResolver(import.meta.url)
490
-
491
- nuxt.hook('nitro:config', (nitroConfig) => {
492
- nitroConfig.publicAssets ||= []
493
- nitroConfig.publicAssets.push({
494
- dir: resolver.resolve('./runtime/public'),
495
- maxAge: 60 * 60 * 24 * 365, // 1 year
496
- })
497
- })
498
- },
499
- })
500
- ```
501
-
502
- #### Using Other Modules in Your Module
503
-
504
- If your module depends on other modules, you can specify them using the `moduleDependencies` option. This provides a more robust way to handle module dependencies with version constraints and configuration merging:
505
-
506
- ```ts
507
- import { createResolver, defineNuxtModule } from '@nuxt/kit'
508
-
509
- const resolver = createResolver(import.meta.url)
510
-
511
- export default defineNuxtModule<ModuleOptions>({
512
- meta: {
513
- name: 'my-module',
514
- },
515
- moduleDependencies: {
516
- '@nuxtjs/tailwindcss': {
517
- // You can specify a version constraint for the module
518
- version: '>=6',
519
- // Any configuration that should override `nuxt.options`
520
- overrides: {
521
- exposeConfig: true,
522
- },
523
- // Any configuration that should be set. It will override module defaults but
524
- // will not override any configuration set in `nuxt.options`
525
- defaults: {
526
- config: {
527
- darkMode: 'class',
528
- content: {
529
- files: [
530
- resolver.resolve('./runtime/components/**/*.{vue,mjs,ts}'),
531
- resolver.resolve('./runtime/*.{mjs,js,ts}'),
532
- ],
533
- },
534
- },
535
- },
536
- },
537
- },
538
- setup (options, nuxt) {
539
- // We can inject our CSS file which includes Tailwind's directives
540
- nuxt.options.css.push(resolver.resolve('./runtime/assets/styles.css'))
541
- },
542
- })
543
- ```
544
-
545
- ::callout{type="info"}
546
- The `moduleDependencies` option replaces the deprecated `installModule` function and ensures proper setup order and configuration merging.
547
- ::
548
-
549
- #### Using Hooks
550
-
551
- [Lifecycle hooks](/docs/4.x/guide/going-further/hooks) allow you to expand almost every aspect of Nuxt. Modules can hook to them programmatically or through the `hooks` map in their definition.
552
-
553
- ```js
554
- import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'
555
-
556
- export default defineNuxtModule({
557
- // Hook to the `app:error` hook through the `hooks` map
558
- hooks: {
559
- 'app:error': (err) => {
560
- console.info(`This error happened: ${err}`)
561
- },
562
- },
563
- setup (options, nuxt) {
564
- // Programmatically hook to the `pages:extend` hook
565
- nuxt.hook('pages:extend', (pages) => {
566
- console.info(`Discovered ${pages.length} pages`)
567
- })
568
- },
569
- })
570
- ```
571
-
572
- :read-more{to="/docs/4.x/api/advanced/hooks"}
573
-
574
- ::tip{icon="i-lucide-video" to="https://vueschool.io/lessons/nuxt-lifecycle-hooks?friend=nuxt" target="_blank"}
575
- Watch Vue School video about using Nuxt lifecycle hooks in modules.
576
- ::
577
-
578
- ::note
579
- **Module cleanup**
580
- :br
581
- :br
582
- If your module opens, handles, or starts a watcher, you should close it when the Nuxt lifecycle is done. The `close` hook is available for this.
583
-
584
- ```ts
585
- import { defineNuxtModule } from '@nuxt/kit'
586
-
587
- export default defineNuxtModule({
588
- setup (options, nuxt) {
589
- nuxt.hook('close', async (nuxt) => {
590
- // Your custom code here
591
- })
592
- },
593
- })
594
- ```
595
- ::
596
-
597
- ##### Custom Hooks
598
-
599
- Modules can also define and call their own hooks, which is a powerful pattern for making your module extensible.
600
-
601
- If you expect other modules to be able to subscribe to your module's hooks, you should call them in the `modules:done` hook. This ensures that all other modules have had a chance to be set up and register their listeners to your hook during their own `setup` function.
602
-
603
- ```ts
604
- // my-module/module.ts
605
- import { defineNuxtModule } from '@nuxt/kit'
606
-
607
- export interface ModuleHooks {
608
- 'my-module:custom-hook': (payload: { foo: string }) => void
609
- }
610
-
611
- export default defineNuxtModule({
612
- setup (options, nuxt) {
613
- // Call your hook in `modules:done`
614
- nuxt.hook('modules:done', async () => {
615
- const payload = { foo: 'bar' }
616
- await nuxt.callHook('my-module:custom-hook', payload)
617
- })
618
- },
619
- })
620
- ```
621
-
622
- #### Adding Templates/Virtual Files
623
-
624
- If you need to add a virtual file that can be imported into the user's app, you can use the `addTemplate` utility.
625
-
626
- ```ts
627
- import { addTemplate, defineNuxtModule } from '@nuxt/kit'
628
-
629
- export default defineNuxtModule({
630
- setup (options, nuxt) {
631
- // The file is added to Nuxt's internal virtual file system and can be imported from '#build/my-module-feature.mjs'
632
- addTemplate({
633
- filename: 'my-module-feature.mjs',
634
- getContents: () => 'export const myModuleFeature = () => "hello world !"',
635
- })
636
- },
637
- })
638
- ```
639
-
640
- For the server, you should use the `addServerTemplate` utility instead.
641
-
642
- ```ts
643
- import { addServerTemplate, defineNuxtModule } from '@nuxt/kit'
644
-
645
- export default defineNuxtModule({
646
- setup (options, nuxt) {
647
- // The file is added to Nitro's virtual file system and can be imported in the server code from 'my-server-module.mjs'
648
- addServerTemplate({
649
- filename: 'my-server-module.mjs',
650
- getContents: () => 'export const myServerModule = () => "hello world !"',
651
- })
652
- },
653
- })
654
- ```
655
-
656
- #### Adding Type Declarations
657
-
658
- You might also want to add a type declaration to the user's project (for example, to augment a Nuxt interface
659
- or provide a global type of your own). For this, Nuxt provides the `addTypeTemplate` utility that both
660
- writes a template to the disk and adds a reference to it in the generated `nuxt.d.ts` file.
661
-
662
- If your module should augment types handled by Nuxt, you can use `addTypeTemplate` to perform this operation:
663
-
664
- ```js
665
- import { addTemplate, addTypeTemplate, defineNuxtModule } from '@nuxt/kit'
666
-
667
- export default defineNuxtModule({
668
- setup (options, nuxt) {
669
- addTypeTemplate({
670
- filename: 'types/my-module.d.ts',
671
- getContents: () => `// Generated by my-module
672
- interface MyModuleNitroRules {
673
- myModule?: { foo: 'bar' }
674
- }
675
- declare module 'nitropack/types' {
676
- interface NitroRouteRules extends MyModuleNitroRules {}
677
- interface NitroRouteConfig extends MyModuleNitroRules {}
678
- }
679
- export {}`,
680
- })
681
- },
682
- })
683
- ```
684
-
685
- If you need more granular control, you can use the `prepare:types` hook to register a callback that will inject your types.
686
-
687
- ```ts
688
- const template = addTemplate({ /* template options */ })
689
- nuxt.hook('prepare:types', ({ references }) => {
690
- references.push({ path: template.dst })
691
- })
692
- ```
693
-
694
- ##### Updating Templates
695
-
696
- If you need to update your templates/virtual files, you can leverage the `updateTemplates` utility like this :
697
-
698
- ```ts
699
- nuxt.hook('builder:watch', (event, path) => {
700
- if (path.includes('my-module-feature.config')) {
701
- // This will reload the template that you registered
702
- updateTemplates({ filter: t => t.filename === 'my-module-feature.mjs' })
703
- }
704
- })
705
- ```
706
-
707
- ### Testing
708
-
709
- Testing helps ensuring your module works as expected given various setup. Find in this section how to perform various kinds of tests against your module.
710
-
711
- #### Unit and Integration
712
-
713
- ::tip
714
- We're still discussing and exploring how to ease unit and integration testing on Nuxt Modules.
715
- :br :br
716
- [Check out this RFC to join the conversation](https://github.com/nuxt/nuxt/discussions/18399).
717
- ::
718
-
719
- #### End to End
720
-
721
- [Nuxt Test Utils](/docs/4.x/getting-started/testing) is the go-to library to help you test your module in an end-to-end way. Here's the workflow to adopt with it:
722
-
723
- 1. Create a Nuxt application to be used as a "fixture" inside `test/fixtures/*`
724
- 2. Setup Nuxt with this fixture inside your test file
725
- 3. Interact with the fixture using utilities from `@nuxt/test-utils` (e.g. fetching a page)
726
- 4. Perform checks related to this fixture (e.g. "HTML contains ...")
727
- 5. Repeat
728
-
729
- In practice, the fixture:
730
-
731
- ```ts [test/fixtures/ssr/nuxt.config.ts]
732
- // 1. Create a Nuxt application to be used as a "fixture"
733
- import MyModule from '../../../src/module'
734
-
735
- export default defineNuxtConfig({
736
- ssr: true,
737
- modules: [
738
- MyModule,
739
- ],
740
- })
741
- ```
742
-
743
- And its test:
744
-
745
- ```ts [test/rendering.ts]
746
- import { describe, expect, it } from 'vitest'
747
- import { fileURLToPath } from 'node:url'
748
- import { $fetch, setup } from '@nuxt/test-utils/e2e'
749
-
750
- describe('ssr', async () => {
751
- // 2. Setup Nuxt with this fixture inside your test file
752
- await setup({
753
- rootDir: fileURLToPath(new URL('./fixtures/ssr', import.meta.url)),
754
- })
755
-
756
- it('renders the index page', async () => {
757
- // 3. Interact with the fixture using utilities from `@nuxt/test-utils`
758
- const html = await $fetch('/')
759
-
760
- // 4. Perform checks related to this fixture
761
- expect(html).toContain('<div>ssr</div>')
762
- })
763
- })
764
-
765
- // 5. Repeat
766
- describe('csr', async () => { /* ... */ })
767
- ```
768
-
769
- ::tip
770
- An example of such a workflow is available on [the module starter](https://github.com/nuxt/starter/blob/module/test/basic.test.ts).
771
- ::
772
-
773
- #### Manual QA With Playground and Externally
774
-
775
- Having a playground Nuxt application to test your module when developing it is really useful. [The module starter integrates one for that purpose](/docs/4.x/guide/going-further/modules#how-to-develop).
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"`.
778
-
779
- After that, you should be able to reference `my-module` like in any regular project.
780
-
781
- ### Best Practices
782
-
783
- With great power comes great responsibility. While modules are powerful, here are some best practices to keep in mind while authoring modules to keep applications performant and developer experience great.
784
-
785
- #### Async Modules
786
-
787
- As we've seen, Nuxt Modules can be asynchronous. For example, you may want to develop a module that needs fetching some API or calling an async function.
788
-
789
- However, be careful with asynchronous behaviors as Nuxt will wait for your module to setup before going to the next module and starting the development server, build process, etc. Prefer deferring time-consuming logic to Nuxt hooks.
790
-
791
- ::warning
792
- If your module takes more than **1 second** to setup, Nuxt will emit a warning about it.
793
- ::
794
-
795
- #### Always Prefix Exposed Interfaces
796
-
797
- Nuxt Modules should provide an explicit prefix for any exposed configuration, plugin, API, composable, or component to avoid conflict with other modules and internals.
798
-
799
- Ideally, you should prefix them with your module's name (e.g. if your module is called `nuxt-foo`, expose `<FooButton>` and `useFooBar()` and **not** `<Button>` and `useBar()`).
800
-
801
- #### Use Lifecycle Hooks for One-Time Setup
802
-
803
- When your module needs to perform one-time setup tasks (like generating configuration files, setting up databases, or installing dependencies), use lifecycle hooks instead of running the logic in your main `setup` function.
804
-
805
- ```ts
806
- import { addServerHandler, defineNuxtModule } from 'nuxt/kit'
807
- import semver from 'semver'
808
-
809
- export default defineNuxtModule({
810
- meta: {
811
- name: 'my-database-module',
812
- version: '1.0.0',
813
- },
814
- async onInstall (nuxt) {
815
- // One-time setup: create database schema, generate config files, etc.
816
- await generateDatabaseConfig(nuxt.options.rootDir)
817
- },
818
- async onUpgrade (options, nuxt, previousVersion) {
819
- // Handle version-specific migrations
820
- if (semver.lt(previousVersion, '1.0.0')) {
821
- await migrateLegacyData()
822
- }
823
- },
824
- setup (options, nuxt) {
825
- // Regular setup logic that runs on every build
826
- addServerHandler({ /* ... */ })
827
- },
828
- })
829
- ```
830
-
831
- This pattern prevents unnecessary work on every build and provides a better developer experience. See the [lifecycle hooks documentation](/docs/4.x/api/kit/modules#using-lifecycle-hooks-for-module-installation-and-upgrade) for more details.
832
-
833
- #### Be TypeScript Friendly
834
-
835
- Nuxt has first-class TypeScript integration for the best developer experience.
836
-
837
- Exposing types and using TypeScript to develop modules benefits users even when not using TypeScript directly.
838
-
839
- #### Avoid CommonJS Syntax
840
-
841
- Nuxt relies on native ESM. Please read [Native ES Modules](/docs/4.x/guide/concepts/esm) for more information.
842
-
843
- #### Document Module Usage
844
-
845
- Consider documenting module usage in the readme file:
846
-
847
- - Why use this module?
848
- - How to use this module?
849
- - What does this module do?
850
-
851
- Linking to the integration website and documentation is always a good idea.
852
-
853
- #### Provide a StackBlitz Demo or Boilerplate
854
-
855
- It's a good practice to make a minimal reproduction with your module and [StackBlitz](https://nuxt.new/s/v4) that you add to your module readme.
856
-
857
- This not only provides potential users of your module a quick and easy way to experiment with the module but also an easy way for them to build minimal reproductions they can send you when they encounter issues.
858
-
859
- #### Do Not Advertise With a Specific Nuxt Version
860
-
861
- Nuxt, Nuxt Kit, and other new toolings are made to have both forward and backward compatibility in mind.
862
-
863
- Please use "X for Nuxt" instead of "X for Nuxt 3" to avoid fragmentation in the ecosystem and prefer using `meta.compatibility` to set Nuxt version constraints.
864
-
865
- #### Stick With Starter Defaults
866
-
867
- The module starter comes with a default set of tools and configurations (e.g. ESLint configuration). If you plan on open-sourcing your module, sticking with those defaults ensures your module shares a consistent coding style with other [community modules](/modules) out there, making it easier for others to contribute.
868
-
869
- ## Ecosystem
870
-
871
- [Nuxt Module ecosystem](/modules) represents more than 15 million monthly NPM downloads and provides extended functionalities and integrations with all sort of tools. You can be part of this ecosystem!
872
-
873
- ::tip{icon="i-lucide-video" to="https://vueschool.io/lessons/exploring-nuxt-modules-ecosystem-and-module-types?friend=nuxt" target="_blank"}
874
- Watch Vue School video about Nuxt module types.
875
- ::
876
-
877
- ### Module Types
878
-
879
- **Official modules** are modules prefixed (scoped) with `@nuxt/` (e.g. [`@nuxt/content`](https://content.nuxtjs.org)). They are made and maintained actively by the Nuxt team. Like with the framework, contributions from the community are more than welcome to help make them better!
880
-
881
- **Community modules** are modules prefixed (scoped) with `@nuxtjs/` (e.g. [`@nuxtjs/tailwindcss`](https://tailwindcss.nuxtjs.org)). They are proven modules made and maintained by community members. Again, contributions are welcome from anyone.
882
-
883
- **Third-party and other community modules** are modules (often) prefixed with `nuxt-`. Anyone can make them, using this prefix allows these modules to be discoverable on npm. This is the best starting point to draft and try an idea!
884
-
885
- **Private or personal modules** are modules made for your own use case or company. They don't need to follow any naming rules to work with Nuxt and are often seen scoped under an npm organization (e.g. `@my-company/nuxt-auth`)
886
-
887
- ### Listing Your Community Module
888
-
889
- 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.
890
-
891
- ### Joining `nuxt-modules` and `@nuxtjs/`
892
-
893
- 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.
894
-
895
- If you have an already published and working module, and want to transfer it to `nuxt-modules`, [open an issue in nuxt/modules](https://github.com/nuxt/modules/issues/new).
896
-
897
- By joining `nuxt-modules` we can rename your community module under the `@nuxtjs/` scope and provide a subdomain (e.g. `my-module.nuxtjs.org`) for its documentation.
898
-
899
- <!-- ## Module Internals
900
-
901
- Maybe just a quick section touching on "how modules work" under the hood, priority, etc. -->