tsconfig
TypeScript config conventions for this monorepo: the two-base layering, the eight leaf tiers, and the never-redeclare list. Use when adding a package, editing any tsconfig.json, picking a tier for a new app, or debugging module resolution.
Works with
---
name: tsconfig
description: TypeScript config conventions for this monorepo: the two-base layering, the eight leaf tiers, and the never-redeclare list. Use when adding a package, editing any tsconfig.json, picking a tier for a new app, or debugging module resolution.
license: MIT
---
# tsconfig conventions
Every package here is **source-only `.ts`**: `exports` point at `./src/*.ts`,
there is no build step, and consumers (Bun, Vite, WXT, Tauri, the Cloudflare
Worker) operate on raw `.ts`. That single fact decides the whole config.
## The one rule
A leaf `tsconfig.json` may set **only**: `types`, library-only strictness
(`noUnusedLocals`/`noUnusedParameters`), `checkJs` (SvelteKit), and genuinely
package-specific options (`jsx`, `paths`, `customConditions`, `include`).
Anything else belongs in a base. If a leaf option repeats a base value or a
TypeScript default, delete it.
## Two base files
```
tsconfig.base.json universal: target/lib[ESNext], module preserve, strict,
noEmit, isolatedModules, verbatimModuleSyntax, types []
tsconfig.dom.json extends base; its ONLY job is lib [ESNext, DOM, DOM.Iterable]
```
There is no `tsconfig.base.lib.json` and no project `references`. Source-only
packages never emit, so `composite`/`declaration`/`outDir` have no place here.
## Module strategy: one, repo-wide
`module: "preserve"` + `moduleResolution: "bundler"`. `preserve` implies
`bundler` (TS 5.4+); the explicit pair is kept for legibility. **Never use
`NodeNext`** anywhere: nothing in this repo is published as emitted Node ESM,
and `bundler` resolution already reads package.json `imports`/`exports`.
## The eight leaf tiers
Pick the tier, copy the shape, change nothing else.
| Tier | `extends` | Leaf adds |
| --- | --- | --- |
| Bun library | `"../../tsconfig.base.json"` | `types:["bun"]`, `noUnusedLocals`, `noUnusedParameters` |
| Node library | `"../../tsconfig.base.json"` | `types:["node"]`, `noUnusedLocals`, `noUnusedParameters` |
| Svelte library | `"../../tsconfig.dom.json"` | `types:["bun"]`, `noUnusedLocals`, `noUnusedParameters` |
| SvelteKit app | `["../../tsconfig.base.json", "./.svelte-kit/tsconfig.json"]` | `checkJs:true`, `types:["bun"]` |
| Cloudflare Worker | `"../../tsconfig.base.json"` | `jsx`, `jsxImportSource`, `types`, `include` |
| Bun app | `"../../tsconfig.base.json"` | `types:["bun"]`, `include` |
| Astro app | `["../../tsconfig.base.json", "astro/tsconfigs/strict"]` | astro `include`/`exclude` |
| WXT extension | `["../../tsconfig.dom.json", "./.wxt/tsconfig.json"]` | `customConditions`, `paths`, `include` |
A generated config (`./.svelte-kit/tsconfig.json`, `./.wxt/tsconfig.json`) goes
**last** in the array so its `lib`/`module` win where they must. Never hand-edit
a generated config.
The two canonical library shapes in full:
```jsonc
// bun library: packages/workspace, filesystem, util, sync, cli, ...
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"types": ["bun"],
"noUnusedLocals": true,
"noUnusedParameters": true
}
}
// svelte library: packages/ui, svelte-utils
{
"extends": "../../tsconfig.dom.json",
"compilerOptions": {
"types": ["bun"],
"noUnusedLocals": true,
"noUnusedParameters": true
}
}
```
## Never redeclare these (base value or TS default)
Putting any of these in a leaf is dead weight. Delete on sight.
| Do not write in a leaf | Why |
| --- | --- |
| `module: "preserve"` | already in `tsconfig.base.json` |
| `moduleResolution`, `target`, `noEmit`, `strict`, `isolatedModules` | already in the base |
| `lib: ["ESNext"]` | the base default; use `tsconfig.dom.json` if you need DOM |
| `noPropertyAccessFromIndexSignature: false` | that is already the TS default |
| `useDefineForClassFields: true` | default when `target` >= ES2022 |
| `forceConsistentCasingInFileNames` | default `true` since TS 5.0 |
| `resolvePackageJsonExports` | default `true` under `moduleResolution: bundler` |
| `sourceMap` | no-op under `noEmit` |
| single-element `extends` array | use the string form: `"extends": "../../tsconfig.base.json"` |
## `types` is opt-in, on purpose
The base sets `types: []` to disable auto-inclusion of every `node_modules/@types`
package. Each leaf opts in: `["bun"]` for almost everything, `["node"]` for the
one package that uses `@types/node`. Do not hoist `["bun"]` to a base: a package
without `@types/bun` installed would then fail with `Cannot find type definition`.
## `include` rules
- TypeScript does **not** merge `include` across `extends`. A leaf `include`
fully *replaces* the inherited one. For SvelteKit apps this means: do not set
your own `include`, or you drop the generated `ambient.d.ts`/`$types` globs.
- Only set `include` when you must narrow scope for a real reason; comment why.
## Adding a new package
1. Scaffold via the `monorepo` skill's boilerplate.
2. Pick a tier from the table above; copy that exact shape.
3. `package.json` uses `exports` only, no `main`/`types`. Entry point is
`./src/index.ts`.
4. `bun install` at the repo root, then `bun typecheck`.
## Background
The full rationale, the migration that established this layout, and the baseline
typecheck state are in `specs/20260522T190000-modernize-monorepo-tsconfig.md`.More Debugging skills
diagnosing-bugs
mattpocock/skills
Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.
explore-code
lllllllama/rigorpilot-skills
Rigor Improve implementation leaf skill for auditable candidate implementation in deep learning research repositories. Use when the researcher explicitly authorizes exploratory work on an isolated branch or worktree to transplant modules, adapt a backbone, add LoRA or adapter layers, replace a head, or stitch together meaningful low-risk migration ideas with rollback-aware records in `explore_outputs/`. Do not use for end-to-end exploration orchestration on top of `current_research`, trusted baseline reproduction, conservative debugging, environment setup, verified contribution claims, or default repository analysis.
safe-debug
lllllllama/rigorpilot-skills
Rigor Debug / Rigor Audit skill for deep learning research work. Use when the user pastes a traceback, terminal error, CUDA OOM, checkpoint load failure, shape mismatch, NaN loss symptom, or training failure and wants conservative diagnosis before any patching, with debug fixes clearly separated from research contributions. Do not use for broad refactoring, speculative adaptation, automatic exploratory patching, or general repository familiarization.

