A production-ready monorepo starter template with TanStack Start, Better Auth, Drizzle ORM, Supabase, and Railway deployment.
- TanStack Start - Full-stack React framework with file-based routing and server functions
- Better Auth - Type-safe authentication with Google OAuth
- Drizzle ORM - TypeScript ORM with PostgreSQL
- Supabase - PostgreSQL database with local development support
- Railway - One-click deployment configuration
- React 19 - Latest React with compiler optimization
- Tailwind CSS v4 - Utility-first CSS with shadcn/ui components
- Biome - Fast linter and formatter
apps/
web/ # TanStack Start frontend application
packages/
backend/ # Auth, database, and service operations
ui/ # Shared React components (shadcn/ui)
logger/ # Shared logging utilities
tsconfig/ # Shared TypeScript configurations
- Node.js 22+
- Bun 1.2+
- Docker (for local Supabase)
- Clone the repository:
git clone https://github.com/FilipLjubic/tanstack-start-monorepo.git
cd tanstack-start-monorepo- Install dependencies:
bun install- Copy environment file:
cp apps/web/env.example apps/web/.envNote:
packages/backend/.envis optional - only needed if you run drizzle commands directly from that directory. The drizzle config falls back toapps/web/.env.
- Start local Supabase:
bun --filter @starter/backend db:startNote: To run Supabase CLI directly from root, use
bun supabase <command>(e.g.,bun supabase status). This ensures Supabase files stay inpackages/backend/supabase.
- Run database migrations:
bun --filter @starter/backend db:push- Start the development server:
bun --filter @starter/web devVisit http://localhost:3000
- Go to Google Cloud Console
- Create a new project or select existing
- Configure the OAuth consent screen
- Create OAuth 2.0 credentials (Web application)
- Add authorized redirect URI:
http://localhost:3000/api/auth/callback/google - Copy Client ID and Client Secret to your
.envfiles
# Development
bun --filter @starter/web dev # Start web dev server
bun --filter @starter/backend db:start # Start local Supabase
# Database
bun --filter @starter/backend db:generate # Generate migrations
bun --filter @starter/backend db:push # Push schema changes
bun --filter @starter/backend db:studio # Open Drizzle Studio
bun --filter @starter/backend db:seed # Seed database with test data
bun --filter @starter/backend db:reset # Reset DB, run migrations, and seed
# Code Quality
bunx biome check --write . # Lint and format
bun --filter @starter/web typecheck # Type checkThe starter includes:
- user - User accounts (Better Auth managed)
- session - User sessions
- account - OAuth provider accounts
- verification - Email verification tokens
- note - Example table for CRUD operations (deletable)
The starter includes a Notes CRUD example to demonstrate the patterns. Search for DELETE in the project to find all example code that can be removed:
grep -r "DELETE" --include="*.ts" --include="*.tsx" apps packagesAfter deleting example code:
- Run
bun --filter @starter/backend db:pushto sync schema - Run
bunx biome check --write .to clean up unused imports - Run
bun --filter @starter/web typecheckto verify no broken references
- Click Deploy on Railway button (or use the Railway template)
- Wait for deployment to complete
- Generate a public domain: Service Settings > Networking > Generate Domain
- Add your
DATABASE_URLin Railway variables, then redeploy - Run migrations (see below)
Railway automatically configures BETTER_AUTH_SECRET, BASE_URL, BETTER_AUTH_URL, and TRUSTED_ORIGINS when you generate the public URL.
You'll need a PostgreSQL database:
- Supabase - Free tier available, includes auth/storage extras
- Neon - Serverless Postgres, generous free tier
- Railway Postgres - Add as separate service in your project
- Self-hosted - Any Postgres-compatible database
-
Run migrations against your production database:
cp packages/backend/.env packages/backend/.env.prod # Edit .env.prod with your production DATABASE_URL bun --filter @starter/backend db:migrate:prod -
Configure Google OAuth (optional):
- Go to Google Cloud Console
- Create a new project or select existing
- Configure the OAuth consent screen
- Create OAuth 2.0 credentials (Web application)
- Add authorized redirect URI:
https://your-app.railway.app/api/auth/callback/google - Add
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRETin Railway variables
| Variable | Auto-configured | Description |
|---|---|---|
DATABASE_URL |
No | PostgreSQL connection string (you provide this) |
BETTER_AUTH_SECRET |
Yes | Auto-generated on deploy |
BASE_URL |
Yes | Set when you generate public domain |
BETTER_AUTH_URL |
Yes | Set when you generate public domain |
TRUSTED_ORIGINS |
Yes | Set when you generate public domain |
GOOGLE_CLIENT_ID |
No | Google OAuth client ID (optional) |
GOOGLE_CLIENT_SECRET |
No | Google OAuth client secret (optional) |
| Category | Technology |
|---|---|
| Framework | TanStack Start |
| Auth | Better Auth |
| Database | PostgreSQL + Drizzle ORM |
| Styling | Tailwind CSS v4 + shadcn/ui |
| Build | Vite + Nitro |
| Package Manager | Bun |
| Linting | Biome |
MIT