A modern full-stack monorepo starter featuring NestJS API with Vite for fast development and Next.js for the frontend.
- 🚀 Fast Development - NestJS with Vite for instant hot reload
- ⚡ Just-in-Time Compilation - No build step needed during development
- 📦 Turborepo - Efficient build system with caching
- 🎨 Next.js Apps - Multiple frontend applications
- 🔧 TypeScript - Full type safety across the monorepo
- 🎯 Shared Packages - Reusable UI components and configurations
- Node.js 18+ (we recommend using nodenv with version 24.1.0)
- npm (package manager)
- Docker and Docker Compose (for PostgreSQL database)
- Git (for cloning the repository)
# Clone the repository
git clone https://github.com/mrgmnn/turbo-starter.git
# Navigate to the project
cd turbo-starter
# Run bootstrap (installs dependencies, builds Prisma client on first run, and sets up database)
npm run bootstrap
# or use the shell script: ./scripts/bootstrap.shThe bootstrap process will:
- Install all npm dependencies
- Generate the Prisma client on first run (so dev doesn't fail if Prisma wasn't built yet)
- Check if Docker is running and start PostgreSQL if needed
- Prompt for a project name (default: "turbo-starter")
- Update
package.jsonwith the project name - Create the database (derived from project name)
- Generate and add
DATABASE_URLto.envfiles inapps/api/andpackages/prisma/
After setup completes:
- Define your database schema in
packages/prisma/schema/schema.prisma - Create and apply migrations when ready:
npx prisma migrate dev --name init - Start development:
npm run dev - View your data:
npx prisma studio
Tip: VS Code will prompt you to install recommended extensions for this project. Accept to get ESLint, Prettier, Prisma, Tailwind CSS IntelliSense, and more!
If you prefer manual setup:
# Start PostgreSQL
docker compose up -d
# Create database
docker exec -it postgres psql -U postgres -c "CREATE DATABASE turbostarter;"
# Create .env files with DATABASE_URL in apps/api/ and packages/prisma/
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/turbostarter?schema=public"
# First-time Prisma client build (if you didn't run bootstrap)
npm run -w @repo/prisma build
# Run migrations
npx prisma migrate dev --name initnpx prisma studio # Open Prisma Studio (Database GUI)
npx prisma migrate dev # Create and apply migrations
docker-compose down # Stop PostgreSQL
docker-compose down -v # Stop and remove dataNote: During development, Prisma automatically watches for schema changes and regenerates the client. The schema is in
packages/prisma/schema/schema.prisma.
Run all apps in development mode (including Prisma watcher):
npm run devRun the API with Prisma watcher:
npm run dev:apiRun the web app:
npm run dev:webThe applications run on the following ports during development:
- API (NestJS):
http://localhost:3000 - Web (Next.js):
http://localhost:8000
Port Convention: APIs use the
3xxxport range, while frontend applications use the8xxxport range. This convention helps organize services and avoid port conflicts as your monorepo grows.
Build all apps and packages:
npm run buildBuild specific apps:
npx turbo build --filter=api
npx turbo build --filter=webRun the API in production mode:
npm run start:prod --filter=api├── apps/
│ ├── api/ # NestJS API with Vite
│ └── web/ # Next.js web application
├── packages/
│ ├── ui/ # Shared UI component library with shadcn/ui
│ ├── prisma/ # Prisma schema and database client
│ ├── eslint-config/ # Shared ESLint configurations
│ └── typescript-config/ # Shared TypeScript configurations
├── docker-compose.yml # PostgreSQL container configuration
├── screenshot.png # Project screenshot
└── turbo.json # Turborepo configuration
api: NestJS REST API with Vite for developmentweb: Next.js web application with React 19, Tailwind CSS v4, and shadcn/ui@repo/ui: Shared UI component library with shadcn/ui components@repo/prisma: Prisma schema and generated client@repo/eslint-config: ESLint configurations@repo/typescript-config: TypeScript configurations
- NestJS - Progressive Node.js framework
- Vite - Fast development server with HMR
- Prisma - Next-generation ORM
- PostgreSQL - Relational database
- TypeScript - Type safety
- Next.js - React framework with App Router
- React 19 - Latest React with modern features
- Tailwind CSS v4 - Utility-first CSS framework
- shadcn/ui - Re-usable component library
- next-themes - Dark mode support
@repo/ui- Shared UI component library with shadcn/ui components@repo/prisma- Shared Prisma schema and client@repo/eslint-config- Shared ESLint configurations@repo/typescript-config- Shared TypeScript configurations
- Turborepo - High-performance build system with caching
- ESLint - Code linting
- Prettier - Code formatting
Using Vite in this monorepo setup enables Just-in-Time (JIT) compilation for shared packages, eliminating the need to rebuild packages during development. This provides:
- ⚡ Instant hot module replacement across the monorepo
- 🎯 Fast startup times with JIT compilation
- 🔄 No build step needed for packages during development
- 📦 Seamless integration between apps and shared packages
This project uses Fontsource for self-hosted font management. Fontsource provides optimized, self-hosted fonts that don't require external CDN requests.
The web app uses Source Sans Pro in multiple weights (300, 400, 900).
-
Install the font package:
npm install @fontsource/<font-name> -w web
-
Import the font weights in
apps/web/app/globals.css:@import '@fontsource/source-sans-pro/300.css'; @import '@fontsource/source-sans-pro/400.css'; @import '@fontsource/source-sans-pro/900.css';
-
Update the font family:
body { font-family: 'Source Sans Pro', sans-serif; }
- Performance: Fonts are bundled and served from your domain
- Privacy: No third-party requests to Google Fonts or other CDNs
- Reliability: No dependency on external services
- Optimization: Only load the weights and subsets you need
# Development
npm run dev # Start all apps
npm run dev --filter=api # Start API only
# Build
npm run build # Build all apps
npm run build --filter=api # Build API only
# Lint
npm run lint # Lint all packages
# Format
npm run format # Format all code# Run unit tests for API
npm run test --filter=api
# Run tests in watch mode
npm run test:watch --filter=api
# Run tests with coverage
npm run test:cov --filter=api
# Run e2e tests
npm run test:e2e --filter=apiIf you see an error like Error: listen EADDRINUSE: address already in use :::3000:
# Find and kill the process using the port
lsof -ti:3000 | xargs kill -9If Prisma can't connect to the database:
-
Check if PostgreSQL container is running:
docker ps
-
Restart the container:
docker-compose down docker-compose up -d
-
Verify the database exists:
docker exec -it postgres psql -U postgres -l -
Check your
.envfiles - Make sure bothapps/api/.envandpackages/prisma/.envhave the correctDATABASE_URL
If you see Cannot find module '@prisma/client':
npx prisma generateIf you encounter module resolution issues:
# Clean install
rm -rf node_modules
rm -rf apps/*/node_modules
rm -rf packages/*/node_modules
npm install- NestJS Documentation
- Next.js Documentation
- shadcn/ui Documentation
- Turborepo Documentation
- Vite Documentation
- Prisma Documentation
- Tailwind CSS Documentation
- Fontsource
- nodenv Documentation
MIT
