Skip to content

TIP

This page mirrors .agents/typescript.md from the repository. Edit it at the source, not here.

TypeScript Conventions

Use this for repo-wide TypeScript structure, import boundaries, and schema placement.

For shared cross-package domain contracts in packages/core, follow Core package patterns.

Shared Schema Pattern

For shared package domains, prefer a small domain module over ad hoc type dumping grounds.

text
src/<domain>/
	constants.ts
	types.ts
	utils.ts
	index.ts

For app-local or slice-local code, keep schemas next to the owning route, feature, or package instead of creating a global type folder.

Schema Placement

  • Keep schemas close to the owning slice or package.
  • For app-local or package-local schemas, the default pattern is types/thing.type.ts.
  • When the same schema, enum, or default is consumed across packages, move it into packages/core instead of recreating literal unions in apps/web or packages/api.

Example package-local schema:

ts
export const ThingSchema = z.object({ ... });
export type Thing = z.infer<typeof ThingSchema>;

Both schema (ThingSchema) and type (Thing) are named exports.

When a schema is shared across package boundaries, export the schema and inferred type from the owning shared module and import that same schema everywhere else.

If the frontend needs labels, options, or defaults for a shared enum, derive them from the shared schema or shared helpers instead of creating a second local union.

Module Resolution

  • nodenext module resolution with allowImportingTsExtensions
  • Cross-package: @saasweave/<package>/<subpath>
  • Intra-package: #@/ alias

lib/ vs utils/

DirectoryContains
lib/Business logic, library integrations, API clients
utils/Pure stateless helper functions

In packages/core, keep shared schemas in domain types.ts files and pure domain helpers in utils.ts. Do not move router, DB, or React logic there.

Linting (Oxlint)

Inline disable syntax:

ts
// oxlint-disable-next-line no-console
console.log("debug");

// oxlint-disable-line no-console, no-plusplus
console.log(x++);

/* oxlint-disable no-console */
// Disables for rest of file

ESLint-style comments (eslint-disable-*) also work for compatibility.

Import Sorting (auto-enforced by Oxfmt)

Order: builtins → external → @saasweave/*@/pages@/widgets@/features@/shared → relative → styles

Released under the MIT License.