Groundwork Checkpoint B Walkthrough
| As of | |
|---|---|
| Version | 1.1.0 |
| Kind | guidance |
| Length | 713 words, about 3 min |
| Tags | buildwalkthroughphase-0checkpoint |
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 prettierThe -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-boundariesStep 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": "[email protected]+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 typecheckAll 5 packages should pass both commands.
If pnpm install warns about ignored build scripts
Run:
pnpm approve-buildsApprove 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 successful -
pnpm 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 root -
eslint.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.
Post note — pnpm build approvals (added 2026-10-23)
pnpm 11 and later no longer read the "pnpm" field in package.json, and warn on every command while it's there. Leave pnpm.onlyBuiltDependencies out of step 8's package.json, and approve dependency build scripts in pnpm-workspace.yaml instead:
allowBuilds:
esbuild: true
sharp: true
unrs-resolver: trueSidekick removed the dead field in sidekick#14, after Phase 2 lesson 3.