9.3 KiB
Convex Turbo Monorepo
A production-ready Turborepo starter with Next.js, Expo, and self-hosted Convex backend. Built with TypeScript, Tailwind CSS, and modern tooling.
What's Inside?
Apps & Packages
apps/next- Next.js 16 web application with App Routerapps/expo- Expo 54 mobile application (in progress)@gib/backend- Self-hosted Convex backend with authentication@gib/ui- Shared shadcn/ui component library@gib/eslint-config- ESLint configuration@gib/prettier-config- Prettier configuration with import sorting@gib/tailwind-config- Tailwind CSS v4 configuration@gib/tsconfig- Shared TypeScript configurations
Tech Stack
- Framework: Next.js 16 (App Router) + Expo 54
- Backend: Convex (self-hosted)
- Auth: @convex-dev/auth with Authentik OAuth & Password providers
- Styling: Tailwind CSS v4 + shadcn/ui
- Language: TypeScript (strict mode)
- Package Manager: Bun
- Monorepo: Turborepo
- Deployment: Docker (standalone)
Getting Started
Prerequisites
- Bun (v1.2.19+)
- Docker & Docker Compose (for self-hosted Convex)
- Node.js 22.20.0+ (for compatibility)
Development Setup
1. Clone & Install
git clone <your-repo-url>
cd convex-monorepo
bun install
2. Configure Environment Variables
Create a .env file in the project root with the following variables:
# Convex Backend (Self-Hosted)
CONVEX_SELF_HOSTED_URL=https://api.convex.example.com
CONVEX_SELF_HOSTED_ADMIN_KEY=<generated>
CONVEX_SITE_URL=https://convex.example.com
# Next.js Public
NEXT_PUBLIC_CONVEX_URL=https://api.convex.example.com
NEXT_PUBLIC_SITE_URL=https://example.com
NEXT_PUBLIC_PLAUSIBLE_URL=https://plausible.example.com
NEXT_PUBLIC_SENTRY_DSN=
NEXT_PUBLIC_SENTRY_URL=
NEXT_PUBLIC_SENTRY_ORG=
NEXT_PUBLIC_SENTRY_PROJECT_NAME=
# Server-side
SENTRY_AUTH_TOKEN=
# Auth (will be synced to Convex)
AUTH_AUTHENTIK_ID=
AUTH_AUTHENTIK_SECRET=
AUTH_AUTHENTIK_ISSUER=
USESEND_API_KEY=
For local development: Use http://localhost:3210 for Convex URLs.
3. Configure Docker Environment
Check and update environment variables in docker/.env for your deployment:
cd docker/
cp .env.example .env
# Edit .env with your configuration
4. Start Self-Hosted Convex
Spin up the Convex backend and dashboard:
cd docker/
docker compose up -d convex-backend convex-dashboard
Services:
- Backend: http://localhost:3210
- Dashboard: http://localhost:6791
5. Generate Auth Keys & Sync Environment Variables
Generate JWT keys for Convex Auth:
cd packages/backend
bun run scripts/generateKeys.mjs
Sync environment variables to Convex deployment (via CLI or Dashboard):
cd packages/backend
bun with-env npx convex env set AUTH_AUTHENTIK_ID "your-value"
bun with-env npx convex env set AUTH_AUTHENTIK_SECRET "your-value"
bun with-env npx convex env set AUTH_AUTHENTIK_ISSUER "your-issuer-url"
bun with-env npx convex env set USESEND_API_KEY "your-api-key"
bun with-env npx convex env set CONVEX_SITE_URL "http://localhost:3000"
Important: For local development, set CONVEX_SITE_URL to http://localhost:3000.
6. Start Development Server
# From project root
bun dev:next # Next.js app + Convex backend
# or
bun dev # All apps (Next.js + Expo + Backend)
App URLs:
- Next.js: http://localhost:3000
- Convex Dashboard: http://localhost:6791
Development Commands
# Development
bun dev # Run all apps
bun dev:next # Next.js + Convex backend
bun dev:expo # Expo + Convex backend
bun dev:backend # Convex backend only
# Quality Checks
bun typecheck # Type checking (recommended for testing)
bun lint # Lint all packages
bun lint:fix # Lint and auto-fix
bun format # Check formatting
bun format:fix # Fix formatting
# Build
bun build # Build all packages (production)
# Utilities
bun ui-add # Add shadcn/ui components
bun clean # Clean node_modules
bun clean:ws # Clean workspace caches
Single Package Commands
Use Turborepo filters to target specific packages:
bun turbo run dev -F @gib/next # Run Next.js only
bun turbo run typecheck -F @gib/backend # Typecheck backend
bun turbo run lint -F @gib/ui # Lint UI package
Project Structure
convex-monorepo/
├── apps/
│ ├── next/ # Next.js web app
│ │ ├── src/
│ │ │ ├── app/ # App Router pages
│ │ │ ├── components/ # React components
│ │ │ └── lib/ # Utilities
│ │ └── package.json
│ └── expo/ # Expo mobile app (WIP)
│
├── packages/
│ ├── backend/ # Convex backend
│ │ ├── convex/ # Convex functions (synced to cloud)
│ │ ├── scripts/ # Utilities (generateKeys.mjs)
│ │ └── types/ # Shared types
│ └── ui/ # shadcn/ui components
│ └── src/ # Component source files
│
├── tools/ # Shared configurations
│ ├── eslint/
│ ├── prettier/
│ ├── tailwind/
│ └── typescript/
│
├── docker/ # Self-hosted deployment
│ ├── compose.yml
│ ├── Dockerfile
│ └── .env.example
│
├── turbo.json # Turborepo configuration
└── package.json # Root workspace & catalogs
Features
Authentication
- OAuth: Authentik SSO integration
- Password: Custom password auth with email verification
- OTP: Email verification via self-hosted UseSend
- Session Management: Secure cookie-based sessions
Next.js App
- App Router: Next.js 16 with React Server Components
- Data Preloading: Server-side data fetching with Convex
- Middleware: Route protection & authentication
- Styling: Tailwind CSS v4 with dark mode
- Analytics: Plausible (privacy-focused)
- Monitoring: Sentry error tracking
Backend
- Real-time: Convex reactive queries
- File Storage: Built-in file upload/storage
- Auth: Multi-provider authentication
- Type-safe: Full TypeScript with generated types
- Self-hosted: Complete control over your data
Developer Experience
- Monorepo: Turborepo for efficient builds
- Type Safety: Strict TypeScript throughout
- Code Quality: ESLint + Prettier with auto-fix
- Hot Reload: Fast refresh for all packages
- Catalog Deps: Centralized version management
Deployment
Docker (Recommended)
Build and deploy with Docker Compose:
cd docker/
# Start all services
docker compose up -d
# View logs
docker compose logs -f
# Stop services
docker compose down
Services:
next-app- Next.js standalone buildconvex-backend- Convex backend (port 3210)convex-dashboard- Admin dashboard (port 6791)
Network: Uses nginx-bridge network (configurable in compose.yml).
Production Checklist
- Update environment variables in
docker/.env - Generate
CONVEX_SELF_HOSTED_ADMIN_KEY - Configure reverse proxy (Nginx/Traefik)
- Set up SSL certificates
- Sync auth environment variables to Convex
- Configure backup strategy for
docker/data/ - Test authentication flow
- Enable Sentry error tracking
Documentation
- AGENTS.md - Comprehensive guide for AI agents & developers
- Convex Docs - Official Convex documentation
- Turborepo Docs - Turborepo documentation
- Next.js Docs - Next.js documentation
Troubleshooting
Backend typecheck shows help message
This is expected behavior. The backend package follows Convex's structure with only convex/tsconfig.json (no root tsconfig). See AGENTS.md for details.
Imports from Convex require .js extension
The project uses ESM ("type": "module"), requiring explicit file extensions:
// ✅ Correct
// ❌ Wrong
import { api } from '@gib/backend/convex/_generated/api';
import { api } from '@gib/backend/convex/_generated/api.js';
Docker containers won't start
- Check Docker logs:
docker compose logs - Verify environment variables in
docker/.env - Ensure ports 3210 and 6791 are available
- Check network configuration (
nginx-bridge)
Contributing
This is a personal monorepo template. Feel free to fork and adapt for your needs.
Code Style
- Single quotes, trailing commas
- 80 character line width
- ESLint + Prettier enforced
- Import order: Types → React → Next → Third-party → @gib → Local
Run bun lint:fix and bun format:fix before committing.
License
MIT
Acknowledgments
Built with inspiration from: