Skip to content

A production-ready, full-stack TypeScript starter template with Next.js 16 frontend/backend, AWS infrastructure managed by Pulumi, PostgreSQL with Drizzle ORM, and complete SaaS features including authentication, payments, monitoring, and email.

License

Notifications You must be signed in to change notification settings

martin-c-peutz/typescript-starter

Repository files navigation

Next.js 16 + Pulumi AWS Production Starter Template

A production-ready, full-stack TypeScript starter template with Next.js 16 frontend/backend, AWS infrastructure managed by Pulumi, PostgreSQL with Drizzle ORM, and complete SaaS features including authentication, payments, monitoring, and email.

✨ Features

This starter template provides everything you need to build and deploy a modern SaaS application:

  • πŸš€ Full-stack TypeScript - End-to-end type safety from database to frontend
  • ⚑ Next.js 16 - App Router, React Server Components, and Server Actions
  • πŸ” Authentication - Better Auth with email/password and OAuth (Google, GitHub, Apple)
  • πŸ’³ Payments - Stripe integration with subscription management and webhooks
  • πŸ—„οΈ Database - PostgreSQL 16 with Drizzle ORM and migrations
  • ☁️ Infrastructure - AWS resources managed with Pulumi (VPC, RDS, ECS, S3, CloudFront, SES)
  • πŸ“Š Monitoring - Sentry error tracking, PostHog analytics, and CloudWatch logs
  • πŸ“§ Email - React Email templates with AWS SES integration
  • 🌍 Internationalization - Multi-language support with next-intl
  • πŸ“ Blog - MDX-based blog system with dynamic routing
  • πŸ”” Real-time - Server-Sent Events (SSE) support
  • πŸ” SEO - Dynamic sitemap and robots.txt generation
  • πŸ§ͺ Testing - Vitest for unit/integration tests, Playwright for E2E tests
  • 🎨 UI Components - shadcn/ui with Tailwind CSS 4

Tech Stack

Frontend

  • Next.js 16 (App Router)
  • React 19
  • TypeScript 5.7+
  • Tailwind CSS 4
  • shadcn/ui components
  • Lucide React icons

Backend

  • Next.js 16 API Routes
  • tRPC 11 for type-safe APIs
  • Better Auth for authentication
  • Stripe for payments
  • React Email for transactional emails

Database

  • PostgreSQL 16
  • Drizzle ORM
  • Drizzle Kit for migrations

Infrastructure

  • Pulumi (TypeScript) for IaC
  • AWS (VPC, RDS, ECS, S3, CloudFront, SES, etc.)

πŸ“‹ Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js 20.0.0 or higher
  • pnpm 9.0.0 or higher (package manager)
  • Docker & Docker Compose (for local development)
  • Git (for version control)

Optional (for deployment)

  • AWS account with appropriate permissions
  • Pulumi CLI (Installation guide)
  • Stripe account (test mode for development, production for deployment)

Getting Started

1. Clone and Install

git clone <repo-url>
cd typescript-starter
pnpm install

2. Environment Variables

Create a .env.local file in the apps/web directory with the following variables:

cd apps/web
touch .env.local

Required variables:

# Database
DATABASE_URL=postgresql://user:password@localhost:5432/dbname

# Authentication
BETTER_AUTH_SECRET=your-secret-key-min-32-characters-long
BETTER_AUTH_URL=http://localhost:3000

# Application
NEXT_PUBLIC_APP_URL=http://localhost:3000
NODE_ENV=development

Optional variables (for full functionality):

# OAuth Providers (optional)
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
APPLE_CLIENT_ID=your-apple-client-id
APPLE_CLIENT_SECRET=your-apple-client-secret

# Stripe (optional, for payments)
STRIPE_SECRET_KEY=sk_test_...
STRIPE_PUBLISHABLE_KEY=pk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

# AWS SES (optional, for emails)
AWS_SES_REGION=us-east-1
AWS_SES_FROM_EMAIL=noreply@yourdomain.com
AWS_SES_FROM_NAME=Your App Name

# Redis (optional, for rate limiting)
UPSTASH_REDIS_REST_URL=https://...
UPSTASH_REDIS_REST_TOKEN=...

# Monitoring (optional)
SENTRY_DSN=https://...
NEXT_PUBLIC_SENTRY_DSN=https://...
NEXT_PUBLIC_POSTHOG_KEY=phc_...
NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com

Note: Generate BETTER_AUTH_SECRET using: openssl rand -base64 32

3. Start Local Services

Start PostgreSQL and Redis using Docker Compose:

# From the project root
docker-compose up -d

This will start:

  • PostgreSQL 16 on port 5432
  • Redis 7 on port 6379

Verify services are running:

docker ps

You should see both postgres and redis containers running.

4. Database Setup

Set up the database schema and seed initial data:

# Navigate to the web app
cd apps/web

# Generate database migrations from schema
pnpm db:generate

# Apply migrations to the database
pnpm db:migrate

# (Optional) Seed the database with sample data
pnpm db:seed

