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.