> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackra.figentra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 0006 — Naming, exports and imports

> Accepted, amended by 0128, 0233 · 2026-10-19

> [!NOTE]
>
> Amended by [0233](/adr/0233-imports-use-subpath-aliases-only), decisions 4 and 5: cross-folder
> imports use `#` aliases only, and `../` is banned.

> [!NOTE]
>
> Amended by [0128](/adr/0128-code-conventions-enums-classes-components-and-kind-folders): enums,
> classes and component folders follow that ADR.

> [!NOTE]
>
> Amended 2026-10-21 (STA-219): decision 6 (`utils/`) is withdrawn and schema files take the
> `.schema.ts` suffix. See the amendment at the end of this page.

## Context

File names, how many things a file exports, how barrels look and how modules name each other are decided on the first
file or re-argued on the twentieth. Four earlier decisions covered these separately. They are one convention, and it is
frozen before packages are created in bulk, because a codemod over many packages costs far more than agreeing now.

## Decision

1. **Kebab-case for every file and directory under `src/`.** No PascalCase, camelCase or underscores.
2. **One exported declaration per file**, named for it, with a kind suffix where the kind is not a plain function:
   `token.class.ts`, `scope.enum.ts`, `class-provider.interface.ts`, `payment.error.ts`. Barrels are exempt.
3. **Barrels re-export and nothing else.** `index.ts` is the only barrel name; it names every symbol
   (`export type { Token } from "./token.class"`), never `export *`, so the public surface is readable without compiling.
4. **Relative specifiers carry no extension and no trailing `/index`.** Exempt: package specifiers, non-code assets
   (`.css`, `.svg`, `.json`), generated output, raw Node `.mjs` and `.cjs` scripts under `tools/`, and `packages/tooling/*`
   (loaded by plain Node, which needs full specifiers).
5. **Climbing imports use package subpath imports.** A member with a `src/` tree declares `imports` in `package.json`
   (`#core`, `#application/*`, ...). A relative specifier may stay in its folder or descend; it never climbs with `../`.
   The `imports` map is generated by a script, never hand-written.
6. **A helper used by a second file moves to `utils/<name>.util.ts`.** A single-use private helper stays where it is used.
7. **Conventions change by ADR only.** No package-local exceptions.

## Consequences

* A file's name tells the reader what it exports; a rename is a move.
* Wildcard barrels are not available, so adding a symbol is a visible diff in the barrel.
* Subpath imports need a bundler and Metro that resolve `package.json` `imports`; native builds are verified before the first native entry ships.

## Enforcement

* `typescript/consistent-type-imports` in the base oxlint preset (off only in the decorators preset, see [0005](/adr/0005-di-container-and-legacy-decorators)).
* Planned: a validator check for kebab-case names, one export per file and barrel shape; an import-specifier check (port basalt `tools/scripts/import-style.mjs`); an `imports` map drift check against the generator.

## Amendment 2026-10-21: no `utils/`; schema files are `*.schema.ts` (STA-219)

**Context.** Decision 6 put a helper used by a second file in `utils/<name>.util.ts`. ADR 0126 (decision 3) bans `utils/`
and `helpers/`, and the two cannot both stand. Schema files were also called `*.contract.ts` (the preview repository's
name), which collides with the `.contract` test tier of ADR 0182. The owner settled both on 2026-10-21.

**Decision.**

1. Decision 6 is withdrawn. There is no `utils/` folder and no `.util.ts` suffix, in any member.
2. **Helpers are placed by how many packages use them.**
   * A helper that a second **package** needs moves to `@stackra/support`, one subpath per concern.
   * A helper shared by two or more **files inside one package** lives in `internal/<name>.ts`. It is not exported from any
     barrel, and its test sits beside it in `internal/__tests__/`. The `internal/` folder is in the kind-folder list of
     [0130](/adr/0130-module-layout-by-semantic-kind) amendment 2026-10-21, decision 2.
   * A single-use helper stays in the file that uses it.
3. A schema file is `<name>.schema.ts` and carries one exported schema and its inferred type. `.contract` is not a file suffix.
   It names only the `.contract` test tier of [0182](/adr/0182-testing-strategy-v2-tiers-coverage-infrastructure-and-policies).

**Consequences.**

* `utils/` and `helpers/` are banned by ADR 0126 and this amendment; the validator's banned-folder list (`checkFileKinds`) carries both.
* A reviewer reads `.schema.ts` as data shape and `.contract.test.ts` as a test; the two never share a name.

**Enforcement.** planned — `checkFileKinds` in `tools/scripts/validate-repository.mjs`, reading the suffix and banned-folder
tables of `tools/scripts/structure.mjs` (STA-220). Nothing checks these rules today.

## Supersedes and sources

Supersedes: none. Sources: basalt `adr/0010`, `0020`, `0022`, `0032`; figentra `docs/adr/0010-module-specifiers`, `0019-subpath-imports`, `0035-conventions-freeze`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.