Tip: Use pnpm db:studio to open Drizzle Studio, a visual database browser.

5. Start Development Server

Start the development server:

# From the project root
pnpm dev

Or from the web app directory:

cd apps/web
pnpm dev

The application will be available at http://localhost:3000.

Note: The dev server uses Turbopack by default for faster builds. If you encounter issues, you can run without Turbopack by modifying the dev script in apps/web/package.json.

πŸ“ Project Structure

typescript-starter/
β”œβ”€β”€ apps/
β”‚   └── web/                          # Next.js application
β”‚       β”œβ”€β”€ app/                      # App Router (Next.js 16)
β”‚       β”‚   β”œβ”€β”€ [locale]/            # Internationalized routes
β”‚       β”‚   β”‚   β”œβ”€β”€ (auth)/          # Authentication routes
β”‚       β”‚   β”‚   β”œβ”€β”€ (dashboard)/     # Protected dashboard routes
β”‚       β”‚   β”‚   β”œβ”€β”€ (marketing)/     # Public marketing pages
β”‚       β”‚   β”‚   └── blog/            # Blog pages (MDX)
β”‚       β”‚   β”œβ”€β”€ api/                 # API routes
β”‚       β”‚   β”‚   β”œβ”€β”€ auth/           # Auth endpoints
β”‚       β”‚   β”‚   β”œβ”€β”€ trpc/           # tRPC handler
β”‚       β”‚   β”‚   β”œβ”€β”€ sse/            # Server-Sent Events
β”‚       β”‚   β”‚   └── webhooks/       # Webhook handlers
β”‚       β”‚   β”œβ”€β”€ sitemap.ts          # Dynamic sitemap
β”‚       β”‚   └── robots.ts            # Dynamic robots.txt
β”‚       β”œβ”€β”€ components/              # React components
β”‚       β”‚   β”œβ”€β”€ ui/                  # shadcn/ui components
β”‚       β”‚   β”œβ”€β”€ auth/               # Auth components
β”‚       β”‚   β”œβ”€β”€ dashboard/          # Dashboard components
β”‚       β”‚   └── todos/              # Todo components
β”‚       β”œβ”€β”€ lib/                     # Utilities and configurations
β”‚       β”‚   β”œβ”€β”€ i18n/               # Internationalization
β”‚       β”‚   β”œβ”€β”€ auth.ts             # Auth configuration
β”‚       β”‚   β”œβ”€β”€ db.ts               # Database client
β”‚       β”‚   β”œβ”€β”€ trpc.ts             # tRPC setup
β”‚       β”‚   └── stripe.ts           # Stripe integration
β”‚       β”œβ”€β”€ server/                  # Server-side code
β”‚       β”‚   β”œβ”€β”€ db/                 # Database schema & queries
β”‚       β”‚   β”œβ”€β”€ trpc/               # tRPC routers & procedures
β”‚       β”‚   └── services/           # Business logic services
β”‚       β”œβ”€β”€ emails/                  # React Email templates
β”‚       β”œβ”€β”€ content/                 # MDX blog posts
β”‚       β”œβ”€β”€ messages/                # i18n translation files
β”‚       β”œβ”€β”€ drizzle/                 # Database migrations
β”‚       β”œβ”€β”€ tests/                   # Test files
β”‚       β”‚   β”œβ”€β”€ e2e/                # Playwright E2E tests
β”‚       β”‚   β”œβ”€β”€ integration/        # Integration tests
β”‚       β”‚   └── unit/               # Unit tests
β”‚       └── scripts/                 # Utility scripts
β”‚
β”œβ”€β”€ packages/
β”‚   └── infrastructure/              # Pulumi infrastructure as code
β”‚       β”œβ”€β”€ database.ts             # RDS configuration
β”‚       β”œβ”€β”€ compute.ts              # ECS configuration
β”‚       β”œβ”€β”€ network.ts              # VPC configuration
β”‚       └── ...
β”‚
β”œβ”€β”€ docker-compose.yml               # Local development services
β”œβ”€β”€ turbo.json                       # Turborepo configuration
β”œβ”€β”€ pnpm-workspace.yaml              # pnpm workspace config
└── README.md                        # This file

πŸ› οΈ Development

Available Scripts

Run these commands from the project root or from apps/web:

Development

pnpm dev              # Start development server (with Turbopack)
pnpm build            # Build for production
pnpm start            # Start production server (after build)

Database

pnpm db:generate      # Generate migrations from schema changes
pnpm db:migrate       # Apply migrations to database
pnpm db:push          # Push schema directly (dev only, no migrations)
pnpm db:studio        # Open Drizzle Studio (visual DB browser)
pnpm db:seed          # Seed database with sample data

Testing

pnpm test             # Run unit and integration tests (Vitest)
pnpm test:ui          # Run tests with interactive UI
pnpm test:coverage    # Run tests with coverage report
pnpm test:e2e         # Run end-to-end tests (Playwright)
pnpm test:e2e:ui      # Run E2E tests with Playwright UI

Code Quality

