Installation

Get CleanStack up and running in less than 5 minutes

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js ≄ 24.12.0
  • PNPM 10.26.2
  • Docker and Docker Compose

Quick Start

Step 1: Clone & Install

git clone https://github.com/axelhamil/nextjs-clean-architecture-starter cleanstack
cd cleanstack
pnpm install

Step 2: Setup Database

# Copy environment variables
cp .env.example .env

# Start PostgreSQL container
pnpm db

# Push database schema
pnpm db:push

The .env file should contain at minimum:

DATABASE_URL="postgresql://postgres:postgres@localhost:5432/cleanstack"

Step 3: Start Development

pnpm dev

Visit http://localhost:3000 to see your app running!

Available Commands

Development Commands

| Command | Description | |---------|-------------| | pnpm dev | Start development server (runs db:generate first) | | pnpm build | Build all packages and apps for production | | pnpm start | Start production server | | pnpm clean | Clean all build artifacts and node_modules |

Code Quality Commands

| Command | Description | |---------|-------------| | pnpm validate | Full validation (type-check + lint + test) | | pnpm quick-check | Fast check (type-check + lint only) | | pnpm type-check | TypeScript type checking (requires db:generate) | | pnpm check | Biome lint & format check (without fixing) | | pnpm format | Format code with Biome | | pnpm fix | Auto-fix Biome issues | | pnpm lint | Lint with Biome | | pnpm ci:check | CI-friendly check |

Database Commands

| Command | Description | |---------|-------------| | pnpm db | Start PostgreSQL container (Docker Compose) | | pnpm db:generate | Generate migrations from schema changes | | pnpm db:push | Push schema to database (dev only - no migrations) | | pnpm db:migrate | Run migrations (production) | | pnpm db:studio | Open Drizzle Studio UI |

Important: Always run pnpm db:generate before pnpm type-check or pnpm dev when you modify database schemas. TypeScript needs the generated types.

Testing Commands

| Command | Description | |---------|-------------| | pnpm test | Run all tests with Vitest | | pnpm test:watch | Run tests in watch mode | | pnpm test:coverage | Generate coverage report |

To run tests in a specific package:

cd apps/nextjs && pnpm test
cd packages/ddd-kit && pnpm test

Package Management

| Command | Description | |---------|-------------| | pnpm ui:add | Add shadcn/ui component | | pnpm install <package> | Install dependency |

Project Structure Overview

cleanstack/
ā”œā”€ā”€ apps/
│   └── nextjs/              # Main Next.js application
│       ā”œā”€ā”€ app/             # Next.js App Router (pages, layouts, routes)
│       ā”œā”€ā”€ common/          # DI container, env config, i18n
│       └── src/             # Clean Architecture layers
│           ā”œā”€ā”€ domain/      # Entities, Value Objects, Aggregates
│           ā”œā”€ā”€ application/ # Use Cases, DTOs, Port interfaces
│           ā”œā”€ā”€ adapters/    # Controllers, Repositories (in/out)
│           └── shared/      # Shared utilities
ā”œā”€ā”€ packages/
│   ā”œā”€ā”€ ddd-kit/         # DDD primitives (Entity, Result, Option, etc.)
│   ā”œā”€ā”€ drizzle/         # Database schema & ORM setup
│   ā”œā”€ā”€ ui/              # shadcn/ui components
│   ā”œā”€ā”€ test/            # Shared Vitest configuration
│   └── typescript-config/ # Shared TypeScript configs
└── turbo.json           # Turborepo configuration

Initial Setup Workflow

After installation, follow this recommended workflow:

1. Read Documentation

  • CLAUDE.md - Complete architecture guide and codebase context
  • .cursorrules - AI coding guidelines and architectural patterns
  • @packages/ddd-kit - Explore DDD primitives

2. Explore the Codebase

Start with these files:

# DDD primitives
packages/ddd-kit/src/entity.ts
packages/ddd-kit/src/value-object.ts
packages/ddd-kit/src/result.ts
packages/ddd-kit/src/option.ts

# Example domain implementations
apps/nextjs/src/domain/examples/

# Dependency injection setup
apps/nextjs/common/di/container.ts
apps/nextjs/common/di/types.ts

3. Try Helper Scripts

Generate boilerplate code:

# Create a new Use Case
./scripts/create-use-case.sh CreateUser

# Create a new Value Object
./scripts/create-value-object.sh Email

4. Run Validation

Ensure everything works:

pnpm validate

This runs:

  • Type checking
  • Linting
  • Tests

Database Setup Details

Docker Compose

The project includes a docker-compose.yml with PostgreSQL:

services:
  postgres:
    image: postgres:16
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: cleanstack

Start it with:

pnpm db
# or
docker compose up -d postgres

Schema Changes Workflow

When you modify database schemas:

# 1. Edit schema files in packages/drizzle/src/schema/
# 2. Generate migration
pnpm db:generate

# 3. Apply changes
pnpm db:push  # Dev: direct push (fast, no migrations)
# OR
pnpm db:migrate  # Prod: run migrations (versioned, safe)

# 4. TypeScript types are auto-generated
pnpm type-check  # Should pass now

Drizzle Studio

Explore your database with a visual interface:

pnpm db:studio

Opens https://local.drizzle.studio

Environment Variables

Required variables in .env:

# Database (required by Turborepo globally)
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/cleanstack"

# Optional: Add your own as needed
# NEXT_PUBLIC_API_URL="http://localhost:3000/api"
# EMAIL_SERVICE_KEY="your-key"

Validation is handled by apps/nextjs/common/env.ts using Zod:

import { z } from 'zod';

const envSchema = z.object({
  DATABASE_URL: z.string().url(),
  // Add more as needed
});

export const env = envSchema.parse(process.env);

Troubleshooting

TypeScript Errors After Schema Changes

Problem: pnpm type-check fails with database-related errors

Solution:

pnpm db:generate  # Regenerate types
pnpm type-check   # Should pass now

Turborepo Cache Issues

Problem: Changes not reflected, stale builds

Solution:

pnpm clean        # Clean all artifacts
pnpm install      # Reinstall dependencies
pnpm build        # Rebuild everything

Database Connection Errors

Problem: Cannot connect to database

Solution:

# Check if PostgreSQL is running
docker ps | grep postgres

# Restart container
docker compose down
docker compose up -d postgres

# Verify connection
psql postgresql://postgres:postgres@localhost:5432/cleanstack

Port Already in Use

Problem: Port 3000 or 5432 already in use

Solution:

# Find process using port
lsof -i :3000
lsof -i :5432

# Kill process or change port in .env

Next Steps

Now that you're set up:

  1. āœ… Read Architecture Docs - Visit /docs/architecture to understand Clean Architecture
  2. āœ… Explore Examples - Check apps/nextjs/src/domain/examples/
  3. āœ… Try Creating a Feature - Follow the Use Case pattern
  4. āœ… Run Tests - pnpm test to see examples
  5. āœ… Use AI Assistance - Read /docs/claude-code for AI development tips

Happy coding with CleanStack! šŸš€