feature-sliced/steiger

Universal file structure and project architecture linter

422

stars

222

commits

TypeScript

primary language

Sep 8, 2026

updated

www.npmjs.com/package/steiger
architecture
folders
imports
linter
naming-conventions

README

Steiger

NPM Version

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.

Features

Installation

npm i -D steiger

# If you want to check compliance to Feature-Sliced Design, also install this:
npm i -D @feature-sliced/steiger-plugin

Usage

npx steiger ./src

To run in watch mode, add -w/--watch to the command:

npx steiger ./src --watch

Configuration

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.

Example

// ./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',
      },
    },
  ])

You can see more examples here

Migration from 0.4.0

Version 0.5.0 introduced a new config file format. Follow the instructions to migrate your config file.

Rules

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.

RuleDescription
fsd/ambiguous-slice-namesForbid slice names that that match some segment’s name in the Shared layer.
fsd/excessive-slicingForbid having too many ungrouped slices or too many slices in a group.
fsd/forbidden-importsForbid imports from higher layers and cross-imports between slices on the same layer.
fsd/no-cross-imports[disabled] Forbid cross-imports between slices on the same layer.
fsd/no-higher-level-imports[disabled] Forbid imports from higher layers.
fsd/inconsistent-namingEnsure that all entities are named consistently in terms of pluralization.
fsd/insignificant-sliceDetect slices that have just one reference or no references to them at all.
fsd/no-layer-public-apiForbid index files on the layer level.
fsd/no-public-api-sidestepForbid going around the public API of a slice to import directly from an internal module in a slice.
fsd/no-reserved-folder-namesForbid subfolders in segments that have the same name as other conventional segments.
fsd/no-segmentless-slicesForbid slices that don't have any segments.
fsd/no-segments-on-sliced-layersForbid segments (like ui, lib, api ...) that appear directly in sliced layer folders (entities, features, ...)
fsd/no-ui-in-appForbid having the ui segment on the App layer.
fsd/public-apiRequire slices (and segments on sliceless layers like Shared) to have a public API definition.
fsd/repetitive-namingEnsure that all entities are named consistently in terms of pluralization.
fsd/segments-by-purposeDiscourage the use of segment names that group code by its essence, and instead encourage grouping by purpose
fsd/shared-lib-groupingForbid having too many ungrouped modules in shared/lib.
fsd/typo-in-layer-nameEnsure that all layers are named without any typos.
fsd/no-processesDiscourage the use of the deprecated Processes layer.
fsd/import-locality[disabled] Require that imports from the same slice be relative and imports from one slice to another be absolute.

Contribution

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

Contributors

illright

159 commits

daniilsapa

16 commits

unordinarity

15 commits

Solant

15 commits

feature-sliced/steiger

Universal file structure and project architecture linter

422

stars

222

commits

TypeScript

primary language

Sep 8, 2026

updated

www.npmjs.com/package/steiger
architecture
folders
imports
linter
naming-conventions

README

Steiger

NPM Version

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.

Features

Installation

npm i -D steiger

# If you want to check compliance to Feature-Sliced Design, also install this:
npm i -D @feature-sliced/steiger-plugin

Usage

npx steiger ./src

To run in watch mode, add -w/--watch to the command:

npx steiger ./src --watch

Configuration

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.

Example

// ./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',
      },
    },
  ])

You can see more examples here

Migration from 0.4.0

Version 0.5.0 introduced a new config file format. Follow the instructions to migrate your config file.

Rules

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.

RuleDescription
fsd/ambiguous-slice-namesForbid slice names that that match some segment’s name in the Shared layer.
fsd/excessive-slicingForbid having too many ungrouped slices or too many slices in a group.
fsd/forbidden-importsForbid imports from higher layers and cross-imports between slices on the same layer.
fsd/no-cross-imports[disabled] Forbid cross-imports between slices on the same layer.
fsd/no-higher-level-imports[disabled] Forbid imports from higher layers.
fsd/inconsistent-namingEnsure that all entities are named consistently in terms of pluralization.
fsd/insignificant-sliceDetect slices that have just one reference or no references to them at all.
fsd/no-layer-public-apiForbid index files on the layer level.
fsd/no-public-api-sidestepForbid going around the public API of a slice to import directly from an internal module in a slice.
fsd/no-reserved-folder-namesForbid subfolders in segments that have the same name as other conventional segments.
fsd/no-segmentless-slicesForbid slices that don't have any segments.
fsd/no-segments-on-sliced-layersForbid segments (like ui, lib, api ...) that appear directly in sliced layer folders (entities, features, ...)
fsd/no-ui-in-appForbid having the ui segment on the App layer.
fsd/public-apiRequire slices (and segments on sliceless layers like Shared) to have a public API definition.
fsd/repetitive-namingEnsure that all entities are named consistently in terms of pluralization.
fsd/segments-by-purposeDiscourage the use of segment names that group code by its essence, and instead encourage grouping by purpose
fsd/shared-lib-groupingForbid having too many ungrouped modules in shared/lib.
fsd/typo-in-layer-nameEnsure that all layers are named without any typos.
fsd/no-processesDiscourage the use of the deprecated Processes layer.
fsd/import-locality[disabled] Require that imports from the same slice be relative and imports from one slice to another be absolute.

Contribution

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

Contributors

illright

159 commits

daniilsapa

16 commits

unordinarity

15 commits

Solant

15 commits

Languages

TypeScript

95.4%

JavaScript

4.6%