- resolve all 69 client type-checking errors for stricter TS compliance - remove obsolete type-check baseline scripts and files - overhaul project root with updated README.md and new DEVELOPMENT.md - migrate to unified baseline migration strategy and cleanup docker configs - remove redundant production and dev-specific shell scripts
3.6 KiB
Development Guide
Prerequisites
- Node.js >= 24
- pnpm >= 9
- Docker
First-time Setup
pnpm setup
This creates server/.env from the example, installs all dependencies, starts PostgreSQL, runs migrations, and seeds baseline data.
If you prefer to do it manually:
pnpm run db:up # start PostgreSQL
cp server/.env.example server/.env # first time only
pnpm install
pnpm run db:migrate
pnpm run db:seed
Running the App
pnpm dev
Starts the server and client concurrently with hot reload.
| Service | URL |
|---|---|
| API | http://localhost:3000/api |
| Client | http://localhost:5173 |
If PostgreSQL stopped (e.g. after a machine restart):
pnpm run db:up # then pnpm dev
Database Workflows
Apply pending migrations
After pulling changes that include new migrations:
pnpm run db:migrate
Add a schema change
- Edit the relevant file in
server/src/db/schema/ - Generate a migration:
This creates a new SQL file in
cd server && pnpm db:generate add-book-tagsserver/src/db/migrations/. Review it before applying. - Apply it:
pnpm run db:migrate
Pre-launch rule: Before the app ships, maintain a single baseline migration (
0000_*.sql) rather than stacking incremental ones. When adding a schema change pre-launch:rm -rf server/src/db/migrations docker compose -f docker-compose.dev.yml down -v pnpm run db:up cd server && pnpm db:generate baseline pnpm run db:migrateAfter go-live, never wipe migrations. Every change gets its own incremental migration.
Full database reset
Wipes all data, re-runs migrations, re-seeds, and clears generated files (covers, author images):
pnpm run db:reset
Use this when:
- Migrations are in a broken or inconsistent state
- A migration requires starting from scratch (e.g. column type change with no clean upgrade path)
- You want a known-clean local state
Inspect the database
cd server && pnpm db:studio
Opens Drizzle Studio in your browser for browsing and editing tables directly.
Testing
pnpm run test # all tests (server + client)
pnpm run test:server # server unit tests only
pnpm run test:client # client unit tests only
pnpm run test:e2e:smoke # e2e smoke suite (requires running DB)
Watch mode while working on a specific area:
cd server && pnpm test:watch
Code Quality
Run before pushing:
pnpm run verify:fast # lint + typecheck + tests (same as pre-push hook)
pnpm run verify # above + e2e smoke (run before opening a PR)
Individual checks:
pnpm run lint:check # check for lint errors
pnpm run lint:fix # auto-fix lint errors
pnpm run typecheck # server + client baseline typecheck
pnpm run typecheck:full # server + full client typecheck (slower)
Format:
cd server && npx prettier --write .
cd client && npx prettier --write .
Common Scenarios
Pulled changes that include a new migration
pnpm run db:migrate
Pulled changes that changed the DB schema significantly and your local state is stale
pnpm run db:reset
Something is wrong and you want a completely clean slate
pnpm run db:reset
If that is not enough (e.g. Docker volume is corrupted):
docker compose -f docker-compose.dev.yml down -v
pnpm run db:up
pnpm run db:migrate
pnpm run db:seed