Skip to content

@noctcore/eslint-plugin-architecture

Folder-per-component, barrels and feature boundaries, anchored on a configurable directory.

Folder structure that nobody enforces decays one convenient shortcut at a time: a barrel that grows a helper function, a component folder missing its test, a feature importing another feature’s internals, a relative import that climbs five parents. These rules make the layout a checked property of the codebase instead of a paragraph in a contributing guide.

It will yell at you about file layout, and several rules read the file system: component-folder-structure wants every <Name>/<Name>.tsx to ship its full sibling set, colocated-test-required wants a test next to each source file it covers. Run ESLint on real file paths, not virtual sources. Every rule anchors on a directory segment (default components) instead of an absolute path, so it behaves the same from the repo root or a package. It is a bad fit for a codebase organised by technical layer (hooks/, components/, utils/ at the top) rather than by feature, and for a small app where a component folder with five siblings is ceremony. colocated-test-required and single-semantic-module ship off because they are opinions many good codebases do not share.

Install
npm install --save-dev @noctcore/eslint-plugin-architecture @typescript-eslint/parser
# or: bun add -D / pnpm add -D @noctcore/eslint-plugin-architecture @typescript-eslint/parser
eslint.config.js
// eslint.config.js
import tsParser from '@typescript-eslint/parser';
import architecture from '@noctcore/eslint-plugin-architecture';
export default [
{
...architecture.configs.recommended,
files: ['**/*.{ts,tsx}'],
languageOptions: { parser: tsParser },
},
];
// Rules outside the preset are enabled one by one, e.g.
// { rules: { 'noctcore-architecture/single-semantic-module': 'error' } }

The recommended preset enables 6 of 8 rules.

Each rule links to its page, with the options it takes and Incorrect and Correct examples. A good first read is no-cross-feature-imports.

RuleWhat it reportsPresetFixTypes
barrel-purityA barrel (index.ts / index.tsx) must contain only re-exports — never local declarations, side effects, or default-exported values.error
colocated-test-requiredA source file matching an include glob must have a colocated *.test.* / *.spec.* sibling on disk.off
component-folder-structureA component <Name>/<Name>.tsx under <componentRoot>/<feature>/... must have its sibling set (.hooks.ts, .types.ts, .stories.tsx, .test.tsx, index.ts) present on disk.error
filename-matches-exportA file's basename must match its primary export (a default export, or the sole named export).errorsuggestion
index-must-reexport-defaultA component folder's index.ts must re-export the component default (export { default as <Name> } from './<Name>').error
max-import-depthA relative import may not climb more than max parent levels (default 3). Autofixed to a path alias when one is configured.errorautofix
no-cross-feature-importsA file in one feature may not import runtime code from another feature. Move shared code to a shared module or a shared feature.error
single-semantic-moduleRequire each module to export only one semantic concern (types, constants, functions, classes, components, hooks, schemas or enums).off

Preset: severity in configs.recommended; off means the preset registers the rule switched off, not listed means it leaves the rule out; both are opt-in, so you turn the rule on yourself. Fix: whether the rule ships an autofix or an editor suggestion. Types: whether the rule needs a type-checked program (parserOptions.projectService).