A modern full-stack application built with TypeScript, featuring independent deployment architecture where the React SPA and Nitro API server are deployed separately.
Independent Deployments: Frontend and API are deployed separately to different services, with CORS configuration enabling cross-origin communication.
- Backend: Nitro server with tRPC for type-safe APIs
- Frontend: React SPA with TanStack Router
- Database: PostgreSQL with Prisma ORM
- Authentication: Better Auth with session-based security
- Styling: TailwindCSS with Radix UI components
- Code Quality: Biome for linting and formatting
# Install dependencies
pnpm install
# Set up environment
cp .env.example .env.local
# Generate database client
pnpm db:generate
# Setup database
pnpm db:push
# Start development
pnpm devapps/
├── api/ # Nitro API server
└── web/ # React frontend application
packages/
├── auth/ # Better Auth configuration
├── database/ # Prisma schema and client
├── logger/ # Structured logging utilities
├── trpc/ # tRPC router and type definitions
└── ui/ # Shared UI components (Shadcn/UI)
tooling/
├── biome/ # Code formatting and linting config
├── generator/ # Package scaffolding tool
└── tsconfig/ # Shared TypeScript configurations
pnpm dev # Start all apps in development
pnpm dev:api # API server only (port 3001)
pnpm dev:web # Frontend only (port 5173)
pnpm build # Build all apps for production
# Build individual apps
pnpm --filter @repo/api build # Build API server only
pnpm --filter @repo/web build # Build frontend only
# Start production servers
pnpm --filter @repo/api start # Start API server
pnpm --filter @repo/web preview # Preview built frontendpnpm db:generate # Generate Prisma client
pnpm db:push # Push schema to database (dev)
pnpm db:migrate # Create migration (prod)
pnpm db:studio # Open Prisma Studio GUI
pnpm db:reset # Reset databasepnpm lint # Lint all packages
pnpm type-check # TypeScript type checking
# pnpm test # Run tests (not yet implemented)
pnpm biome:check # Check formatting/linting
pnpm biome:fix # Fix formatting/linting issues# Database
DATABASE_URL="postgresql://user:pass@localhost:5432/dbname"
# Authentication
BETTER_AUTH_SECRET="your-32-char-secret-key-here"
# API URL for frontend (both dev and production)
VITE_API_URL=http://localhost:3001
# Server Configuration
PORT=3001
NODE_ENV=developmentDevelopment: Frontend (port 5173) proxies API calls to backend (port 3001) Production: Frontend and API deployed independently with CORS configuration
- End-to-end type safety with tRPC
- Shared types between frontend and backend
- Runtime validation with ArkType schemas
- Session-based authentication with Better Auth
- HTTP-only secure cookies
- Role-based access control
- Automatic session renewal
- PostgreSQL with Prisma ORM
- Type-safe database operations
- Automatic migration system
- Better Auth compatible schema
- Shadcn/UI component library
- Radix UI primitives for accessibility
- TailwindCSS for styling
- Dark mode ready
| Package | Description | Port |
|---|---|---|
@repo/api |
Nitro API server | |
@repo/web |
React SPA with TanStack Router | 5173 |
| Package | Description |
|---|---|
@repo/auth |
Better Auth configuration and React hooks |
@repo/database |
Prisma schema, client, and database utilities |
@repo/logger |
Structured logging with environment detection |
@repo/trpc |
tRPC router, procedures, and client setup |
@repo/ui |
Shared UI components with Shadcn/UI |
| Package | Description |
|---|---|
@repo/biome-config |
Code formatting and linting configuration |
@repo/generator |
Interactive package scaffolding tool |
@repo/tsconfig |
Shared TypeScript configurations |
This project supports two deployment strategies:
Single Nitro server serves both frontend and API on the same domain:
# Build for unified deployment
pnpm --filter @repo/web build
pnpm --filter @repo/api build
# Deploy to Railway, Render, or any Node.js hosting
# No CORS configuration needed (same-origin)Environment variables:
BETTER_AUTH_URL=https://your-app.railway.app
BETTER_AUTH_SECRET=<your-secret>
DATABASE_URL=<auto-injected-by-railway>
# Do NOT set: VITE_API_URL, CORS_ORIGINS, BETTER_AUTH_TRUSTED_ORIGINSBenefits:
- No CORS complexity
- Single service to manage
- Lower hosting costs
- Simplified cookie handling
Frontend and API on separate domains (requires CORS):
API:
pnpm --filter @repo/api build
# Deploy to Railway, Render, etc.Frontend:
pnpm --filter @repo/web build
# Deploy to Vercel, Netlify, Cloudflare PagesEnvironment variables:
# API
BETTER_AUTH_URL=https://api.example.com
BETTER_AUTH_TRUSTED_ORIGINS=https://app.example.com
CORS_ORIGINS=https://app.example.com
# Frontend
VITE_API_URL=https://api.example.comDocker Development: See DOCKER-QUICKSTART.md for local HTTPS development setup.
Detailed Architecture: See ARCH.md for Railway deployment architecture details
- Runtime: Node.js 18+
- Package Manager: pnpm 10.15.0 (required)
- Framework: Nitro (universal server)
- Frontend: React 18 + TypeScript
- Routing: TanStack Router (frontend), file-based (API)
- Database: PostgreSQL + Prisma ORM
- Authentication: Better Auth
- API: tRPC with ArkType validation
- Styling: TailwindCSS + Shadcn/UI
- Code Quality: Biome
- Build System: Turbo (monorepo orchestration)
pnpm --filter @repo/api <command> # Target specific app
pnpm --filter @repo/web <command> # Target frontend
pnpm generate # Scaffold new packagespnpm db:studio # Visual database editor
pnpm db:seed # Populate with sample data
pnpm db:deploy # Deploy migrations to production