Checkpoint B — Step-by-Step Walkthrough
Goal: Add shared TypeScript config, Prettier, ESLint with dependency boundary enforcement, and wire everything into Turborepo pipelines.
Prerequisite: Checkpoint A completed — monorepo scaffold exists,
pnpm installpasses.
Step 1 — Create tsconfig.base.json
Create tsconfig.base.json at the repo root. This is the single source of truth for TypeScript settings shared across every package.
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true,
"esModuleInterop": true,
"resolveJsonModule": true
}
}
Step 2 — Update all package tsconfig.json files to extend the base
For apps/cli, packages/core, packages/ui, packages/features-registry — replace the full tsconfig.json with:
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist"
},
"include": ["src"]
}
For apps/web — extend the base but keep all Next.js-specific options:
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"noEmit": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": { "@/*": ["./src/*"] }
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts",
"**/*.mts"
],
"exclude": ["node_modules"]
}
Step 3 — Add typecheck script to apps/web
The Next.js scaffolder doesn’t add a typecheck script. Add it to apps/web/package.json:
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint .",
"typecheck": "tsc --noEmit"
}
Step 4 — Install Prettier
pnpm add -D -w prettier
The -w flag installs at the workspace root so all packages share it.
Step 5 — Create .prettierrc.json
Create .prettierrc.json at the repo root:
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 100,
"arrowParens": "always",
"quoteProps": "consistent"
}
Step 6 — Install ESLint and plugins
pnpm add -D -w eslint @eslint/js typescript-eslint eslint-plugin-boundaries
Step 7 — Create eslint.config.js
Create eslint.config.js at the repo root. Note: ESLint 9’s flat config requires a .js file — there is no JSON alternative.
import boundaries from "eslint-plugin-boundaries"
import { defineConfig } from 'eslint/config'
import tseslint from "typescript-eslint"
import js from "@eslint/js"
export default defineConfig(
js.configs.recommended,
...tseslint.configs.recommended,
{
plugins: {
boundaries,
},
settings: {
"boundaries/elements": [
{ type: "app-elements", pattern: "apps/*" },
{ type: "package-elements", pattern: "packages/*" },
],
},
rules: {
'boundaries/no-unknown': 'error',
'boundaries/element-types': [
'error',
{
default: 'disallow',
rules: [
{
from: 'app-elements',
allow: ['app-elements', 'package-elements'],
},
{
from: 'package-elements',
allow: ['package-elements'],
},
],
},
],
},
},
{
ignores: [
'**/node_modules/**',
'**/dist/**',
'**/.next/**',
'**/.turbo/**',
],
},
)
Step 8 — Add format scripts and type: module to root package.json
Update root package.json:
{
"name": "sidekick",
"private": true,
"version": "0.0.0",
"type": "module",
"packageManager": "pnpm@11.0.8+sha512.<your-hash>",
"scripts": {
"build": "turbo build",
"dev": "turbo dev",
"lint": "turbo lint",
"typecheck": "turbo typecheck",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,md}\""
},
"devDependencies": {
"@eslint/js": "^10.0.0",
"eslint": "^9.0.0",
"eslint-plugin-boundaries": "^6.0.0",
"prettier": "^3.0.0",
"turbo": "^2.5.6",
"typescript": "^5.0.0",
"typescript-eslint": "^8.0.0"
},
"pnpm": {
"onlyBuiltDependencies": ["sharp", "unrs-resolver"]
}
}
Key additions:
"type": "module"— required so Node.js treatseslint.config.jsas an ES moduleformatandformat:checkscripts — Prettier runs at root level across the whole repo, not per packagetypescriptin rootdevDependencies— hoisted to all packages sotscis consistently TypeScript 5+
Step 9 — Update lint script in every package
Replace "lint": "echo 'lint not configured yet'" with "lint": "eslint ." in:
apps/cli/package.jsonapps/web/package.jsonpackages/core/package.jsonpackages/ui/package.jsonpackages/features-registry/package.json
Step 10 — Install and verify
pnpm install
pnpm lint
pnpm typecheck
All 5 packages should pass both commands.
If pnpm install warns about ignored build scripts
Run:
pnpm approve-builds
Approve sharp and unrs-resolver. If apps/web lint fails with the same error, run pnpm approve-builds from inside apps/web as well.
Checkpoint B Exit Criteria
pnpm turbo lint— 5 packages, all successfulpnpm turbo typecheck— 5 packages, all successful- Second run of either command shows
cache hitfor all packages tsconfig.base.jsonexists at root; all packages extend it.prettierrc.jsonexists at rooteslint.config.jsexists at root with boundary enforcement rules
What’s Next
Checkpoint C confirms pnpm turbo build and pnpm turbo dev work end-to-end, then adds the root README.md.