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

  1. OpenAPI-First API Design: The backend uses Fastify with @fastify/swagger to automatically generate OpenAPI specifications from TypeScript schemas.

  2. Automatic Client Generation: The api-client-backend package uses @hey-api/openapi-ts to generate a fully typed API client from the OpenAPI spec, ensuring type safety across the stack.

  3. 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.

  4. PNPM Workspace: All packages are managed in a monorepo with workspace protocol for instant local dependency updates.

  5. 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 pets
  • backend: 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

Development Workflow

Initial Setup

  1. Copy environment files:
cp .env.example .env
cp apps/frontend/.env.example apps/frontend/.env
cp apps/backend/.env.example apps/backend/.env
  1. Start local dependencies (PostgreSQL):
docker compose up -d
  1. 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 watch only works for non-persistent tasks. So dev tasks are not affected, therefore we need to run the dev:watch task here, so the apps actually watch changes by themselves.

What dev:watch Does

This single command orchestrates the entire development workflow:

  1. Starts Development Servers (dev:watch task):

  2. Watches for API Changes (export-openapi task):

    • Monitors backend source files (src/**/*.ts)
    • When API schemas change, automatically exports updated OpenAPI spec to packages/api-client-backend/openapi.json
  3. Regenerates API Client (generate task):

    • 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
  4. 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

Learn more about the power of Turborepo:

Description
No description provided
Readme 329 KiB
Languages
TypeScript 97.4%
Dockerfile 2%
HTML 0.6%