Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @Emieldv
120 changes: 113 additions & 7 deletions packages/biome-config/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
# @nimblestudio/biome-config

Shared [Biome](https://biomejs.dev/) configuration for Nimble projects.
Shared [Biome](https://biomejs.dev/) configuration for Nimble projects. Provides composable presets for formatting, linting, and import organization across different project types.

## Installation

```bash
npm install -D @nimblestudio/biome-config @biomejs/biome
```

> `@biomejs/biome` is a peer dependency (>=2.0.0) and must be installed alongside this package.

## Usage

Create a `biome.json` in your project root and extend the config that matches your project:
Expand Down Expand Up @@ -49,6 +51,8 @@ Extends the root config with Next.js-specific linting rules:
}
```

> **Note:** The Next.js config sets the React linter domain to `"none"` because Next.js has its own set of rules. Do not combine `next.biome.json` with `react.biome.json` — use one or the other.

### NestJS

Extends the root config with NestJS-specific settings (decorator support, relaxed import types):
Expand All @@ -63,22 +67,124 @@ Extends the root config with NestJS-specific settings (decorator support, relaxe
}
```

## Monorepo setup

Biome walks up the directory tree looking for configuration files. In a monorepo, this means you need to be deliberate about where configs live so that packages pick up the right settings.

### How Biome resolves configuration

1. Biome starts from the file being checked and walks up directories looking for a `biome.json`.
2. When it finds one, it checks for `"root": true` (the default). If set, resolution stops there.
3. If `"root": false`, Biome merges that config with any parent config found further up the tree.

This means a monorepo root `biome.json` acts as the base, and each package can layer on its own overrides.

### Recommended structure

```
monorepo/
├── biome.json ← root config (root: true by default)
├── packages/
│ ├── web/
│ │ └── biome.json ← extends root + adds React rules (root: false)
│ ├── api/
│ │ └── biome.json ← extends root + adds NestJS rules (root: false)
│ └── shared/
│ └── (no biome.json) ← inherits root config automatically
```

### Step 1: Root config

The monorepo root `biome.json` should extend the base config and serve as the default for all packages:

```json
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["@nimblestudio/biome-config/root.biome.json"]
}
```

Since `"root"` defaults to `true`, Biome will stop here for any package that doesn't have its own `biome.json`.

### Step 2: Package-level configs

Packages that need framework-specific rules should add their own `biome.json` with `"root": false`. This tells Biome to merge the package config with the root config found further up the tree:

```json
{
"$schema": "../../node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["@nimblestudio/biome-config/react.biome.json"],
"root": false
}
```

Key details:

- **`"root": false`** is required — without it, Biome stops at this file and won't inherit the root config's formatter and base linter settings.
- **`$schema` path** — In a monorepo with hoisted dependencies, point the schema to the root `node_modules` using a relative path (e.g. `../../node_modules/...`).
- **Only extend the framework config** — The root `biome.json` already extends `root.biome.json`, so the package config only needs to add the framework-specific layer (e.g. `react.biome.json`). Biome merges them automatically.

### Packages that only need the base config

If a package doesn't need framework-specific rules, you have two options:

1. **No `biome.json` at all** — Biome walks up and finds the root config. Simplest approach.
2. **Explicit `biome.json` with `root: false`** — Useful if you want to add package-specific overrides later:

```json
{
"$schema": "../../node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["@nimblestudio/biome-config/root.biome.json"],
"root": false
}
```

## Overriding rules

You can override any setting from the shared configs in your project's `biome.json`. Rules defined later in the file take precedence over extended configs:

```json
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"extends": ["@nimblestudio/biome-config/root.biome.json"],
"linter": {
"rules": {
"suspicious": {
"noConsole": "error"
}
}
},
"formatter": {
"lineWidth": 80
}
}
```

## Available configs

| Config | Description |
| ------------------- | -------------------------------------------------------- |
| `root.biome.json` | Base formatter and linter settings (2-space indent, single quotes, import organization) |
| `react.biome.json` | React recommended linting, relaxed a11y rules, Tailwind CSS parsing |
| `next.biome.json` | Next.js recommended linting (disables React rules) |
| `next.biome.json` | Next.js recommended linting (sets React domain to `none`) |
| `nest.biome.json` | Unsafe parameter decorators, `useImportType` off |

### Config composition

The configs are designed to be layered on top of `root.biome.json`:

- **`root`** — Always required. Provides formatter settings, base linter rules, and import organization.
- **`react`** — Adds React linting and Tailwind CSS support. Use for React apps (Vite, CRA, etc.).
- **`next`** — Adds Next.js linting. Do **not** combine with `react` — Next.js replaces the React domain with its own rules.
- **`nest`** — Adds NestJS support (decorators, relaxed import types). Use for NestJS backends.

## What's included

### Formatter

- 2-space indentation
- 120 character line width
- Single quotes
- Single quotes (single quotes in JSX too)
- Semicolons as needed
- Trailing commas everywhere
- Arrow function parentheses always
Expand All @@ -92,11 +198,11 @@ Extends the root config with NestJS-specific settings (decorator support, relaxe

### Import organization

Imports are automatically organized into groups:
Imports are automatically organized into three groups separated by blank lines:

1. URL and Node.js built-in imports
2. Package imports
3. Alias and relative path imports
1. URL and Node.js built-in imports (`node:`, `https://`)
2. Package imports (`react`, `@nestjs/core`, etc.)
3. Alias and relative path imports (`@/`, `./`, `../`)

## License

Expand Down
90 changes: 80 additions & 10 deletions packages/tsconfig/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# @nimblestudio/tsconfig

Shared TypeScript configurations for Nimble projects.
Shared TypeScript configurations for Nimble projects. Provides opinionated presets for different project types, all built on a strict base configuration.

## Installation

Expand Down Expand Up @@ -72,17 +72,87 @@ The base config that all others extend from. Use this directly only if none of t
}
```

## Monorepo setup

In a monorepo, each package typically has its own `tsconfig.json` that extends one of these presets. TypeScript resolves `extends` from `node_modules`, so as long as `@nimblestudio/tsconfig` is installed (at the root or in the package), it works out of the box.

### Recommended structure

```
monorepo/
├── packages/
│ ├── web/
│ │ └── tsconfig.json ← extends next.json or react-vite.json
│ ├── api/
│ │ └── tsconfig.json ← extends nest.json
│ └── shared/
│ └── tsconfig.json ← extends node.json
```

### Adding project-specific settings

Extend a preset and add your own `compilerOptions`, `include`, and `exclude` as needed. Your settings merge with (and override) the preset:

```json
{
"extends": "@nimblestudio/tsconfig/next.json",
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src", "next-env.d.ts"],
"exclude": ["node_modules"]
}
```

### Multiple tsconfigs in one package

Some setups need separate configs for different file sets (e.g. app code vs. tooling config). A common pattern in React Vite projects:

```
packages/web/
├── tsconfig.json ← references the others
├── tsconfig.app.json ← extends react-vite.json (src files)
└── tsconfig.node.json ← extends react-vite-node.json (vite.config.ts)
```

The root `tsconfig.json` ties them together with [project references](https://www.typescriptlang.org/docs/handbook/project-references.html):

```json
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}
```

## Available configs

| Config | Extends | Use case |
| ------------------ | -------- | ----------------------------------------- |
| `base.json` | - | Shared base settings (ES2022, strict) |
| `node.json` | base | Node.js projects |
| `nest.json` | node | NestJS projects (decorators, source maps) |
| `next.json` | node | Next.js projects (JSX preserve) |
| `mastra.json` | node | Mastra projects |
| `react-vite.json` | base | React apps with Vite |
| `react-vite-node.json` | node | Vite config / server-side in React Vite |
| Config | Extends | Key settings |
| ---------------------- | -------- | ----------------------------------------------------------------------------- |
| `base.json` | - | ES2022, strict mode, bundler module resolution, isolated modules |
| `node.json` | base | Adds Node.js types, `noEmit: true` |
| `nest.json` | node | Decorators, emit enabled, source maps, nodenext module resolution |
| `next.json` | node | DOM libs, JSX preserve, allows JS files, incremental builds |
| `mastra.json` | node | ES2022 target, bundler resolution, emits to `dist/` |
| `react-vite.json` | base | DOM libs, `jsx: react-jsx`, Vite client types, verbatim module syntax |
| `react-vite-node.json` | node | ES2023, verbatim module syntax, erasable syntax only |

### Config hierarchy

```
base.json
├── node.json
│ ├── nest.json
│ ├── next.json
│ ├── mastra.json
│ └── react-vite-node.json
└── react-vite.json
```

## License

Expand Down
Loading