A production-ready Turborepo monorepo for building full-stack TypeScript applications with end-to-end type safety.
- Runtime: Node.js 22+
- Framework: Fastify - Fast and low overhead web framework
- API Layer:
- tRPC - End-to-end typesafe APIs for internal/frontend communication
- REST/OpenAPI - External product APIs with automatic Swagger documentation
- Database: PostgreSQL with Orchid ORM
- API Gateway: API key authentication, rate limiting, CORS validation, IP whitelisting, subscription management
- Observability: OpenTelemetry integration
- Security: Helmet, CORS, Rate Limiting, OAuth2 (Google)
- Deployment: Docker support with automated migrations
- Framework: React 19 with Vite
- Routing: React Router
- Data Fetching: TanStack Query + tRPC Client
- Type Safety: Direct TypeScript imports from backend
- Package Manager: Yarn (v1.22.22)
- Monorepo: Turborepo
- Linting: Biome
- Formatting: Biome
- TypeScript: v5.8.x with strict mode
.
βββ apps/
β βββ backend/ # Fastify server
β β βββ src/
β β β βββ modules/ # Feature modules
β β β β βββ api-gateway/ # External REST API with OpenAPI
β β β β βββ auth/ # OAuth2 + session management
β β β β βββ journal-entries/ # Journal entry feature (tRPC)
β β β β βββ users/ # User management (tRPC)
β β β β βββ teams/ # Teams & members
β β β β βββ subscriptions/ # API subscriptions
β β β β βββ logs/ # API request logs
β β β βββ routers/ # Route aggregation
β β β β βββ app.router.ts # Main router
β β β β βββ openapi.plugin.ts # OpenAPI/Swagger setup
β β β β βββ trpc.router.ts # tRPC routes
β β β βββ db/ # Database layer
β β β βββ configs/ # App configuration
β β β βββ middlewares/ # Global middleware
β β β βββ server.ts # Entry point
β β β βββ app.ts # Fastify setup
β β β βββ trpc.ts # tRPC initialization
β β βββ Dockerfile # Docker configuration
β β βββ DEPLOYMENT.md # Deployment guide
β β βββ package.json
β βββ frontend/ # React + Vite
β βββ src/
β β βββ components/ # Reusable components
β β βββ pages/ # Page components
β β βββ modules/ # Feature modules
β β βββ App.tsx
β β βββ router.tsx
β βββ package.json
βββ packages/
β βββ typescript-config/ # Shared TypeScript configs
β βββ ui-mui/ # Material-UI component library
β βββ zod-schemas/ # Shared Zod schemas for validation
βββ turbo.json
βββ package.json
- Node.js 22+
- Yarn 1.22.22
- PostgreSQL database
- Clone the repository:
git clone git@github.com:teziapp/connected-repo-starter.git
cd connected-repo-starter- Install dependencies:
yarn install- Set up environment variables:
# Copy environment examples
cp .env.example .env
cp apps/backend/.env.example apps/backend/.env
cp apps/frontend/.env.example apps/frontend/.env-
Configure your database connection in
apps/backend/.env -
Create a PostgreSQL database, run migrations & seed data:
yarn run db create;
yarn run db up;
yarn run db seed;Start both frontend and backend in development mode:
yarn devOr run them individually:
# Backend only (http://localhost:3000)
cd apps/backend && yarn dev
# Frontend only (http://localhost:5173)
cd apps/frontend && yarn devyarn dev- Start all apps in watch modeyarn build- Build all apps and packagesyarn lint- Run Biome linter across all workspacesyarn format- Format code with Biomeyarn check-types- Type check all workspacesyarn clean- Remove node_modules and build artifacts
# Build and start the backend
cd apps/backend
yarn build
yarn starttRPC for Internal APIs:
- Type-safe APIs for frontend-backend communication
- Zero code generation - types flow automatically
- Routes:
/trpc/* - Example:
trpc.journalEntry.create.useMutation()
REST/OpenAPI for External APIs:
- Automatic Swagger documentation at
/api/documentation - OpenAPI 3.1.0 spec generation from Zod schemas
- Routes:
/api/v1/* - Full middleware chain: API key auth, rate limiting, CORS validation, IP whitelist, subscription tracking
Authentication & Authorization:
- API key-based authentication (
x-api-key+x-team-idheaders) - Team-based access control with scrypt-hashed API keys
- User-specific subscriptions (teamId + userId + productSku)
- Bearer token authentication for webhooks
Security:
- Global rate limiting (2 req/sec, burst 5 req/10sec in production)
- Global CORS allows all origins; team-specific CORS validation via middleware
- Per-team rate limiting (configurable requests per minute)
- CORS validation against team's allowed domains with preflight handling
- IP whitelist per team
- OpenAPI security schemes (apiKey, teamId headers)
- Request logging to
api_product_request_logstable - 404 route protection with stricter rate limiting
Subscription Management:
- Quota enforcement per subscription
- Atomic real-time usage tracking
- 90% usage threshold triggers webhook alert
- Webhook queue with retry logic (3 max attempts, exponential backoff)
- Batch processing limit: 50 webhooks per run
- Configuration constants in
api-gateway/constants/apiGateway.constants.ts
The monorepo achieves full type safety without code generation:
- Backend exports router type from
router.trpc.ts - Frontend imports this type directly via TypeScript workspace references
- Shared Zod schemas in
packages/zod-schemas/:- Entity schemas:
<entity>CreateInputZod,<entity>UpdateInputZod,<entity>SelectAllZod - API product schemas with OpenAPI metadata
- Enum definitions for request status, webhook status, etc.
- Entity schemas:
- All API calls have autocomplete and compile-time type checking
// tRPC usage (internal)
const { data } = trpc.journalEntry.getAll.useQuery();
const create = trpc.journalEntry.create.useMutation();
// OpenAPI usage (external)
// See interactive docs at /api/documentation- ORM: Orchid ORM with automatic snake_case conversion
- Type Safety: Zod schemas for input validation across backend and frontend
- Timestamps: Epoch milliseconds (number) not Date objects
- Naming: Descriptive IDs (
userId,teamId) and FKs (authorUserId) - Tables: Organized by feature module in
modules/<feature>/tables/ - Indexes: Composite indexes on frequently queried columns for performance
Key tables: users, sessions, teams, team_members, journal_entries, subscriptions, api_product_request_logs, webhook_call_queue
Multi-layer error handling system:
- tRPC Layer: Transforms errors into structured responses
- Error Parser: Converts database/validation errors to user-friendly messages
- Fastify Handler: Catches unhandled errors
Global:
- Rate limiting: 2 req/sec, burst 5 req/10sec (production)
- CORS allows all origins globally (team validation via middleware)
- Helmet security headers
- 404 route protection (stricter rate limiting)
- Environment-based configuration
API Gateway:
- API key authentication (scrypt hashed) via x-api-key + x-team-id headers
- Team-based access control
- Per-team rate limiting (configurable per minute)
- Per-team CORS validation against allowedDomains with preflight handling
- Per-team IP whitelist validation
- OpenAPI security schemes defined
- Internal routes secured by bearer token (INTERNAL_API_SECRET)
- Webhook endpoints secured by bearer token (team.subscriptionAlertWebhookBearerToken)
- OpenTelemetry integration for tracing
- Custom spans for tRPC errors
- Create table in
apps/backend/src/modules/<feature>/tables/<entity>.table.ts- Use descriptive IDs:
userId,teamId(not genericid) - Use descriptive FKs:
authorUserId(not justauthorId) - Use
timestampNumberfor timestamps (epoch milliseconds)
- Use descriptive IDs:
- Create Zod schemas in
packages/zod-schemas/src/<entity>.zod.ts - Register table in
apps/backend/src/db/db.ts - Run
yarn run db g <migration_name>thenyarn run db up
- Import schema from
@connected-repo/zod-schemas/<entity>.zod - Create procedure in
apps/backend/src/modules/<feature>/<feature>.trpc.ts - Register in
apps/backend/src/routers/trpc.router.ts - Use
protectedProcedurefor operations requiring auth - Frontend auto-gets types via tRPC router type import
- Define Zod schemas in
packages/zod-schemas/src/<entity>.zod.ts - Add product to
API_PRODUCTSarray inpackages/zod-schemas/src/enums.zod.ts - Create handler in
apps/backend/src/modules/api-gateway/handlers/<product>.handler.ts - Add route in
apps/backend/src/modules/api-gateway/api-gateway.router.ts:- Use
.withTypeProvider<FastifyZodOpenApiTypeProvider>() - Apply middleware chain (apiKeyAuth, CORS, whitelist, rateLimit, subscriptionCheck)
- Use
- Test via Swagger UI at
/api/documentation
- Create component in
apps/frontend/src/pages/ormodules/<feature>/pages/ - Add route in
apps/frontend/src/router.tsxwith lazy loading - Use tRPC hooks for data fetching
This monorepo uses Turborepo for task orchestration. Key tasks:
build- Builds with dependency graph awarenessdev- Runs development servers (persistent, no cache)check-types- Type checking across workspacesclean- Cleanup task
Learn more:
- CLAUDE.md - Comprehensive architecture and development guide
- apps/backend/CLAUDE.md - Backend-specific guidance
- apps/backend/DEPLOYMENT.md - Deployment guide with Docker
- apps/backend/src/modules/api-gateway/WEBHOOK_CRON_SETUP.md - Webhook processor setup
- apps/frontend/CLAUDE.md - Frontend React patterns and best practices
- packages/CLAUDE.md - Package architecture overview
- packages/zod-schemas/CLAUDE.md - Zod schema documentation
Interactive API Documentation:
- Swagger UI: http://localhost:3000/api/documentation
- OpenAPI Spec: http://localhost:3000/api/documentation/json
Endpoints:
- tRPC APIs: http://localhost:3000/trpc
- REST APIs: http://localhost:3000/api/v1/*
- Health Check: http://localhost:3000/health
- OAuth2: http://localhost:3000/oauth2/google
- Internal APIs: http://localhost:3000/internal/* (secured by bearer token)
[AGPL-3.0] (./LICENSE) Copyright (c) 2025 Tezi Communications LLP, India