# Development Guide Personal cheat sheet for bootstrapping and deploying projects from this template. ## Local Development Setup ### 1. Clone & Install ```bash git clone my-project cd my-project pnpm install ``` ### 2. Environment Variables Copy `.env.example` to `.env.local` and fill in: ```bash CONVEX_SELF_HOSTED_URL='https://convex-backend.mentat.ovh' CONVEX_SELF_HOSTED_ADMIN_KEY='self-hosted-convex|...' NEXT_PUBLIC_SITE_URL=http://localhost:3000 NEXT_PUBLIC_CONVEX_URL=https://convex-backend.mentat.ovh NEXT_PUBLIC_CONVEX_SITE_URL=https://backend-site-xxx.mentat.ovh ``` > **Never commit `.env.local`** — it's in `.gitignore`. ### 3. Run Dev Server ```bash pnpm dev --webpack ``` > ⚠️ **Never use Turbopack** — Next.js 16.2.1 has a CPU spike bug. Always `--webpack`. ### 4. Convex Setup (Local) ```bash npx convex dev ``` This connects to your self-hosted Convex instance. Ensure CLI version matches your backend image version. ## Coolify Deployment (Convex Self-Hosted) ### 1. Deploy Convex Backend On Coolify, create a new service using this docker-compose: ```yaml services: backend: image: 'ghcr.io/get-convex/convex-backend:latest' stop_grace_period: 10s stop_signal: SIGINT ports: - '${PORT:-3210}:3210' - '${SITE_PROXY_PORT:-3211}:3211' volumes: - 'data:/convex/data' environment: INSTANCE_NAME: '${INSTANCE_NAME}' INSTANCE_SECRET: '${INSTANCE_SECRET}' CONVEX_CLOUD_ORIGIN: '${SERVICE_URL_BACKEND}' CONVEX_SITE_ORIGIN: '${SERVICE_URL_BACKEND_SITE}' DO_NOT_REQUIRE_SSL: '${DO_NOT_REQUIRE_SSL:-true}' DATABASE_URL: '${DATABASE_URL:-}' # ... (see README.md for full config) healthcheck: test: ['CMD-SHELL', 'curl -f http://localhost:3210/version'] interval: 5s start_period: 10s timeout: 5s retries: 10 dashboard: image: 'ghcr.io/get-convex/convex-dashboard:latest' stop_grace_period: 10s stop_signal: SIGINT ports: - '${DASHBOARD_PORT:-6791}:6791' environment: PORT: '6791' NEXT_PUBLIC_DEPLOYMENT_URL: '${SERVICE_URL_BACKEND}' depends_on: backend: condition: service_healthy volumes: data: null ``` > **Best practice**: Copy the [official self-hosted config](https://github.com/get-convex/convex-backend/blob/main/self-hosted/docker/docker-compose.yml) and adapt env vars for Coolify. ### 2. Generate Admin Key SSH into the server and run: ```bash docker exec -it ./generate_admin_key.sh ``` Save the key. You'll use it to log into the Convex dashboard. ### 3. Configure Domains Add **2 domains** in Coolify for the backend: 1. Backend API: `https://convex-backend.mentat.ovh:3210` 2. Actions proxy: `https://backend-site-xxx.mentat.ovh:3211` ### 4. Better Auth Env Vars Set these on your Convex backend via CLI: ```bash pnpm dlx convex env set BETTER_AUTH_SECRET=$(openssl rand -base64 32) pnpm dlx convex env set SITE_URL=http://localhost:3000 ``` For production, `SITE_URL` should be your deployed frontend URL. ### 5. Resend Email Setup Email is handled by Resend. The API key is **server-side only** and lives on Convex, not in `.env.local`. 1. Get your API key from [resend.com](https://resend.com) 2. Verify your domain in Resend and create a sender email (e.g. `noreply@yourdomain.com`) 3. Set Convex environment variables: ```bash pnpm dlx convex env set RESEND_API_KEY=re_xxxxxxxxxxxxx pnpm dlx convex env set RESEND_FROM_EMAIL=noreply@yourdomain.com ``` > These are read by `convex/lib/resend.ts` at runtime. Never commit them. ## Adding a New Project from Template ### Option A: Manual Clone (Private Forgejo) ```bash git clone /convex-next-saas.git new-project cd new-project # Remove .git and re-init git remote remove origin git init git remote add origin ``` ### Option B: Using the Init Script ```bash node bin/init-template.mjs new-project ``` This will: - Copy the template to `new-project/` - Replace placeholders (`{{project-name}}`, `{{site-url}}`) - Initialize a fresh git repo - Run `pnpm install` ## Common Issues ### `missing field functions` on `npx convex dev` Your CLI and backend image versions differ. Check: ```bash npx convex --version # Compare with backend image tag in Coolify ``` Upgrade whichever is lower. ### Auth redirect loop - Ensure `callbackURL` starts with `/` - Ensure `sign-in` and `sign-up` pages are **not** protected by `isAuthenticated()` - Check `NEXT_PUBLIC_SITE_URL` matches your actual URL ### Locale not switching - Check `src/proxy.ts` matcher includes the route - Check browser has `NEXT_LOCALE` cookie - Ensure both `messages/en.json` and `messages/pl.json` exist and are valid JSON ### Build fails with Turbopack You forgot `--webpack`: ```bash # Wrong pnpm build # Right # build script in package.json already does next build # dev only: pnpm dev --webpack ``` ## Project Checklist When starting a new project: - [ ] Clone template / run init script - [ ] Update `package.json` name - [ ] Update `README.md` title and description - [ ] Fill `.env.local` - [ ] Deploy Convex backend on Coolify - [ ] Set `BETTER_AUTH_SECRET` and `SITE_URL` on Convex - [ ] Set `RESEND_API_KEY` and `RESEND_FROM_EMAIL` on Convex - [ ] Update `src/app/layout.tsx` metadata - [ ] Remove/replace placeholder content in `src/app/[locale]/page.tsx` - [ ] Add project-specific routes to `src/lib/routes.ts` - [ ] Run `pnpm lint` and `pnpm build` to verify