Guides: File and folder names: Check the style of file and folder names, permit a list of names, make a file export the name of its file, and make each folder hold its entry file. # File and folder names > Check the style of file and folder names, permit a list of names, make a file export the name of its file, and make each folder hold its entry file. This guide checks the names of files and folders, and which files a folder must hold. ## Before you start * Read [Getting started](/archangel/start/getting-started/). The example is a React app with components and features. Some of its names break the team’s conventions: * archangel.config.ts * src/ * components/ * Avatar.tsx * priceTag.tsx * features/ * cart/ * index.ts * ui/ * cart-row\.tsx * cart.container.tsx * cart.view\.tsx * orderHistory/ * ui/ * orders.view\.tsx ## Write the rules This config has five rules. The sections below tell you about each one. archangel.config.ts ```ts import { defineConfig } from '@enhance-eng/archangel'; export default defineConfig({ rules: ({ rule }) => [ rule('folder-names', { folders: 'src/**', mustBeNamed: 'kebab-case', because: 'One style for folders, so an import path is easy to guess.', examples: { rejected: ['src/features/UserProfile/index.ts'] }, }), rule('component-names', { files: 'src/components/**/*.tsx', mustBeNamed: 'PascalCase', because: 'A component file has the name of the component.', examples: { rejected: ['src/components/user-avatar.tsx'] }, }), rule('component-exports', { files: 'src/components/**/*.tsx', mustExport: '{FileName}', because: 'Code imports a component by the name of its file.', examples: { rejected: [{ 'src/components/Avatar.tsx': 'export function Picture() {}' }], }, }), rule('ui-file-names', { files: 'src/features/*/ui/**/*.tsx', mustBeNamed: ['*.view', '*.container'], because: 'A view only shows data. A container gets the data.', examples: { rejected: ['src/features/cart/ui/cart-list.tsx'] }, }), rule('feature-entry', { folders: 'src/features/*', mustContain: 'index.ts', because: 'Other code imports a feature through its index file.', examples: { rejected: ['src/features/search/ui/search.view.tsx'] }, }), ], }); ``` ### A style for folders `folder-names` uses `folders`, not `files`. The pattern `src/**` matches each folder inside `src`. `mustBeNamed: 'kebab-case'` gives the style. The styles are `kebab-case`, `camelCase`, `PascalCase`, `snake_case` and `SCREAMING_SNAKE_CASE`. ### A style for files `component-names` gives each component file a name in `PascalCase`. For a style, archangel reads the name up to the first dot. So `Avatar.tsx` has the name `Avatar`, and `Button.test.tsx` has the name `Button`. ### A list of permitted names `ui-file-names` permits two name patterns: `*.view` and `*.container`. A name pattern reads the full name of the file without its last extension, so `cart.view.tsx` has the full name `cart.view`. In a name pattern, `*` is any text or no text. * `*.view` matches `cart.view.tsx`. * `*.view` does not match `view.tsx`, whose full name is `view`. * `*.view` does not match `cart.view.extra.tsx`, whose full name is `cart.view.extra`. One entry of the list must match. A list can mix styles and name patterns. An empty list is a config error. ### A file exports the name of its file `component-exports` uses an export condition: `mustExport: '{FileName}'`. `{FileName}` is the name of the file in `PascalCase`. So `Avatar.tsx` must export `Avatar`. A re-export and `export *` count. The name of the file or its folder can go in a name pattern in each style: `{FileName}`, `{fileName}`, `{file-name}`, `{file_name}`, `{FILE_NAME}`, and the same spellings of `{FolderName}`. ### Each folder has its entry file `feature-entry` uses `mustContain`. Each folder that `src/features/*` matches must hold `index.ts`. To permit one file of a list, write a list: `mustContain: ['index.ts', 'index.tsx']`. ## Check the names 1. Check the app: Terminal ```ansi $ npx archangel check error[must-be-named]: the name of priceTag.tsx is priceTag, which is not PascalCase; in PascalCase the file is PriceTag.tsx --> src/components/priceTag.tsx = help: name it PriceTag.tsx = note: rule: component-names = note: because: A component file has the name of the component. error[must-be-named]: the full name of cart-row.tsx is cart-row, and it must be *.view or *.container --> src/features/cart/ui/cart-row.tsx = help: rename the file so that its name without the extension is *.view or *.container = note: rule: ui-file-names = note: because: A view only shows data. A container gets the data. error[must-contain]: the folder src/features/orderHistory has no file that matches index.ts --> src/features/orderHistory = help: add src/features/orderHistory/index.ts = note: rule: feature-entry = note: because: Other code imports a feature through its index file. error[must-be-named]: the folder src/features/orderHistory is not kebab-case; in kebab-case it is src/features/order-history --> src/features/orderHistory = help: name it src/features/order-history = note: rule: folder-names = note: because: One style for folders, so an import path is easy to guess. checked 8 files and 4 imports: 4 problems For what a code means, run `archangel docs must-be-named` or `archangel docs must-contain`. ``` Each error says what is wrong and gives the correct name: * `priceTag.tsx` is not in `PascalCase`. * `cart-row.tsx` matches neither `*.view` nor `*.container`. * `src/features/orderHistory` has no `index.ts`. * `src/features/orderHistory` is not in `kebab-case`. 2. Run the examples: Terminal ```ansi $ npx archangel test pass folder-names rejected #1 src/features/UserProfile/index.ts pass component-names rejected #1 src/components/user-avatar.tsx pass component-exports rejected #1 src/components/Avatar.tsx pass ui-file-names rejected #1 src/features/cart/ui/cart-list.tsx pass feature-entry rejected #1 src/features/search/ui/search.view.tsx 5 examples, none failed; 0 rules without a rejected example ``` An example sees your repository Archangel lays the files of an example over the files of your repository. So the example of `feature-entry` uses a new feature, `search`. An example in `src/features/cart` would also see the real `src/features/cart/index.ts`, and the rule would not refuse it. ## See what the rules cover Terminal ```ansi $ npx archangel rules folder-names archangel.config.ts:5 because: One style for folders, so an import path is easy to guess. folders in src/** must have names in kebab-case 6 folders · 1 problem component-names archangel.config.ts:12 because: A component file has the name of the component. files in src/components/**/*.tsx must have names in PascalCase 2 files · 1 problem component-exports archangel.config.ts:19 because: Code imports a component by the name of its file. files in src/components/**/*.tsx must export a name that matches {FileName} 2 files · 0 problems ui-file-names archangel.config.ts:28 because: A view only shows data. A container gets the data. files in src/features/*/ui/**/*.tsx must have full names that match *.view or *.container 4 files · 1 problem feature-entry archangel.config.ts:35 because: Other code imports a feature through its index file. each folder in src/features/* must have a file that matches index.ts 2 folders · 1 problem Files that no rule judges: 1 src/features/cart/index.ts Imports between repository files that no rule judges: 3 src/features/cart/index.ts:1 imports src/features/cart/ui/cart.container.tsx src/features/cart/ui/cart.container.tsx:1 imports src/features/cart/ui/cart.view.tsx src/features/cart/ui/cart.view.tsx:1 imports src/features/cart/ui/cart-row.tsx Outside packages that no rule names: none. ``` The end of the output lists one file and three imports that no rule judges. Name rules judge files, not imports. To check the imports too, add a table. ## What archangel does not check * Archangel has no rule for the first or the last character of a name, for example a name that starts with `_`. * Archangel does not check the names inside a file, such as names of functions. `mustExport` and `mayNotExport` check only exported names. ## Next steps * [Conditions](/archangel/reference/conditions/) lists each structure and export condition. * [Migrate from eslint-plugin-check-file](/archangel/guides/from-eslint-plugin-check-file/).