naming-files
Skill4 starsChanged 8 days agoMITView on GitHub
Use when creating or renaming a file or folder in a front-end source tree — case, role suffix (`.store`, `.endpoint`, `.events`, `.meta`), stores, classes and singletons, DTOs, `index.ts` barrels, `helpers`, a regex constant, an acronym, or a hyphen in a name.
In this repository12 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- keeping-symbols-localSkill
- release-dailySkill
- structuring-componentsSkill
- structuring-script-setupSkill
- structuring-utility-filesSkill
- writing-commentsSkill
- writing-composablesSkill
- writing-functions-and-classesSkill
- writing-testsSkill
- writing-typesSkill
The file
Files
Naming Files
The rules cover an app's front-end source tree, with paths relative to its source root; a backend or another package names its files by its own architecture.
Component folders and the ui/ layout: structuring-components. One function per file in utils/: structuring-utility-files. Where a test file sits: writing-tests.
Rules
- Case follows the kind of content. A component or a class is PascalCase, and so is a file that exports a ready instance of a class — it is named by the class without its underscore, and the instance is what callers import. Here the class is
_<Name>and the instance<Name>, both in<Name>.ts:api/Storage.tsholdsclass _Storageandexport const Storage = new _Storage(...), and callers importStorage. Everything else is camelCase. The case of the exported identifier does not matter: a table of strings exported asErrorMessagesgoes inerrorMessages.ts. Never kebab-case.ApiClient.ts;utils/common/EventEmitter.ts;utils/auth/withToken.ts;ui/base/BaseInput.vue. - Name by the main export; several equal exports → name by the topic.
composables/useTheme.ts;constants/storageKeys.ts;utils/common/typeGuards.ts. Composables (Vue): the group's name is not repeated in the composable's name when the rest is clear on its own —composables/websocket/useSubscription.ts; keep the prefix when it carries the meaning —composables/widgets/useWidgetState.ts. The prefix itself (useXxx,watchXxx,xxxRef) is chosen by writing-composables. - Role suffix — a closed list:
.store,.endpoint,.schema,.worker,.test,.d,.events,.meta. The part before the dot follows rules 1–2, and suffixes stack:<name>.store.test.ts.stores/session/session.store.ts,login.endpoint.ts,email.schema.ts,parser.worker.ts,env.d.ts,locales/en-US.meta.ts,useTheme.test.ts. Event-name constants areconstants/events/<name>.events.ts: the files are found by searching for the suffix, yet they lie together in one folder. - Identifier tied to the file name:
useXStore↔x.store.ts;xEndpoint↔x.endpoint.ts;xSchema↔x.schema.ts; directivevX↔vX.ts(Vue);useXModal↔XModal/(Vue).useSessionStore↔stores/session/session.store.ts,loginEndpoint↔login.endpoint.ts,directives/vFocusOnMount.ts,useConfirmModal↔ConfirmModal/. - Folders outside
ui/are kebab-case, usually one word.api/rest-client/,constants/validation-schemas/. helpersis not a name for a file or a folder, inrouter/too: router utilities live inrouter/utils/. What to do with an existing one: structuring-utility-files.- The kind word goes last in a component or class name, everywhere — in groups, in
{fragments}, for classes.ConfirmModal,PasswordInput,SessionStore,ApiRestError. - No truncated words; an acronym is written as a word.
IconButton, notIconBtn;QrCode, notQRCode;CsvExporter;ApiRestError, notApiRESTError;decodeJwt, notdecodeJWT. index.tsis the door of a module: a component folder, a store, anapimodule, the router, a class split over several files.stores/session/index.ts,api/rest-client/index.ts. A grouping — aui/group, a domain folder ofutils/,composables/,constants/,types/,directives/,lib/— has no barrel.A store is always a folder, one folder one store:
stores/<name>/<name>.store.tsplus anindex.tsthat re-exports by name:export {useSessionStore} from "./session.store". A second store is a second folder, never a second file in the first. The store file defines it asexport const useXStore = defineStore("x", () => {…})— no default export; the store id matches the folder and never changes once released. What else lies in the folder, only when the store has it:composables/— composables only this store uses; the door does not re-export them.utils/— the store's functions; where a function lives and how far it is exported: structuring-utility-files and keeping-symbols-local.constants.ts— the store's constants.types.ts— the types of the store's state and of what it works on; a type other code needs too goes totypes/(writing-types).- the tests of the store and of the files above, placed as writing-tests says.
The door re-exports the store and any name from the folder that other code needs. How the store releases what it subscribes to: writing-composables.
- A regex is a constant in
constants/regex.ts, named<WHAT>_REGEX, and a caller imports it from there; no file keeps its own regex literal. - One file per
Errorsubclass, named by the class, in a folder of errors grouped by domain:errors/auth/SessionExpiredError.ts. - Shared data and environment. Shared contracts go in
types/<domain>.ts, static catalogs and content inconstants/<domain>/, loaders and transforms inutils/<domain>/— no feature silo at the source root. Application metadata is static data, not an export borrowed from a page. Build-environment values are read through one module,constants/env.ts. - DTO, when the app has an API layer:
<Name>Dto.ts, a class with astatic fromEntrythat normalizes an endpoint response, and astatic to<Name>Body(params)for every request body the endpoint sends, so an endpoint never builds a body inline:UserDto.fromEntry,UserDto.toUpdateBody. A DTO never imports a type from an endpoint file: it declares a local, unexported input type for each mapper, with only the fields that mapper reads, and the endpoint's params satisfy it structurally.
Exceptions
assets/**— the naming rules do not apply: inicons/the file name is the sprite id, andstyles/keeps its names.- Locale files are named by their locale tag:
locales/en-US.json,locales/en-US.meta.ts. - Generated files keep the names and paths their generator gives them.
- A
constants/folder whoseindex.tscomposes the files beside it into one value (a map of form schemas built from the field schemas next to it) is a module, and thatindex.tsis its door, not a barrel.
Common mistakes
- Copying a hyphenated,
Btn-style or otherwise rule-breaking name from a neighbouring file. - camelCase for a class, or for a file that exports an instance of a class.
- PascalCase for a module of functions or constants:
constants/messages/validationMessages.ts, notValidationMessages.ts. - A suffix that is not on the list:
user.endpoints.test.ts. - A second store dropped next to the first inside one folder, or a store hidden in a component folder.
- A regex literal written inline instead of imported from
constants/regex.ts.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

