Formatting and linting
Consistent spacing, imports, and formatting across Pathfinder source, examples, and documentation.
Commands
Run these from the repository root:
# Fix ESLint findings, then apply Prettier.
pnpm pathfinder:format
# Check formatting without changing files.
pnpm pathfinder:format:check
# Check spacing, imports, types, hooks, and accessibility.
pnpm pathfinder:lint
# Run the complete package verification.
pnpm pathfinder:checkThe root formatting command also refreshes generated example source and API metadata after fixing source files. The fast formatting pass runs only spacing and import rules without constructing a TypeScript program. Full type-aware lint remains a required separate gate; use the workspace lint:fix command for other autofixable lint findings. The commands cover packages/pathfinder and apps/pathfinder-docs. They do not reformat other applications. Prettier 3.6.2 is pinned in both workspaces. CI checks formatting separately from ESLint; formatting errors do not run through an ESLint Prettier plugin.
The package and docs lint and lint:fix commands give ESLint a 4 GB JavaScript heap limit for type-aware analysis. This avoids the roughly 2 GB default heap limit on CI runners without disabling rules or excluding source files. pathfinder:ci runs heavy tasks sequentially to bound total memory use.
Formatting conventions
Prettier owns indentation, wrapping, punctuation, and repeated empty lines. The scoped configs inherit the repository's 80-column target, two-space indentation, single JS/TS quotes, JSX double quotes, semicolons, ES5 trailing commas, parentheses around arrow parameters, and LF endings. Line width is a target, not a hard limit for strings or import paths.
Prettier preserves a single blank line between logical groups, collapses repeated blank lines, removes empty lines at block boundaries, and ends each file with one newline. Avoid manual alignment or line-length lint rules that compete with the formatter.
Pathfinder disables the root Prettier plugins. Import organization belongs to ESLint; source formatting does not delete imports or reorder Tailwind classes. Tailwind class sorting would require a separate configuration using the package's v4 stylesheet and generated tokens.
Blank lines
ESLint enforces one blank line:
- After directives such as
'use client'and after the import block. - Before and after type aliases, interfaces, functions, and classes, including exported declarations.
- Before and after variables initialized directly with an arrow function or function expression, including exported components.
- Before a
returnwhen another statement precedes it in the same block.
Related constants and hook calls may remain consecutive. Simple object/type fields and JSX children do not require artificial blank lines. A return-only function does not need a blank line after its opening brace.
type Option = {
id: string;
label: string;
};
const getLabels = (options: readonly Option[]) => {
const labels = options.map((option) => option.label);
const uniqueLabels = new Set(labels);
return [...uniqueLabels];
};Spacing around function wrappers such as memo(...) remains an authoring choice; the automatic function-variable rule matches direct function initializers. Function overload signatures remain together.
Imports
ESLint sorts imports into these groups, separated by blank lines:
- Side-effect imports, preserving their relative order.
- Node built-ins and external packages.
- Workspace packages under
@commenda/. - Internal absolute aliases (
@/and~/). - Relative imports.
Type imports follow the existing consistent-type-imports rule. Unused imports are checked by ESLint. Handwritten export barrels are not automatically reordered. Generated barrels are sorted by their generator. Keep stylesheet override imports in their intended relative order; the import sorter moves the side-effect group before named imports, so modules with initialization dependencies must be reviewed when applying fixes.
Generated files and examples
Edit SVG sources, inventories, example TSX, or generator scripts rather than generated React components. TypeScript generators use the shared spacing/import formatter followed by the same Prettier configuration, so generator checks and formatting checks agree. Generated source stays checked; build output, raw assets, public files, and isolated consumer fixtures are excluded from broad formatting.
After editing example source, run the affected generator:
pnpm --filter @commenda/pathfinder generate:examples
pnpm --filter @commenda/pathfinder-docs generate:api
pnpm --filter @commenda/pathfinder-docs generate:navigationDocumentation display formatting preserves teaching-only imports and uses the same whitespace conventions. Component snippets may be incomplete intentionally; the docs renderer never runs unused-import fixes on them.
Editor setup
Select Prettier as the formatter for these workspaces and use their local ESLint 9 installation. In VS Code, add the two directories to eslint.workingDirectories alongside any existing workspace entries. Enable format on save and source.fixAll.eslint for explicit saves. The CLI runs ESLint before Prettier and is the authoritative check when editor save actions differ.
Keep the repository's other applications on their existing tooling. Do not add global editor settings or repository-wide save actions just for Pathfinder.