Universal file structure and project architecture linter.
Note
The project is in beta and in active development. Some APIs may change.
Note
Version 0.5.0 introduced a new config file format. We have a codemod to automatically update your config, see the migration guide.
- Built-in set of rules to validate adherence to Feature-Sliced Design
- Watch mode
- Rule configurability
npm i -D steiger
npx steiger ./src
To run in watch mode, add -w
/--watch
to the command:
npx steiger ./src --watch
Steiger is zero-config! If you don't want to disable certain rules, you can safely skip this section.
Steiger is configurable via cosmiconfig
. That means that you can create a steiger.config.ts
or steiger.config.js
file in the root of your project to configure the rules. Import { defineConfig } from "steiger"
to get autocompletion.
The config file shape is highly inspired by ESLint's config file, so if you have configured ESLint before, you'll find it easy to configure Steiger.
// ./steiger.config.js
import { defineConfig } from 'steiger'
import fsd from '@feature-sliced/steiger-plugin'
export default defineConfig([
...fsd.configs.recommended,
{
// disable the `public-api` rule for files in the Shared layer
files: ['./src/shared/**'],
rules: {
'fsd/public-api': 'off',
},
},
])
Tip
If you want Steiger to ignore certain files, add an object like this to the config array:
defineConfig([, /* … */ { ignores: ['**/__mocks__/**'] }])
Comprehensive showcase of the config file syntax
// ./steiger.config.ts
import { defineConfig } from 'steiger'
import fsd from '@feature-sliced/steiger-plugin'
export default defineConfig([
...fsd.configs.recommended,
{
// ignore all mock files for all rules
ignores: ['**/__mocks__/**'],
},
{
files: ['./src/shared/**'],
rules: {
// disable public-api rule for files in /shared folder
'fsd/public-api': 'off',
},
},
{
files: ['./src/widgets/**'],
ignores: ['**/discount-offers/**'],
rules: {
// disable no-segmentless-slices rule for all widgets except /discount-offers
'fsd/no-segmentless-slices': 'off',
},
},
])
Version 0.5.0 introduced a new config file format. Follow the instructions to migrate your config file.
Currently, Steiger is not extendable with more rules, though that will change in the near future. The built-in rules check for the project's adherence to Feature-Sliced Design.
Rule | Description |
---|---|
fsd/ambiguous-slice-names | Forbid slice names that that match some segment’s name in the Shared layer. |
fsd/excessive-slicing | Forbid having too many ungrouped slices or too many slices in a group. |
fsd/forbidden-imports | Forbid imports from higher layers and cross-imports between slices on the same layer. |
fsd/inconsistent-naming | Ensure that all entities are named consistently in terms of pluralization. |
fsd/insignificant-slice | Detect slices that have just one reference or no references to them at all. |
fsd/no-layer-public-api | Forbid index files on the layer level. |
fsd/no-public-api-sidestep | Forbid going around the public API of a slice to import directly from an internal module in a slice. |
fsd/no-reserved-folder-names | Forbid subfolders in segments that have the same name as other conventional segments. |
fsd/no-segmentless-slices | Forbid slices that don't have any segments. |
fsd/no-segments-on-sliced-layers | Forbid segments (like ui, lib, api ...) that appear directly in sliced layer folders (entities, features, ...) |
fsd/no-ui-in-app | Forbid having the ui segment on the App layer. |
fsd/public-api | Require slices (and segments on sliceless layers like Shared) to have a public API definition. |
fsd/repetitive-naming | Ensure that all entities are named consistently in terms of pluralization. |
fsd/segments-by-purpose | Discourage the use of segment names that group code by its essence, and instead encourage grouping by purpose |
fsd/shared-lib-grouping | Forbid having too many ungrouped modules in shared/lib . |
fsd/typo-in-layer-name | Ensure that all layers are named without any typos. |
fsd/no-processes | Discourage the use of the deprecated Processes layer. |
Feel free to report an issue or open a discussion. Ensure you read our Code of Conduct first though :)
To get started with the codebase, see our Contributing guide.
Project licensed under MIT License. Here's what it means