T3 Stack (Next.js + tRPC + Prisma)
Full-stack TypeScript application with tRPC, Prisma, and NextAuth.
Overview
Next.js is a React framework for building production-ready web applications with server-side rendering, static site generation, and full-stack capabilities. Developed by Vercel and first released in 2016, Next.js has become the de facto standard for React applications requiring SEO optimization, fast initial page loads, and developer productivity. It provides file-based routing, automatic code splitting, and built-in optimization features that eliminate the need for complex webpack configurations. The T3 Stack combines Next.js with tRPC (TypeScript Remote Procedure Call), Prisma ORM, and NextAuth for authentication, creating an end-to-end type-safe development experience. This stack leverages PostgreSQL for reliable data persistence with ACID compliance, Redis for high-performance session storage and caching, and NGINX for production-grade reverse proxying and static asset serving. The combination delivers sub-millisecond cache responses through Redis while maintaining complex relational data integrity with PostgreSQL. Organizations choose this stack for its complete TypeScript integration from database schema to frontend components, eliminating runtime type errors and improving developer productivity. Startups building SaaS platforms, e-commerce sites, and content management systems benefit from the rapid development cycle, while enterprises appreciate the type safety, scalability through PostgreSQL's table partitioning, and NGINX's proven ability to handle high-traffic loads with minimal resource consumption.
Key Features
- End-to-end type safety from Prisma database schema through tRPC API routes to Next.js frontend components
- Server-side rendering and static site generation with automatic code splitting and image optimization
- tRPC client-server communication with automatic TypeScript inference and runtime validation
- NextAuth integration supporting OAuth providers like Discord, GitHub, and Google with session management
- Prisma ORM with database migrations, relation management, and automatic TypeScript client generation
- PostgreSQL JSONB support for flexible document storage alongside traditional relational data
- Redis-based session persistence with sub-millisecond response times for user authentication
- NGINX reverse proxy with HTTP/2 support, SSL termination, and static asset caching
Common Use Cases
- 1SaaS platforms requiring user authentication, subscription management, and complex business logic
- 2E-commerce applications with product catalogs, user accounts, and real-time inventory management
- 3Content management systems with author permissions, publishing workflows, and SEO optimization
- 4Social platforms with user profiles, real-time messaging, and activity feeds
- 5Internal business dashboards with role-based access control and data visualization
- 6API-first applications serving both web and mobile clients with type-safe endpoints
- 7Multi-tenant applications requiring data isolation and user-specific customizations
Prerequisites
- Docker and Docker Compose installed with at least 2GB available RAM for PostgreSQL and Redis
- Node.js knowledge and familiarity with React components and TypeScript syntax
- Basic understanding of SQL queries and relational database concepts for Prisma usage
- OAuth application credentials from Discord or other providers for NextAuth configuration
- Available ports 80, 443, 3000, and 5432 for NGINX, Next.js, and PostgreSQL services
- SSL certificates for production HTTPS setup through NGINX reverse proxy
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 t3-app: 3 build: 4 context: .5 dockerfile: Dockerfile6 ports: 7 - "3000:3000"8 environment: 9 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}10 NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}11 NEXTAUTH_URL: http://localhost:300012 DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID}13 DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET}14 depends_on: 15 postgres: 16 condition: service_healthy17 redis: 18 condition: service_started19 networks: 20 - t3-net21 restart: unless-stopped2223 postgres: 24 image: postgres:16-alpine25 environment: 26 POSTGRES_USER: ${POSTGRES_USER}27 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}28 POSTGRES_DB: ${POSTGRES_DB}29 volumes: 30 - postgres_data:/var/lib/postgresql/data31 healthcheck: 32 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]33 interval: 10s34 timeout: 5s35 retries: 536 networks: 37 - t3-net38 restart: unless-stopped3940 redis: 41 image: redis:7-alpine42 volumes: 43 - redis_data:/data44 networks: 45 - t3-net46 restart: unless-stopped4748 nginx: 49 image: nginx:alpine50 ports: 51 - "80:80"52 - "443:443"53 volumes: 54 - ./nginx.conf:/etc/nginx/nginx.conf:ro55 - ./certs:/etc/nginx/certs:ro56 depends_on: 57 - t3-app58 networks: 59 - t3-net60 restart: unless-stopped6162volumes: 63 postgres_data: 64 redis_data: 6566networks: 67 t3-net: 68 driver: bridge.env Template
.env
1# PostgreSQL2POSTGRES_USER=t3app3POSTGRES_PASSWORD=secure_postgres_password4POSTGRES_DB=t3app56# NextAuth7NEXTAUTH_SECRET=$(openssl rand -base64 32)89# Discord OAuth (optional)10DISCORD_CLIENT_ID=11DISCORD_CLIENT_SECRET=Usage Notes
- 1Create T3 app: npm create t3-app@latest
- 2T3 App at http://localhost:3000
- 3Run Prisma migrations: npx prisma migrate deploy
- 4Type-safe API with tRPC
Individual Services(4 services)
Copy individual services to mix and match with your existing compose files.
t3-app
t3-app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}
NEXTAUTH_URL: http://localhost:3000
DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID}
DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET}
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
networks:
- t3-net
restart: unless-stopped
postgres
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test:
- CMD-SHELL
- pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}
interval: 10s
timeout: 5s
retries: 5
networks:
- t3-net
restart: unless-stopped
redis
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
networks:
- t3-net
restart: unless-stopped
nginx
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
depends_on:
- t3-app
networks:
- t3-net
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 t3-app:5 build:6 context: .7 dockerfile: Dockerfile8 ports:9 - "3000:3000"10 environment:11 DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}12 NEXTAUTH_SECRET: ${NEXTAUTH_SECRET}13 NEXTAUTH_URL: http://localhost:300014 DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID}15 DISCORD_CLIENT_SECRET: ${DISCORD_CLIENT_SECRET}16 depends_on:17 postgres:18 condition: service_healthy19 redis:20 condition: service_started21 networks:22 - t3-net23 restart: unless-stopped2425 postgres:26 image: postgres:16-alpine27 environment:28 POSTGRES_USER: ${POSTGRES_USER}29 POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}30 POSTGRES_DB: ${POSTGRES_DB}31 volumes:32 - postgres_data:/var/lib/postgresql/data33 healthcheck:34 test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]35 interval: 10s36 timeout: 5s37 retries: 538 networks:39 - t3-net40 restart: unless-stopped4142 redis:43 image: redis:7-alpine44 volumes:45 - redis_data:/data46 networks:47 - t3-net48 restart: unless-stopped4950 nginx:51 image: nginx:alpine52 ports:53 - "80:80"54 - "443:443"55 volumes:56 - ./nginx.conf:/etc/nginx/nginx.conf:ro57 - ./certs:/etc/nginx/certs:ro58 depends_on:59 - t3-app60 networks:61 - t3-net62 restart: unless-stopped6364volumes:65 postgres_data:66 redis_data:6768networks:69 t3-net:70 driver: bridge71EOF7273# 2. Create the .env file74cat > .env << 'EOF'75# PostgreSQL76POSTGRES_USER=t3app77POSTGRES_PASSWORD=secure_postgres_password78POSTGRES_DB=t3app7980# NextAuth81NEXTAUTH_SECRET=$(openssl rand -base64 32)8283# Discord OAuth (optional)84DISCORD_CLIENT_ID=85DISCORD_CLIENT_SECRET=86EOF8788# 3. Start the services89docker compose up -d9091# 4. View logs92docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/t3-stack-prisma/run | bashTroubleshooting
- NextAuth NEXTAUTH_URL must match your domain exactly, including protocol and port for callback URLs to work
- Prisma migrate deploy fails: Ensure PostgreSQL health check passes and DATABASE_URL connection string is correct
- tRPC query fails with network error: Check that t3-app service can reach postgres and redis containers on t3-net network
- NGINX 502 Bad Gateway: Verify t3-app service is running on port 3000 and nginx.conf upstream configuration points to correct container name
- Redis connection refused: Confirm redis service started successfully and Next.js Redis client uses 'redis:6379' as connection string
- Build context errors: Ensure Dockerfile and package.json exist in current directory when running docker-compose up
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
nextjspostgresqlredisnginx
Tags
#t3-stack#nextjs#trpc#prisma#typescript
Category
Full Web StacksAd Space
Shortcuts: C CopyF FavoriteD Download