Install any skill in seconds. Free to start, no credit card required.
Get Started Free →minpeter's house style for building and reviewing TypeScript packages and monorepos. The locked stack: pnpm (latest) + Turborepo + Changesets + Biome via the ultracite preset with ZERO ignores/overrides/suppressions + tsdown for builds + Vitest, with `tsc --noEmit` for type-checking, the namespaced source-condition for zero-build internal deps, and MANDATORY npm OIDC trusted publishing (no NPM_TOKEN). Use this when scaffolding a new TS library or monorepo, adding a workspace package, choosing bu
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 115% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 74% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 34% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 56% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 69% | 0% |
An opinionated, locked toolchain for TypeScript libraries and monorepos. "Locked" means: don't re-litigate these per project — they are the defaults. Every choice below was distilled from minpeter's own repos and then checked against current ecosystem best practice (see the verdicts in references/).
| Concern | Choice (no substitutes) | |----------------|----------------------------------------------------------| | Package manager| pnpm latest, with the resolved version recorded in packageManager | | Monorepo | pnpm workspaces + Turborepo latest | | Lint + format | Biome latest via ultracite latest — zero ignores (§3) | | Type-check | tsc --noEmit only — never emit JS with tsc | | Build | tsdown latest — not tsup, not raw tsc | | Internal deps | namespaced source-condition @minpeter/source (§5) | | Tests | Vitest latest + v8 coverage | | Versioning | Changesets | | Publish | npm OIDC trusted publishing, mandatory (§6) | | TS compiler | TypeScript latest stable | | Filenames | kebab-case (enforced by ultracite) |
> If you find ESLint, Prettier, tsup, npm/yarn lockfiles, a long-lived > NPM_TOKEN, or // biome-ignore comments → that's not this style. Flag it.
One publishable thing → SINGLE-PACKAGE repo (src/ at root). No turbo, no source-condition.
Several related pkgs → MONOREPO (packages/*, turbo, source-condition for internal deps).pnpm-workspace.yaml with packages: ["packages/*"] (omit for single pkg);put pnpm settings (onlyBuiltDependencies, verifyDepsBeforeRun) here, not .npmrc.
corepack use pnpm@latest, installall dev tools with @latest, then keep the resolved packageManager, dependency ranges, and lockfile that pnpm writes.
tsconfig.base.json (shared strict options) + root tsconfig.json(noEmit, customConditions) + tsconfig.build.json (NO custom condition).
biome.jsonc = just extends: ["ultracite/biome/core", "ultracite/biome/vitest"]. Nothing else (§3).tsc --noEmit for typecheck.package.json: type: module, sideEffects: false,exports with the source-condition (§5), publishConfig.provenance: true.
.changeset/config.json, turbo.json, vitest.config.ts.ci.yml: lint → typecheck → test → build → attw) andrelease.yml (Changesets + OIDC, §6).
→ All file contents are in references/templates.md. Copy them verbatim.
The whole biome.jsonc is two lines of intent:
jsonc{ "$schema": "https://biomejs.dev/schemas/<installed-biome-version>/schema.json", "extends": ["ultracite/biome/core", "ultracite/biome/vitest"] }
No files.includes ignores. No overrides. No rule "off". No // biome-ignore / // biome-ignore-all comments. ultracite is already very strict and already relaxes the right things itself (tests, *.config.ts, *.d.ts, generated/build dirs, noConsole off). Adding exceptions is how a style guide rots — the rule here is fix the code, not the config.
Practical consequences (this is why zero-ignore works cleanly):
noBarrelFile fires on re-export-only files.Instead of overriding it (what the older repos did), expose subpath exports that point at real modules (§5). This is also better for tree-shaking — the rule is steering you correctly.
interface over type, no enum (constobjects / unions), no any, no !, node: import protocol, type-only import type/export type — all enforced; just write to them.
.omx, .omo) → put them in .gitignore; ultracitesets vcs.useIgnoreFile: true, so Biome skips them without a Biome ignore.
See references/templates.md for the full list of what ultracite enforces.
tsc --noEmitbuild tool. dts: true, sourcemap: true, unbundle: true for file-per-module output (pairs well with subpath exports).
tsc never emits. "typecheck": "tsc --noEmit". The bundler owns output."type": "module", exports use import). Ship CJSonly if you actually have CJS consumers — and then nest types correctly per branch (.d.ts vs .d.cts); see the dual template.
Verdict: keep it. It's the Colin McDonnell / TypeScript-endorsed way to get zero-build "live types" across a monorepo, and unlike publishConfig.exports it's package-manager-agnostic. But it has sharp edges — wire all four of these or it silently resolves to stale dist:
jsonc// each publishable package's package.json — condition FIRST, then types, then import "exports": { "./package.json": "./package.json", ".": { "@minpeter/source": "./src/index.ts", "types": "./dist/index.d.ts", "import": "./dist/index.js" } }
tsconfig.json: "customConditions": ["@minpeter/source"] (editor + tsc --noEmit resolve to source).tsconfig.build.json, used by tsdown): must NOT carry the condition, or your .d.ts resolves sibling deps to .ts.tsx --conditions @minpeter/source (tsx does not read tsconfig — it'll silently miss otherwise).resolve: { conditions: ["@minpeter/source"] }.Guardrails (non-negotiable):
@minpeter/source, never bare source) so it can't collide.src file is missing — it silently fallsback. So run attw --pack (@arethetypeswrong/cli) in CI on every publishable package to prove external consumers get correct dist types.
Full rationale, the contested history, every footgun, and citations: references/source-condition.md. (Single-package repos: skip all of this.)
No NPM_TOKEN. Ever. Releases authenticate via GitHub OIDC; provenance is attached automatically.
permissions: { id-token: write, contents: read },the Node runtime currently recommended by npm's trusted-publishing docs, and npm@latest installed immediately before publishing.
enable "Allow GitHub Actions to create and approve pull requests". New repos default to read-only with PR creation off; without this, the CI run that opens the Version Packages PR fails with 403 even when the workflow declares pull-requests: write.
changeset publish works under OIDC; do not set NODE_AUTH_TOKEN on thepublish step (npm only uses OIDC when the auth token env is unset).
publishConfig: { "access": "public", "provenance": true } per package.(org/user + repo + workflow filename). Caveat: OIDC can't publish a package's first ever version — do the initial publish with a token, then switch to OIDC.
Step-by-step + the release workflow: references/publishing-oidc.md.
packageManager; pnpm-workspace.yaml holds pnpm settingsbiome.jsonc extends ultracite and has zero overrides/ignores/biome-ignoretsc is --noEmit onlyattw in CIexports order: custom condition → types → import/require (types nested per branch if dual)type: module, sideEffects: false, files: ["dist"], publishConfig.provenance: trueid-token: write), no NPM_TOKEN, current npm trusted-publishing runtime guidance, and npm@latestinterface over type; no enum/any/!; node: importsESLint / Prettier · tsup or raw-tsc library builds · npm/yarn/bun lockfiles · NPM_TOKEN secret for publishing · // biome-ignore or biome overrides · barrel index.ts re-export files · default-export-heavy modules · PascalCase/snake_case filenames · enum · any · non-null !.
Other measured skills in the registry, with their headline benchmark lift.