A Nuxt 3 module for Feature-Sliced Design support.
- Defines path aliases for all FSD layers (compatible with Nuxt 4 "app" directory structure)
- Redefines
layouts
directory to be<srcDir>/app/layouts
segment andpages
to<srcDir>/app/routes
segment - Registers auto-imports for code and components in all your slices (respects
imports.autoImport
config) - Prevents cross-imports from higher layers
Install the module to your Nuxt application with one command:
npx nuxi module add nuxt-fsd
That's it! You can now use Feature-Sliced Design in your Nuxt app ✨
By default, the module uses the following layers and segments:
- Layers:
app
,pages
,widgets
,features
,entities
, andshared
- Segments:
ui
,model
,api
,lib
, andconfig
They are both configurable using the layers
and segments
options (respectively) in your nuxt.config.ts
:
export default defineNuxtConfig({
// ...
modules: ["nuxt-fsd"],
fsd: {
// An example changing the layers and segments
layers: ["app", "layouts", "screens", "features", "entities", "common"],
segments: ["components", "composables", "model", "api"],
},
});
All layer names are relative to srcDir
, which defaults to the root directory in Nuxt 3, and to the app
directory in Nuxt 4 (compatibility mode).
The first and last layers always correspond to app
and shared
(respectively) from the FSD standard, in that they do not have slices.
The module automatically defines path aliases for all layers. You can use them in your code like so:
import { useUser } from "features/user";
You can optionally add a prefix to the aliases using the aliasPrefix
option:
export default defineNuxtConfig({
// ...
modules: ["nuxt-fsd"],
fsd: {
aliasPrefix: '@',
},
});
and then use the aliases like so:
import { useUser } from "@features/user";
Auto-imported components are prefixed by the name of the layer and slice they belong to. App and Shared layers do not have slice. For example, shared/ui/button.vue
can be auto-imported as <SharedButton />
, and features/user/ui/avatar.vue
can be auto-imported as <FeaturesUserAvatar />
.
There is currently no way to configure the prefix for auto-imported components. Please open an issue if you need this feature.
If the preventCrossImports
option is set to true
(the default), the module will prevent cross-imports between layers. This means that you cannot import a slice from a higher layer in a lower layer. For example, you cannot import a slice from the features
layer in the entities
layer. You also cannot import from other slices in the same layer.
The module also respects the explicit public API for cross-imports
If you need more tailored configuration for this option (e.g. enable it only in dev or only print a warning), please open an issue.
- Auto-imports do not respect cross-import protection rules. It is advisable to keep imports explicit as much as possible.
- The dev server restarts when adding new slices/segments to register auto-imports and cross-import protection in them. With better coding from my side, this should not be necessary, but I will probably only handle it if it becomes problematic.
Local development
# Install dependencies
pnpm install
# Generate type stubs
pnpm run dev:prepare
# Develop with the playground
pnpm run dev
# Build the playground
pnpm run dev:build
# Run ESLint
pnpm run lint
# Release new version
pnpm run release