ESLint plugin for Feature-Sliced Design (FSD) architecture.
pnpm add -D @yh-kim/eslint-plugin-fsd
# or
npm install --save-dev @yh-kim/eslint-plugin-fsd
# or
yarn add --dev @yh-kim/eslint-plugin-fsd// eslint.config.js
import fsdPlugin from '@yh-kim/eslint-plugin-fsd';
export default [
// Use recommended config
fsdPlugin.configs['flat/recommended'],
// Or configure manually
{
plugins: {
fsd: fsdPlugin,
},
rules: {
'fsd/no-cross-layer-import': 'error',
},
},
];Add to your .eslintrc configuration file:
{
"plugins": ["@yh-kim/fsd"],
"extends": ["plugin:@yh-kim/fsd/recommended"]
}Or configure rules individually:
{
"plugins": ["@yh-kim/fsd"],
"rules": {
"@yh-kim/fsd/no-cross-layer-import": "error"
}
}{
"plugins": ["@yh-kim/fsd"],
"rules": {
"@yh-kim/fsd/no-cross-layer-import": [
"error",
{
"alias": "@",
"ignorePatterns": ["\\.test\\.", "\\.spec\\."]
}
]
}
}fsdPlugin.configs['flat/recommended']- Recommended rules for FSD architecturefsdPlugin.configs['flat/all']- All available rules enabled
plugin:@yh-kim/fsd/recommended- Recommended rules for FSD architectureplugin:@yh-kim/fsd/all- All available rules enabled
This plugin expects the following project structure:
src/
├── app/
│ ├── App.tsx
│ └── providers/
├── pages/
│ ├── home/
│ └── profile/
├── widgets/
│ ├── header/
│ │ ├── model/
│ │ ├── ui/
│ │ └── index.ts
│ └── sidebar/
├── features/
│ ├── auth/
│ │ ├── model/
│ │ ├── ui/
│ │ ├── api/
│ │ └── index.ts
│ └── comments/
├── entities/
│ ├── user/
│ │ ├── model/
│ │ ├── ui/
│ │ ├── api/
│ │ ├── lib/
│ │ └── index.ts
│ └── post/
└── shared/
├── ui/
├── lib/
└── api/
Each slice (e.g., entities/user, features/auth) should only contain these segment folders:
model/- Business logic, stores, typesui/- UI componentsapi/- API calls and data fetchinglib/- Slice-specific utility functionsconfig/- Configuration files and constants
Example - Valid Structure:
entities/user/
├── model/ ✅ Allowed
├── ui/ ✅ Allowed
├── api/ ✅ Allowed
├── lib/ ✅ Allowed
├── config/ ✅ Allowed
└── index.ts ✅ Root file
entities/user/
├── utils/ ❌ Invalid segment!
├── helpers/ ❌ Invalid segment!
└── constants/ ❌ Invalid segment! (use config/)
| Rule | Description | Recommended | Level |
|---|---|---|---|
| no-cross-layer-import | Enforces FSD layer hierarchy (upper layers can only import from lower layers) | ✅ | error |
| Rule | Description | Recommended | Level |
|---|---|---|---|
| enforce-segment-naming | Enforces valid segment folders within slices (checks file system structure, not imports) | ✅ | error |
This plugin enforces the following FSD layer hierarchy:
app (Top - Application initialization)
↓
pages (Page routes)
↓
widgets (Independent UI blocks)
↓
features (Business features)
↓
entities (Business entities)
↓
shared (Bottom - Shared utilities)
Core Principle: Each layer can only import from layers below it in the hierarchy.
// ✅ Upper layer importing lower layer
import { HomePage } from '@/pages/home'; // app → pages
import { Header } from '@/widgets/header'; // pages → widgets
import { LoginForm } from '@/features/auth'; // widgets → features
import { User } from '@/entities/user'; // features → entities
import { Button } from '@/shared/ui'; // entities → shared
// ✅ Same layer imports
import { UserCard } from './UserCard';
// ✅ External packages
import React from 'react';// ❌ Lower layer importing upper layer (violates hierarchy)
import { config } from '@/app/config'; // pages → app ✗
import { HomePage } from '@/pages/home'; // widgets → pages ✗
import { Sidebar } from '@/widgets/sidebar'; // features → widgets ✗
import { login } from '@/features/auth'; // entities → features ✗
import { User } from '@/entities/user'; // shared → entities ✗- 🏗️ Architecture Enforcement: Automatically enforce FSD architectural principles
- 🔒 Prevent Circular Dependencies: Catch dependency violations before they become problems
- 📚 Self-Documenting Code: Clear layer structure makes codebase easier to understand
- ⚡ Scalability: Maintain clean architecture as your project grows
- 🛡️ Type Safety: Works seamlessly with TypeScript projects
See CONTRIBUTING.md for details on how to contribute.
MIT