5.7 KiB
Ollis Turborepo Test
A full-stack TypeScript monorepo demonstrating modern development practices with automatic API client generation and type-safe end-to-end data flow.
Architecture Overview
This monorepo showcases a type-safe, auto-generated API contract between backend and frontend:
Backend (Fastify) → OpenAPI Spec → Generated API Client → Frontend (SolidJS)
Key Design Decisions
-
OpenAPI-First API Design: The backend uses Fastify with
@fastify/swaggerto automatically generate OpenAPI specifications from TypeScript schemas. -
Automatic Client Generation: The
api-client-backendpackage uses@hey-api/openapi-tsto generate a fully typed API client from the OpenAPI spec, ensuring type safety across the stack. -
Turborepo Watch Mode: Development workflow uses Turborepo's watch feature to orchestrate the entire pipeline automatically - when you change an API schema, the OpenAPI spec is regenerated, the client is regenerated, and the frontend picks up changes via HMR.
-
PNPM Workspace: All packages are managed in a monorepo with workspace protocol for instant local dependency updates.
-
Environment-Based Configuration: Frontend uses Vite's environment variable system (
VITE_*prefix) for runtime configuration.
What's inside?
This Turborepo includes the following packages/apps:
Apps
frontend: a SolidJS app with CRUD UI for persons and petsbackend: a Fastify REST API with PostgreSQL and Kysely ORM
Packages
@olli/api-client-backend: Auto-generated TypeScript API client based on backend's OpenAPI spec@olli/ts-config: Shared TypeScript configurations
Utilities
- TypeScript for static type checking
- Biome for code formatting and linting
- Kysely for type-safe SQL queries
- Vitest for testing
Development Workflow
Initial Setup
- Copy environment files:
cp .env.example .env
cp apps/frontend/.env.example apps/frontend/.env
cp apps/backend/.env.example apps/backend/.env
- Start local dependencies (PostgreSQL):
docker compose up -d
- PGAdmin: http://localhost:5050
- Install dependencies:
pnpm install
Running Development Servers
The recommended way to develop is using Turborepo's watch mode:
pnpm run dev:watch
Or with global Turbo:
turbo watch dev:watch export-openapi generate
turbo watchonly works for non-persistent tasks. Sodevtasks are not affected, therefore we need to run thedev:watchtask here, so the apps actually watch changes by themselves.
What dev:watch Does
This single command orchestrates the entire development workflow:
-
Starts Development Servers (
dev:watchtask):- Backend: Runs on http://localhost:3000 with nodemon for auto-restart
- Frontend: Runs on http://localhost:5173 with Vite HMR
-
Watches for API Changes (
export-openapitask):- Monitors backend source files (
src/**/*.ts) - When API schemas change, automatically exports updated OpenAPI spec to
packages/api-client-backend/openapi.json
- Monitors backend source files (
-
Regenerates API Client (
generatetask):- Watches the OpenAPI spec file
- When spec changes, regenerates TypeScript client in
packages/api-client-backend/generated/ - Thanks to PNPM workspace linking, frontend immediately sees the updated types
-
Updates Frontend (automatic via Vite HMR):
- Vite detects changes in workspace dependencies
- Frontend auto-refreshes with new API types and methods
The Flow:
Backend code change
↓
Nodemon restarts backend server
↓
Turbo watch detects file change
↓
export-openapi script runs → generates openapi.json
↓
Turbo runs generate task → regenerates API client
↓
Vite HMR detects api-client-backend change
↓
Frontend reloads with updated types ✨
This workflow ensures zero manual steps - just change your API schema and watch it propagate through the entire stack!
Alternative Development Commands
Develop all apps and packages:
turbo dev
Develop a specific package:
turbo dev --filter=backend
turbo dev --filter=frontend
Build
Build all apps and packages:
turbo build
Build a specific package:
turbo build --filter=backend
Testing
Run all tests:
turbo test
Run tests in watch mode:
turbo test:watch
Project Structure
apps/
backend/ # Fastify API server
src/
features/ # Feature-based organization
demo/
*.routes.ts # API route handlers
*.schema.ts # Zod/TypeBox schemas
*.repository.ts
db/ # Database setup and migrations
scripts/
export-openapi.ts # OpenAPI spec generator
frontend/ # SolidJS web app
src/
person-crud.tsx # Person management UI
pet-crud.tsx # Pet management UI
api.ts # Configured API client
packages/
api-client-backend/ # Generated API client
generated/ # Auto-generated (don't edit!)
openapi.json # Source of truth from backend
Useful Links
Learn more about the power of Turborepo: