A production-ready TypeScript monorepo built with Better-T-Stack. This project demonstrates modern full-stack development with shared code, type safety across all layers, and Docker support for easy deployment.
This monorepo architecture provides:
- End-to-end Type Safety - Share types between frontend, backend, and mobile with oRPC
- Code Reuse - Shared packages eliminate duplication across applications
- Fast Builds - Turborepo caches and parallelizes builds intelligently
- Developer Experience - Hot reload, TypeScript, and modern tooling throughout
- Production Ready - Includes Docker support, authentication, and database setup
- Next.js - Full-stack React framework with App Router
- React Native + Expo - Cross-platform mobile development
- TailwindCSS - Utility-first styling
- shadcn/ui - High-quality, accessible UI components
- Hono - Ultra-fast, lightweight web framework
- oRPC - Type-safe RPC with automatic OpenAPI generation
- Drizzle ORM - TypeScript-first database toolkit
- PostgreSQL - Robust relational database
- Better-Auth - Modern authentication solution
- Turborepo - High-performance monorepo build system
- pnpm - Fast, disk-efficient package manager
- Docker - Containerization for consistent deployments
First, install the dependencies:
pnpm installThis project uses PostgreSQL with Drizzle ORM.
-
Make sure you have a PostgreSQL database set up.
-
Update your
apps/server/.envfile with your PostgreSQL connection details. -
Apply the schema to your database:
pnpm db:pushThen, run the development server:
pnpm devOpen http://localhost:3001 in your browser to see the web application. Use the Expo Go app to run the mobile application. The API is running at http://localhost:3000.
app-mono-skaffold/
├── apps/
│ ├── web/ # Next.js web application
│ │ ├── app/ # App Router pages and layouts
│ │ ├── components/ # React components
│ │ └── Dockerfile # Production Docker image
│ ├── native/ # React Native mobile app (Expo)
│ │ ├── app/ # Expo Router screens
│ │ └── components/ # Mobile components
│ └── server/ # Hono backend API
│ ├── src/ # Server source code
│ ├── dist/ # Build output
│ └── Dockerfile # Production Docker image
├── packages/
│ └── shared/ # Shared code (types, utilities, etc.)
├── turbo.json # Turborepo configuration
├── pnpm-workspace.yaml # pnpm workspace configuration
└── package.json # Root package.json
pnpm dev- Start all applications in development modepnpm dev:web- Start only the Next.js web applicationpnpm dev:server- Start only the Hono backend serverpnpm dev:native- Start the React Native/Expo development server
pnpm build- Build all applications for productionpnpm check-types- Run TypeScript type checking across all apps
pnpm db:push- Push Drizzle schema changes to the databasepnpm db:studio- Open Drizzle Studio (database UI)
Both the web and server applications include production-ready Dockerfiles with multi-stage builds for optimized image sizes.
Build from the repository root:
# Web application
docker build -t your-registry/web:latest -f apps/web/Dockerfile .
# Server application
docker build -t your-registry/server:latest -f apps/server/Dockerfile .Web (Next.js):
- Multi-stage build for minimal image size
- Uses Next.js standalone output
- Runs as non-root user for security
- Includes health checks
- Exposes port 3000
Server (Hono):
- Builds shared package dependencies
- Production-only dependencies in final image
- Supports monorepo workspace structure
- Exposes port 3000
# Run web application
docker run -p 3000:3000 your-registry/web:latest
# Run server application with environment variables
docker run -p 3000:3000 \
-e DATABASE_URL="postgresql://..." \
-e AUTH_SECRET="your-secret" \
your-registry/server:latestCreate a docker-compose.yml for running multiple services:
version: '3.8'
services:
web:
build:
context: .
dockerfile: apps/web/Dockerfile
ports:
- "3001:3000"
environment:
- NEXT_PUBLIC_API_URL=http://server:3000
server:
build:
context: .
dockerfile: apps/server/Dockerfile
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
- AUTH_SECRET=your-secret-here
db:
image: postgres:16
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:This monorepo supports multiple deployment strategies:
- Docker: Use the provided Dockerfiles to deploy to any container platform (AWS ECS, Google Cloud Run, Azure Container Apps, etc.)
- Vercel: Deploy the Next.js app directly from the
apps/webdirectory - Traditional Hosting: Build and deploy individual apps to VPS or traditional hosting
- Kubernetes: Use the Docker images with Kubernetes/Skaffold for orchestration
NEXT_PUBLIC_API_URL=http://localhost:3000
DATABASE_URL=postgresql://user:password@localhost:5432/database
AUTH_SECRET=your-secret-key
PORT=3000