pnpm lint             # Lint code with Biome
pnpm lint:fix         # Fix linting issues automatically
pnpm format           # Format code with Biome
pnpm type-check       # Type check with TypeScript

Email Development

pnpm email:dev        # Start email preview server

Docker

pnpm docker:build     # Build Docker image
pnpm docker:run       # Run Docker container

Database Management

Drizzle Studio - Visual database browser:

pnpm db:studio

Opens a web interface at http://localhost:4983 where you can:

  • Browse tables and data
  • Run queries
  • Edit records
  • View relationships

Email Preview

Preview React Email templates locally:

pnpm email:dev

This starts a development server where you can preview all email templates.

Type Safety

This project uses end-to-end type safety:

  • Database schema β†’ TypeScript types (Drizzle)
  • API routes β†’ Type-safe clients (tRPC)
  • Environment variables β†’ Validated at runtime (Zod)
  • Component props β†’ TypeScript interfaces

Run pnpm type-check to verify type safety across the entire codebase.

πŸš€ Deployment

This project uses Pulumi for infrastructure as code on AWS. For detailed deployment instructions, see the Deployment Guide.

Quick Start

  1. Install Pulumi CLI: Installation guide

  2. Configure AWS credentials:

    aws configure
  3. Initialize and deploy infrastructure:

    cd packages/infrastructure
    pulumi stack init production
    pulumi config set aws:region us-east-1
    pulumi preview  # Review changes
    pulumi up       # Deploy

What Gets Deployed

  • VPC - Isolated network environment
  • RDS PostgreSQL - Managed database
  • ECS Fargate - Containerized application
  • Application Load Balancer - Traffic distribution
  • S3 + CloudFront - Static asset hosting
  • AWS SES - Email delivery
  • Secrets Manager - Secure environment variables

See docs/DEPLOYMENT.md for complete deployment guide.

πŸ§ͺ Testing

This project includes comprehensive testing setup. For detailed testing documentation, see the Testing Guide.

Quick Start

# Run all tests
pnpm test

# Run E2E tests
pnpm test:e2e

# Run with coverage
pnpm test:coverage

Test Structure

  • Unit Tests (tests/unit/) - Test individual functions and utilities
  • Integration Tests (tests/integration/) - Test API endpoints and tRPC procedures
  • E2E Tests (tests/e2e/) - Test full user flows with Playwright

See docs/TESTING.md for complete testing guide.

πŸ“š Documentation

🀝 Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes
  4. Run quality checks:
    pnpm lint
    pnpm type-check
    pnpm test
  5. Commit your changes: git commit -m 'Add amazing feature'
  6. Push to your branch: git push origin feature/amazing-feature
  7. Open a Pull Request

Code Style Guidelines

  • Linting: Use Biome (configured in biome.json)
  • TypeScript: Follow strict mode, avoid any types
  • Naming: Use meaningful, descriptive names
  • Formatting: Run pnpm format before committing
  • Testing: Add tests for new features
  • Documentation: Update docs for significant changes

πŸ”§ Troubleshooting

Database Connection Issues

Problem: Cannot connect to PostgreSQL

Solutions:

  • Verify Docker containers are running: docker ps
  • Check DATABASE_URL in .env.local matches docker-compose.yml
  • Ensure database exists: docker exec -it postgres psql -U user -d dbname
  • Restart containers: docker-compose restart

Build Errors

Problem: Build fails with cryptic errors

Solutions:

  • Clear Next.js cache: rm -rf apps/web/.next
  • Clear Turbo cache: pnpm clean
  • Reinstall dependencies: rm -rf node_modules && pnpm install
  • Check Node.js version: node --version (should be 20+)

Type Errors

Problem: TypeScript errors in IDE or build

Solutions:

  • Run type check: pnpm type-check
  • Restart TypeScript server in your IDE
  • Ensure all dependencies are installed: pnpm install
  • Check tsconfig.json paths are correct

Port Already in Use

Problem: Port 3000 is already in use

Solutions:

  • Find process using port: lsof -i :3000 (macOS/Linux) or netstat -ano | findstr :3000 (Windows)
  • Kill the process or change port in package.json: next dev -p 3001

Environment Variables Not Loading

Problem: Environment variables are undefined

Solutions:

  • Ensure .env.local is in apps/web/ directory
  • Check variable names match env.ts schema
  • Restart dev server after changing .env.local
  • Verify no typos in variable names

Migration Issues

Problem: Database migrations fail

Solutions:

  • Check database connection: pnpm db:studio
  • Verify migration files in apps/web/drizzle/
  • Reset database (dev only): pnpm db:push (drops and recreates)
  • Check for conflicting migrations

Still Having Issues?

  • Check the project's GitHub Issues for similar problems
  • Review the Deployment Guide for production issues
  • Ensure all prerequisites are installed correctly

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments


Built with ❀️ using modern web technologies

About

A production-ready, full-stack TypeScript starter template with Next.js 16 frontend/backend, AWS infrastructure managed by Pulumi, PostgreSQL with Drizzle ORM, and complete SaaS features including authentication, payments, monitoring, and email.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages