Handle Async Setup
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. 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.Prefix Your Exports
Nuxt modules should provide an explicit prefix for any exposed configuration, plugin, API, composable, component, or server route to avoid conflicts with other modules, Nuxt internals, or user-defined code. Ideally, prefix them with your module’s name. For example, if your module is callednuxt-foo:
| Type | Avoid | Prefer |
|---|---|---|
| Components | <Button>, <Modal> | <FooButton>, <FooModal> |
| Composables | useData(), useModal() | useFooData(), useFooModal() |
| Server routes | /api/track, /api/data | /api/_foo/track, /api/_foo/data |
Server Routes
This is particularly important for server routes, where common paths like/api/auth, /api/login, or /api/user are very likely already used by the application.
Use a unique prefix based on your module name:
/api/_foo/...(using underscore prefix)/_foo/...(for non-API routes)
Use Lifecycle Hooks
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 mainsetup function.
Be TypeScript Friendly
Nuxt has first-class TypeScript integration for the best developer experience. Exposing types and using TypeScript to develop modules benefits users even when not using TypeScript directly.Provide Type Definitions
- Export TypeScript types for your module options
- Add type declarations for composables and utilities
- Augment Nuxt types when adding new configuration options
Use ESM Syntax
Nuxt relies on native ESM. Use modern ES module syntax in your modules:Document Your Module
Consider documenting module usage in the readme file:- Why use this module? - Explain the problem it solves
- How to use this module? - Provide clear installation and usage instructions
- What does this module do? - Describe the features and functionality
Documentation Structure
Your README should include:- Installation - How to install and configure the module
- Usage - Basic examples and common use cases
- Configuration - Available options and their defaults
- API Reference - Exported composables, components, and utilities
- Examples - Real-world usage scenarios
Provide a Demo
It’s a good practice to make a minimal reproduction with your module and StackBlitz that you add to your module readme. 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.Stay Version Agnostic
Nuxt, Nuxt Kit, and other new toolings are made to have both forward and backward compatibility in mind. Please use “X for Nuxt” instead of “X for Nuxt 3” to avoid fragmentation in the ecosystem and prefer usingmeta.compatibility to set Nuxt version constraints.
Follow Starter Conventions
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 out there, making it easier for others to contribute.Conventions Include
- ESLint - For code quality and consistency
- TypeScript - For type safety
- Vitest - For testing
- Conventional Commits - For changelog generation
Summary
By following these best practices, you’ll create modules that are:- Performant - Fast setup and minimal overhead
- Compatible - Works well with other modules and user code
- Maintainable - Easy to update and extend
- User-friendly - Well-documented and easy to use
Module Recipes
Learn practical patterns for module development