@noctcore/eslint-plugin-architecture
Folder-per-component, barrels and feature boundaries, anchored on a configurable directory.
What it solves
Section titled “What it solves”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.
What it will yell at you about
Section titled “What it will yell at you about”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 and configure
Section titled “Install and configure”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.jsimport 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.
| Rule | What it reports | Preset | Fix | Types |
|---|---|---|---|---|
barrel-purity | A barrel (index.ts / index.tsx) must contain only re-exports — never local declarations, side effects, or default-exported values. | error | ||
colocated-test-required | A source file matching an include glob must have a colocated *.test.* / *.spec.* sibling on disk. | off | ||
component-folder-structure | A 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-export | A file's basename must match its primary export (a default export, or the sole named export). | error | suggestion | |
index-must-reexport-default | A component folder's index.ts must re-export the component default (export { default as <Name> } from './<Name>'). | error | ||
max-import-depth | A relative import may not climb more than max parent levels (default 3). Autofixed to a path alias when one is configured. | error | autofix | |
no-cross-feature-imports | A 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-module | Require 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).