# Deploy guide (Novya PWA) Stack: **Vite React PWA** (static) + **Node/Hono API** (`backend/`) + **MySQL 8**. ## 1. Requirements - Node.js 20+ - MySQL 8 (or Docker Compose in `backend/docker-compose.dev.yml`) - Domain + reverse proxy (Nginx/Caddy) with HTTPS ## 2. Environment ### Backend — `backend/.env` Copy from `backend/.env.example`: | Variable | Notes | |----------|--------| | `DATABASE_URL` | MySQL connection string | | `CORS_ORIGIN` | Production frontend origin(s), comma-separated (e.g. `https://your.domain`) | | `TRUST_PROXY` | `true` behind Nginx/Caddy | | `NODE_ENV` | `production` | | `OPENAI_API_KEY` | GapGPT / OpenAI-compatible key (required for AI coach) | | `OPENAI_BASE_URL` | Default `https://api.gapgpt.app/v1` | | `OPENAI_MODEL` | e.g. `gpt-4o-mini` | ### Frontend — root `.env` (build-time) Copy from `.env.example`: | Variable | Notes | |----------|--------| | `VITE_BACKEND_URL` | Public API URL, e.g. `https://api.your.domain` (no trailing slash) | | `VITE_SUPABASE_URL` / `VITE_SUPABASE_ANON_KEY` | Optional legacy; auth/progress use the backend | | `VITE_OPENAI_*` | Prefer backend AI; only needed if client-side AI is still used | **Never commit `.env` files.** ## 3. Database ```bash cd backend npm install # start MySQL if needed: # docker compose -f docker-compose.dev.yml up -d npm run prisma:migrate:deploy npm run prisma:seed ``` ## 4. Build & run API ```bash cd backend npm run build NODE_ENV=production npm start # listens on PORT (default 3001) ``` Health check: `GET /health` ## 5. Build & serve PWA ```bash # from repo root npm install npm run build # serve `dist/` with Nginx/Caddy (SPA fallback → index.html) ``` Suggested proxy layout: - `https://your.domain/` → static `dist/` - `https://your.domain/api/` or `https://api.your.domain/` → backend `:3001` Set `VITE_BACKEND_URL` to the public API base URL **before** `npm run build`. ## 6. Checklist for the other deployer - [ ] MySQL migrated + seeded (11 course sessions) - [ ] Backend `CORS_ORIGIN` matches the real frontend origin - [ ] `OPENAI_API_KEY` set on backend - [ ] Frontend built with correct `VITE_BACKEND_URL` - [ ] HTTPS + SPA fallback configured - [ ] PWA icons/manifest reachable over HTTPS