Guides: Migrate from Steiger: Replace Steiger with the fsd preset. Each Steiger rule has a rule of the same name, with examples, and the differences are listed. # Migrate from Steiger > Replace Steiger with the fsd preset. Each Steiger rule has a rule of the same name, with examples, and the differences are listed. Steiger is the linter of Feature-Sliced Design. Archangel’s `fsd` preset has a rule for each of Steiger’s 21 rules, with the same name and a link to Steiger’s page for it. A test in the archangel repository runs Steiger and the preset on the same repositories, and compares the files that each one reports. [Feature-Sliced Design](/archangel/guides/feature-sliced-design/) tells you how to use the preset. This page tells you how to move from Steiger. ## The config before steiger.config.ts ```ts import { defineConfig } from 'steiger'; import fsd from '@feature-sliced/steiger-plugin'; export default defineConfig([ ...fsd.configs.recommended, { rules: { 'fsd/insignificant-slice': 'off', }, }, ]); ``` ## The config after archangel.config.ts ```ts import { defineConfig, fsd } from '@enhance-eng/archangel'; export default defineConfig({ extends: [fsd({ root: 'src' })], off: ['fsd/insignificant-slice'], }); ``` | Steiger | archangel | | -------------------------------- | ------------------------------------------------------------------------------------------------- | | `...fsd.configs.recommended` | `extends: [fsd({ root: 'src' })]` | | All rules on | `fsd({ root: 'src', strict: true })` | | `'fsd/': 'off'` | `off: ['fsd/']` | | `'fsd/': 'warn'` | No equivalent. A rule is on or off. | | `ignores: [...]` | `ignore: [...]` in the config, in `.gitignore` syntax. It removes the files from the whole check. | | `files: [...]` with a rule `off` | Write a rule with the same name as the preset rule. Your rule replaces it. | | A second FSD root | A second `fsd({ root, name })` with its own `name`, for example `fsd-admin`. | ## Run it 1. Check the repository: Terminal ```ansi $ npx archangel check error[may-not-import]: src/features/login/ui/login-form.ts may not import "../../signup", because files in "features" may not import "all of (fsd/features, not src/features/*/@x/**)" in a different instance --> src/features/login/ui/login-form.ts:1:28 | 1 | import { signupLink } from '../../signup'; | ^^^^^^^^^^^^^^ remove the import, or move the code to files that may import it | = note: rule: fsd/forbidden-imports = note: reason: A module may import only from layers below its own, and a slice not from another slice of its layer, except through @x. = note: see: https://feature-sliced.github.io/steiger/rules/forbidden-imports checked 8 files and 8 imports: 1 problem fsd/shared matches nothing in this repository fsd/entities matches nothing in this repository fsd/widgets matches nothing in this repository fsd/processes matches nothing in this repository For what a code means, run `archangel docs may-not-import`. ``` The feature `login` imports the feature `signup`, so `fsd/forbidden-imports` refuses it. The lines that say “matches nothing” are parts of the preset with no files. A repository usually has only some layers, so these lines are not errors. 2. Run `npx archangel test`. It checks the examples of each preset rule in your repository, under the preset’s `root`, with your tsconfig. 3. Remove Steiger when the results are the same. ## The rules Each rule name has the prefix of the preset, `fsd/` by default. The rules that Steiger recommends are on by default. `strict: true` adds the four rules that Steiger has as options. | Steiger rule | archangel rule | On | | ---------------------------------- | ---------------------------------- | -------------- | | `fsd/forbidden-imports` | `fsd/forbidden-imports` | Default | | `fsd/no-public-api-sidestep` | `fsd/no-public-api-sidestep` | Default | | `fsd/public-api` | `fsd/public-api` | Default | | `fsd/no-layer-public-api` | `fsd/no-layer-public-api` | Default | | `fsd/no-reserved-folder-names` | `fsd/no-reserved-folder-names` | Default | | `fsd/no-segmentless-slices` | `fsd/no-segmentless-slices` | Default | | `fsd/no-segments-on-sliced-layers` | `fsd/no-segments-on-sliced-layers` | Default | | `fsd/no-ui-in-app` | `fsd/no-ui-in-app` | Default | | `fsd/segments-by-purpose` | `fsd/segments-by-purpose` | Default | | `fsd/no-processes` | `fsd/no-processes` | Default | | `fsd/typo-in-layer-name` | `fsd/typo-in-layer-name` | Default | | `fsd/ambiguous-slice-names` | `fsd/ambiguous-slice-names` | Default | | `fsd/inconsistent-naming` | `fsd/inconsistent-naming` | Default | | `fsd/insignificant-slice` | `fsd/insignificant-slice` | Default | | `fsd/repetitive-naming` | `fsd/repetitive-naming` | Default | | `fsd/excessive-slicing` | `fsd/excessive-slicing` | Default | | `fsd/shared-lib-grouping` | `fsd/shared-lib-grouping` | Default | | `fsd/no-higher-level-imports` | `fsd/no-higher-level-imports` | `strict: true` | | `fsd/no-cross-imports` | `fsd/no-cross-imports` | `strict: true` | | `fsd/import-locality` | `fsd/import-locality` | `strict: true` | | `fsd/no-wildcard-exports` | `fsd/no-wildcard-exports` | `strict: true` | The rules about imports and folders are built-in conditions of archangel. The seven rules about names and counts, from `typo-in-layer-name` to `shared-lib-grouping`, are conditions of the preset’s plugin, and they read the whole tree as Steiger does. ## Results that change These differences are on purpose. The test that compares the two tools names each one. * **A slice is any folder in a sliced layer.** The built-in rules take each folder directly in Entities, Features, Widgets or Pages as a slice, with or without segments. They do not know slice groups. Steiger finds a slice by the segments inside it. The plugin rules find slices and slice groups as Steiger does. * **Each folder in `shared/ui` and `shared/lib` needs an index file.** `fsd/public-api` asks for it even when the segment has an index file of its own. Steiger checks those folders only when the segment has none. * **A misspelt layer is reported beside the real one.** `fsd/typo-in-layer-name` reports `src/featurez` even when `src/features` exists. Steiger then reports nothing. * **A layer has its exact name.** The built-in rules take only a folder named exactly as a layer. Steiger also reads `1_shared` or `_app` as a layer. * **Code outside the layers is checked too.** `fsd/no-public-api-sidestep` checks imports from files outside the layers, such as tests. A deep import from a test is still a sidestep. Steiger reads only the files in the layers. * **A re-export is an import.** Each rule counts `export ... from` as an import, because a re-export loads the module. One tool for more rules Steiger checks Feature-Sliced Design only. With archangel, you can add your own tables and rules next to the preset, in the same config, and check them in one run.