Setting Up a Simple, Clean TypeScript Project with Bun and Biome #
Summary #
For a super simple and clean TypeScript setup in 2025, Bun + Biome is the optimal combination. Bun provides native TypeScript execution without any build step, bundling, test runner, and package management in a single binary. Biome replaces both ESLint and Prettier with a single Rust-based tool that's 25x faster than Prettier and 15x faster than ESLint.
This combination reduces your toolchain from 5+ packages (TypeScript, ts-node, ESLint, Prettier, various plugins) to just 2 dependencies while providing better performance and simpler configuration. The entire setup takes about 2 minutes and requires just 2 configuration files.
Project Context #
This is a brand new project with no existing dependencies or configuration. This makes it the ideal candidate for the Bun + Biome stack, as there are no legacy ESLint configs to migrate and no existing toolchain constraints.
Detailed Findings #
The Bun + Biome Stack #
What it is: A modern TypeScript development stack combining:
- Bun: A fast all-in-one JavaScript runtime, package manager, bundler, and test runner
- Biome: A unified linting and formatting tool written in Rust
Why consider it:
- Zero-config TypeScript execution (no transpilation step needed)
- Single binary for runtime, testing, bundling, and package management
- 4x faster startup than Node.js
- 25x faster formatting than Prettier
- Dramatically simpler configuration
Step-by-Step Setup #
1. Initialize the Project #
1# Create project and initialize
2bun init
3
4# This creates:
5# - package.json
6# - tsconfig.json (pre-configured for Bun)
7# - index.ts (entry point)
2. Install Biome #
1# The -E flag pins exact version for consistency
2bun add -D -E @biomejs/biome
3
4# Initialize Biome configuration
5bunx --bun biome init
3. Configure tsconfig.json #
Bun's init creates a good default, but here's the recommended configuration:
1{
2 "compilerOptions": {
3 "lib": ["ESNext"],
4 "target": "ESNext",
5 "module": "ESNext",
6 "moduleDetection": "force",
7 "jsx": "react-jsx",
8 "allowJs": true,
9
10 "moduleResolution": "bundler",
11 "allowImportingTsExtensions": true,
12 "verbatimModuleSyntax": true,
13 "noEmit": true,
14
15 "strict": true,
16 "skipLibCheck": true,
17 "noFallthroughCasesInSwitch": true,
18 "noUncheckedIndexedAccess": true,
19 "noUnusedLocals": true,
20 "noUnusedParameters": true,
21
22 "outDir": "./dist",
23 "rootDir": "./src"
24 },
25 "include": ["src/**/*"]
26}
4. Configure biome.json #
1{
2 "$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
3 "vcs": {
4 "enabled": true,
5 "clientKind": "git",
6 "useIgnoreFile": true
7 },
8 "organizeImports": {
9 "enabled": true
10 },
11 "linter": {
12 "enabled": true,
13 "rules": {
14 "recommended": true
15 }
16 },
17 "formatter": {
18 "enabled": true,
19 "indentStyle": "space",
20 "indentWidth": 2,
21 "lineWidth": 100
22 },
23 "files": {
24 "ignore": ["node_modules", "dist"]
25 }
26}
5. Add package.json Scripts #
1{
2 "name": "your-project",
3 "type": "module",
4 "scripts": {
5 "dev": "bun run --watch src/index.ts",
6 "start": "bun run src/index.ts",
7 "test": "bun test",
8 "lint": "biome lint ./src",
9 "format": "biome format --write ./src",
10 "check": "biome check --write ./src",
11 "typecheck": "tsc --noEmit"
12 },
13 "devDependencies": {
14 "@biomejs/biome": "2.0.0",
15 "@types/bun": "latest"
16 }
17}
6. Create Project Structure #
your-project/
├── src/
│ └── index.ts
├── tests/
│ └── index.test.ts
├── biome.json
├── tsconfig.json
├── package.json
└── .gitignore
7. VS Code Integration (Optional) #
Create .vscode/settings.json:
1{
2 "editor.defaultFormatter": "biomejs.biome",
3 "editor.formatOnSave": true,
4 "editor.codeActionsOnSave": {
5 "source.organizeImports.biome": "explicit",
6 "quickfix.biome": "explicit"
7 },
8 "[typescript]": {
9 "editor.defaultFormatter": "biomejs.biome"
10 },
11 "[typescriptreact]": {
12 "editor.defaultFormatter": "biomejs.biome"
13 }
14}
Install the Biome VS Code extension.
Complete Setup Script #
For convenience, here's a one-shot setup:
1#!/bin/bash
2# Initialize Bun project
3bun init -y
4
5# Create src directory and move entry point
6mkdir -p src tests
7mv index.ts src/
8
9# Install Biome
10bun add -D -E @biomejs/biome @types/bun
11
12# Initialize Biome
13bunx --bun biome init
14
15# Create .gitignore
16cat > .gitignore << 'EOF'
17node_modules/
18dist/
19.DS_Store
20*.log
21EOF
Alternative: Node.js + Biome #
If you need Node.js compatibility (for specific npm packages or deployment targets):
1# Initialize with npm
2npm init -y
3
4# Install TypeScript and Biome
5npm install -D typescript @types/node @biomejs/biome
6
7# Initialize configs
8npx tsc --init
9npx @biomejs/biome init
10
11# Run with experimental TypeScript support (Node 22+)
12node --experimental-strip-types src/index.ts
13
14# Or use tsx for better DX
15npm install -D tsx
16npx tsx src/index.ts
Trade-offs:
- Pro: Maximum npm ecosystem compatibility
- Pro: Mature, battle-tested runtime
- Con: Requires additional tooling for TypeScript execution
- Con: Slower startup and execution
Recommendation #
Use Bun + Biome for this new project. The combination provides:
- Minimal configuration: 2 files (tsconfig.json, biome.json)
- Fast feedback loop: Native TypeScript execution, no build step
- Unified tooling: One tool for linting AND formatting
- Modern defaults: Sensible out-of-the-box settings
- Future-proof: Both tools are actively developed and improving rapidly
The setup is literally:
1bun init
2bun add -D -E @biomejs/biome
3bunx --bun biome init
Three commands and you have a fully-functional TypeScript project with linting and formatting.
When NOT to Use This #
-
Enterprise compliance requirements: If you need specific ESLint plugins for security scanning or compliance (e.g., eslint-plugin-security, eslint-plugin-sonarjs), stick with ESLint. Biome's plugin ecosystem is limited.
-
Type-aware linting rules: Biome doesn't have access to TypeScript's type information, so rules like
@typescript-eslint/no-floating-promisesor@typescript-eslint/await-thenablearen't available. Use typescript-eslint if these are critical. -
Vue, Svelte, or Markdown support: Biome's language support is focused on JS/TS/JSX/TSX and JSON. If you need to lint/format Vue SFCs, Svelte components, or Markdown files, you'll need additional tools.
-
Legacy Node.js features: Some older npm packages use CommonJS patterns or Node.js-specific APIs that Bun doesn't fully support. Check Bun's compatibility tracker for your critical dependencies.
-
Production workloads requiring proven stability: While Bun is stable for development, some teams prefer Node.js for production due to its longer track record. Consider using Bun for development and Node.js for production if stability is paramount.
Sources #
- TypeScript - Bun Docs
- Getting Started with BiomeJS | Better Stack
- Biome Getting Started Guide
- How to Run TypeScript in 2025 | Akos Komuves
- Bun vs Node.js 2025: Performance Guide | Strapi
- Biome vs ESLint: The Ultimate 2025 Showdown | Medium
- From ESLint and Prettier to Biome | Kitty Giraudel
- Node.js vs Deno vs Bun | Better Stack