| name | typescript-build-tools |
| description | TypeScript project tooling with Bun, tsgo, Vitest, Biome, and Turborepo. Use when setting up package.json scripts, running builds, typechecking, configuring tests, linting, formatting, or orchestrating monorepo development. |
| user-invocable | false |
TypeScript Build Tools
Modern TypeScript build tooling stack: Bun for package management and task running, tsgo for typechecking, Vitest for testing, Biome for linting/formatting, and Turborepo for monorepo orchestration.
Additional References
Quick Start
bun add -D vitest @vitest/coverage-v8 @biomejs/biome
bun add -D turbo
Package.json Scripts
Single Package
{
"scripts": {
"dev": "bun run --watch src/index.ts",
"build": "bun build ./src/index.ts --outdir ./dist --target bun",
"typecheck": "tsgo --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write .",
"check": "bun run typecheck && bun run lint && bun run test"
}
}
Monorepo Root
{
"scripts": {
"dev": "turbo dev",
"build": "turbo build",
"typecheck": "turbo typecheck",
"test": "turbo test",
"lint": "turbo lint",
"check": "turbo typecheck lint test"
}
}
Bun
Package Manager
bun install
bun add fastify drizzle-orm
bun add -D vitest @biomejs/biome
bun remove package-name
bun update
Task Runner
Important: Use bun run test (not bun test) on Node projects. bun test invokes Bun's native test runner, not your package.json test script.
bun run dev
bun run test
bun run build
bun run src/index.ts
bun run --watch src/index.ts
bun run --env-file .env src/index.ts
Build Command
bun build ./src/index.ts --outdir ./dist --target bun
bun build ./src/index.ts --outdir ./dist --target node
bun build ./src/index.ts --outdir ./dist --target bun --minify
bun build ./src/index.ts ./src/worker.ts --outdir ./dist --target bun
See references/bun.md for bunfig.toml configuration and advanced patterns.
tsgo Typechecking
tsgo is a fast TypeScript typechecker. Use it instead of tsc for faster CI builds.
tsgo --noEmit
tsgo --noEmit src/**/*.ts
tsgo --noEmit -p tsconfig.json
tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true,
"noEmit": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"lib": ["ESNext"],
"types": ["bun-types"]
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
Vitest
Basic Configuration
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
environment: 'node',
include: ['src/**/*.test.ts', 'test/**/*.test.ts'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
include: ['src/**/*.ts'],
exclude: ['src/**/*.test.ts', 'src/types/**'],
},
},
})
With Path Aliases
import { defineConfig } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
plugins: [tsconfigPaths()],
test: {
globals: true,
},
})
Global Setup (Database Migrations)
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
globalSetup: './test/global-setup.ts',
setupFiles: ['./test/setup.ts'],
},
})
import { execSync } from 'node:child_process'
export async function setup() {
console.log('Running database migrations...')
execSync('drizzle-kit migrate', { stdio: 'inherit' })
}
export async function teardown() {
console.log('Test teardown complete')
}
See references/vitest.md for workspace configs, benchmarks, and Cloudflare Workers pool.
Biome
Basic biome.json
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"ignore": ["dist", "node_modules", "*.gen.ts"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab",
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"trailingCommas": "es5"
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"organizeImports": {
"enabled": true
}
}
Strict Rules (Production)
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noForEach": "error"
},
"performance": {
"noDelete": "error"
},
"style": {
"useNodejsImportProtocol": "error"
}
}
}
}
See references/biome.md for rule explanations, shareable configs, and CLI commands.
Turborepo (Monorepo)
turbo.json
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"typecheck": {
"dependsOn": ["^typecheck"]
},
"lint": {},
"test": {
"dependsOn": ["^build"],
"env": ["DATABASE_URL"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
Workspace Structure
my-monorepo/
├── package.json # Root with turbo scripts
├── turbo.json # Turbo configuration
├── biome.json # Shared Biome config
├── packages/
│ ├── config-biome/ # Shareable Biome package
│ └── shared/ # Shared utilities
├── apps/
│ ├── api/ # Fastify API
│ └── web/ # React app
└── bun.lock
See references/turborepo.md for caching strategies, filtering, and CI setup.
Cloudflare Workers
Vite + Cloudflare Plugin
import { cloudflare } from '@cloudflare/vite-plugin'
import { reactRouter } from '@react-router/dev/vite'
import tailwindcss from '@tailwindcss/vite'
import tsconfigPaths from 'vite-tsconfig-paths'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
cloudflare({ viteEnvironment: { name: 'ssr' } }),
tailwindcss(),
reactRouter(),
tsconfigPaths(),
],
})
Vitest with Cloudflare Workers Pool
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'
export default defineWorkersConfig({
test: {
globals: true,
pool: '@cloudflare/vitest-pool-workers',
poolOptions: {
workers: {
wrangler: { configPath: './wrangler.jsonc' },
},
},
},
})
CI Pipeline
GitHub Actions
name: typescript-build-tools
on:
push:
branches: [main]
pull_request:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bun run typecheck
- run: bun run lint
- run: bun run test
Monorepo CI with Turbo
name: typescript-build-tools
on:
push:
branches: [main]
pull_request:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run check
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
Guidelines
- Use Bun as package manager (
bun install) and task runner (bun run)
- Use
bun run test (not bun test) - bun test runs Bun's native test runner
- Use tsgo for typechecking - faster than
tsc for CI
- Use Vitest for testing - fast, ESM-native, great DX
- Use Biome for linting and formatting - single tool, fast
- Use Turborepo for monorepos - caching, parallel execution
- Enable V8 coverage in Vitest for accurate coverage reports
- Configure global setup for database migrations in tests
- Use workspace configs in Vitest for different test pools
- Share Biome config via workspace package in monorepos
- Run checks in order: typecheck, lint, test (fail fast)
- Use
--frozen-lockfile in CI for reproducible builds
- Configure Turbo caching for faster CI with remote cache