A production-ready full-stack TypeScript starter. Click "Use this template" on GitHub to create a new repo.
- API: NestJS 11, TypeORM, PostgreSQL, JWT auth (httponly cookie), S3 file uploads
- Web: React 19, Vite, TanStack Router, TanStack Query, Tailwind CSS v4, shadcn/Radix UI
- Infra: Docker (dev + prod), GitHub Actions (build → GHCR → SSH deploy)
- Node 22+
- Docker + Docker Compose
-
Copy the env file and fill in values:
cp docker/.env.example docker/.env
-
Start all services:
npm run dev:all
-
Initialize the database (first run):
docker exec -i starter-postgres psql -U $DB_USER -d $DB_NAME < apps/api/src/database/sql/schema.sql
Default seed user:
admin/password
| Variable | Description |
|---|---|
DB_USER |
PostgreSQL username |
DB_PWD |
PostgreSQL password |
DB_NAME |
PostgreSQL database name |
DB_HOST |
PostgreSQL host (use container name in Docker) |
PORT |
API port (default: 8010) |
JWT_SECRET |
Secret for signing JWT tokens |
S3_ENDPOINT |
S3-compatible endpoint URL |
S3_ACCESS_KEY_ID |
S3 access key |
S3_SECRET_ACCESS_KEY |
S3 secret key |
S3_BUCKET_NAME |
S3 bucket name |
VITE_API_URL |
API base URL used by the frontend |
Set the following GitHub Actions secrets:
| Secret | Description |
|---|---|
VM_HOST |
SSH host |
VM_USER |
SSH user |
VM_SSH_KEY |
SSH private key |
VM_APP_DIR |
Path to the app directory on the VM |
CR_PAT |
GitHub container registry PAT |
Push to main to trigger the build → push to GHCR → deploy pipeline.
apps/
api/ ← NestJS API (auth, S3 uploads, TypeORM)
web/ ← React/Vite SPA (TanStack Router + Query, Tailwind)
docker/ ← Compose files, nginx configs, env example