It supports ESLint 9+ and the new Flat Config system.
eslint-plugin-fsd-lint
is an ESLint plugin that enforces best practices for Feature-Sliced Design (FSD) architecture.
It is fully compatible with ESLint 9+ and follows the modern Flat Config format, ensuring seamless integration into modern JavaScript and TypeScript projects.
- Flat Config support: Fully compatible with ESLint 9+ and the new Flat Config system.
- Strict FSD compliance: Prevents architectural violations in feature-based project structures.
- Improves maintainability: Encourages clear module separation and dependency control.
- Ensures consistent code quality: Standardizes import patterns and best practices.
Feature-Sliced Design (FSD) is a modern architecture pattern that provides a structured approach to organizing frontend applications.
This plugin enforces key FSD principles such as proper layer separation, import restrictions, and dependency management,
helping developers build scalable and maintainable codebases.
You can install eslint-plugin-fsd-lint
via npm or pnpm:
npm install --save-dev eslint-plugin-fsd-lint
pnpm add -D eslint-plugin-fsd-lint
This plugin requires ESLint 9+ to work properly.
Make sure you have ESLint installed in your project:
npm install --save-dev eslint
π‘ Tip: If you're using a monorepo with multiple packages, install eslint-plugin-fsd-lint at the root level to share the configuration across all workspaces.
eslint-plugin-fsd-lint
is designed for ESLint 9+ and works seamlessly with the Flat Config system.
To use it in your project, add the following configuration to your eslint.config.mjs
:
import fsdPlugin from "eslint-plugin-fsd-lint";
export default [
{
plugins: {
fsd: fsdPlugin,
},
rules: {
"fsd/forbidden-imports": "error",
"fsd/no-relative-imports": "error",
"fsd/no-public-api-sidestep": "error",
"fsd/no-cross-slice-dependency": "error",
"fsd/no-ui-in-business-logic": "error",
"fsd/no-global-store-imports": "error",
"fsd/ordered-imports": "warn"
},
},
];
For a stricter FSD enforcement, you can extend the default rule set:
import fsdPlugin from "eslint-plugin-fsd-lint";
export default [
{
plugins: {
fsd: fsdPlugin,
},
rules: {
"fsd/forbidden-imports": "error",
"fsd/no-relative-imports": "error",
"fsd/no-public-api-sidestep": "error",
"fsd/no-cross-slice-dependency": "error",
"fsd/no-ui-in-business-logic": "error",
"fsd/no-global-store-imports": "error",
"fsd/ordered-imports": "error"
},
},
];
Hereβs how an FSD-compliant project might look:
src/
βββ app/
β βββ providers/
β βββ store.js
β βββ index.js
β
βββ processes/
β βββ auth/
β βββ onboarding/
β
βββ pages/
β βββ HomePage/
β βββ ProfilePage/
β
βββ widgets/
β βββ Navbar/
β βββ Sidebar/
β
βββ features/
β βββ login/
β βββ registration/
β
βββ entities/
β βββ user/
β βββ post/
β
βββ shared/
β βββ ui/
β βββ utils/
π‘ Tip: The plugin enforces correct layer imports according to FSD principles. For example, a feature can depend on entities and shared, but cannot directly import another feature.
This plugin provides a set of ESLint rules that enforce Feature-Sliced Design (FSD) best practices.
Each rule helps maintain a clear module structure, enforce import constraints, and prevent architectural violations.
Rule | Description |
---|---|
fsd/forbidden-imports | Prevents imports from higher layers and cross-imports between slices. |
fsd/no-relative-imports | Enforces alias usage instead of relative imports (../../shared/ui ). |
fsd/no-public-api-sidestep | Prevents direct imports from internal modules, enforcing public API usage. |
fsd/no-cross-slice-dependency | Disallows direct dependencies between feature slices. |
fsd/no-ui-in-business-logic | Prevents UI imports inside business logic layers (e.g., entities ). |
fsd/no-global-store-imports | Forbids direct imports of global state (store ). |
fsd/ordered-imports | Enforces import grouping by layer. |
Prevents imports from higher layers and cross-imports between slices.
β
Allowed: features
can import from entities
or shared
β Not Allowed: features
importing directly from app
// β Incorrect (feature importing from app)
import { config } from "../../app/config";
// β
Correct (feature importing from entities/shared)
import { getUser } from "../../entities/user";
import { formatCurrency } from "../../shared/utils";
Disallows relative imports and enforces alias usage.
β
Allowed: Using project-defined aliases
β Not Allowed: Using ../ or ./
// β Incorrect (relative import)
import { Button } from "../shared/ui/Button";
// β
Correct (alias import)
import { Button } from "@shared/ui/Button";
Prevents direct imports from internal modules of features, widgets, or entities.
β
Allowed: Importing from index.ts (public API)
β Not Allowed: Importing a featureβs internal file
// β Incorrect (direct internal import)
import { authSlice } from "../../features/auth/slice.ts";
// β
Correct (importing via public API)
import { authSlice } from "../../features/auth";
Prevents direct dependencies between feature slices.
β
Allowed: features should communicate via entities or shared
β Not Allowed: Direct imports between different features
// β Incorrect (feature importing from another feature)
import { processPayment } from "../../features/payment";
// β
Correct (using entities/shared as an intermediary)
import { PaymentEntity } from "../../entities/payment";
Prevents UI imports inside business logic layers (e.g., entities).
β
Allowed: UI should only be used inside widgets or pages
β Not Allowed: entities importing UI components
// β Incorrect (entity importing widget)
import { ProfileCard } from "../../widgets/ProfileCard";
// β
Correct (widget using entity data)
import { getUser } from "../../entities/user";
Forbids direct imports of global state (store).
β
Allowed: Using useStore or useSelector
β Not Allowed: Direct imports of the store
// β Incorrect (direct import of store)
import { store } from "../../app/store";
// β
Correct (using hooks)
import { useStore } from "zustand";
import { useSelector } from "react-redux";
Enforces import grouping by layer.
β
Allowed: Grouping imports by layer
β Not Allowed: Mixed import order
// β Incorrect (random import order)
import { processPayment } from "../features/payment";
import { getUser } from "../entities/user";
import { formatCurrency } from "../shared/utils";
import { loginUser } from "../features/auth";
import { Header } from "../widgets/Header";
import { useStore } from "../app/store";
// β
Correct (layered grouping)
import { useStore } from "../app/store"; // App
import { loginUser } from "../features/auth"; // Features
import { processPayment } from "../features/payment";
import { getUser } from "../entities/user"; // Entities
import { formatCurrency } from "../shared/utils"; // Shared
import { Header } from "../widgets/Header"; // Widgets
π‘ Tip: Use
npx eslint --fix
to automatically reorder imports according to FSD layers.
Certain rules in eslint-plugin-fsd-lint
support automatic fixing using ESLint's --fix
option.
This allows developers to quickly resolve violations without manual code adjustments.
The following rules can be automatically fixed:
Rule | Description |
---|---|
fsd/ordered-imports | Automatically sorts imports based on Feature-Sliced Design (FSD) layers. |
To apply automatic fixes to your project, simply run:
npx eslint --fix your-file.js
Or, to fix all files in your project:
npx eslint --fix .
β Before (fsd/ordered-imports violation)
import { processPayment } from "../features/payment";
import { getUser } from "../entities/user";
import { formatCurrency } from "../shared/utils";
import { loginUser } from "../features/auth";
import { Header } from "../widgets/Header";
import { useStore } from "../app/store";
β After (npx eslint --fix applied)
import { useStore } from "../app/store"; // App
import { loginUser } from "../features/auth"; // Features
import { processPayment } from "../features/payment";
import { getUser } from "../entities/user"; // Entities
import { formatCurrency } from "../shared/utils"; // Shared
import { Header } from "../widgets/Header"; // Widgets
π‘ Tip:
fsd/ordered-imports
ensures a clean and structured import order based on FSD layers.
We welcome contributions to improve eslint-plugin-fsd-lint
!
If you have an idea for a new rule or an improvement, feel free to submit a Pull Request.
Check out our contribution guide.
This project is licensed under the MIT License.
See the LICENSE file for details.