# Meezi — Docker (full platform) Run all services with one command. ## Services | Service | Description | Default Port | |---------|-------------|-------------| | **postgres** | PostgreSQL 16 database | 5434 (host) | | **redis** | Redis 7 (session, rate-limit, refresh tokens) | 6381 (host) | | **api** | Main ASP.NET Core 10 API | 5080 | | **admin-api** | Admin ASP.NET Core 10 API | 5081 | | **web** | Customer-facing Next.js dashboard | 3101 | | **website** | Marketing / landing website | 3010 | | **admin-web** | Admin panel Next.js | 3102 | --- ## Quick start — full stack (all 7 services) ```powershell cd F:\Projects\Meezi copy .env.example .env docker compose -f docker-compose.full.yml up -d --build ``` ## Quick start — core stack only (dashboard + API) ```powershell docker compose up -d --build ``` ## Quick start — with admin panel ```powershell docker compose -f docker-compose.yml -f docker-compose.admin.yml up -d --build ``` --- ## Default URLs | Service | URL | |---------|-----| | Dashboard (customer) | http://localhost:**3101**/fa/login | | Marketing website | http://localhost:**3010**/fa | | Admin panel | http://localhost:**3102**/fa/admin/login | | Main API Swagger | http://localhost:**5080**/swagger | | Admin API Swagger | http://localhost:**5081**/swagger | | Health (main API) | http://localhost:**5080**/health | | Health (admin API) | http://localhost:**5081**/health | | Hangfire (main API) | http://localhost:**5080**/hangfire | Demo login: `09121234567` — OTP appears in API logs (`docker compose logs -f api`). --- ## Ports (change in `.env`) | Variable | Default | Purpose | |----------|---------|---------| | `WEB_PORT` | 3101 | Next.js dashboard | | `WEBSITE_PORT` | 3010 | Marketing website | | `ADMIN_WEB_PORT` | 3102 | Admin panel | | `API_PORT` | 5080 | Main ASP.NET API | | `ADMIN_API_PORT` | 5081 | Admin ASP.NET API | | `POSTGRES_PORT` | 5434 | Postgres on host | | `REDIS_PORT` | 6381 | Redis on host | If a port is taken, edit `.env`: ```powershell copy .env.example .env # Edit .env — change WEB_PORT, WEBSITE_PORT, etc. docker compose -f docker-compose.full.yml up -d --build ``` --- ## Build args and API URLs `NEXT_PUBLIC_API_URL` — what the **browser** uses to call the Main API. Must be a host URL (not `api:8080`). `MEEZI_API_URL` — what the **website server** uses for internal SSR calls. Uses the Docker service name `http://api:8080`. ```powershell # Rebuild only the website after changing NEXT_PUBLIC_SITE_URL: docker compose -f docker-compose.full.yml up -d --build website ``` --- ## Useful commands ```powershell # Status docker compose -f docker-compose.full.yml ps # Logs docker compose -f docker-compose.full.yml logs -f api docker compose -f docker-compose.full.yml logs -f website docker compose -f docker-compose.full.yml logs -f web # Stop everything docker compose -f docker-compose.full.yml down # Stop and remove volumes (wipes DB!) docker compose -f docker-compose.full.yml down -v # Rebuild a single service docker compose -f docker-compose.full.yml up -d --build website docker compose -f docker-compose.full.yml up -d --build api ``` --- ## Printer setup (inside Docker) The Meezi API sends print jobs directly from the **browser dashboard** — the API itself does not talk to printers. This means: - Your thermal printer only needs to be on the **same WiFi/LAN** as the browser running the dashboard - **No Docker-specific configuration needed** for printers - See the full guide at: http://localhost:3010/fa/printer-guide --- ## Dev without Docker Still works: ```powershell docker compose up -d postgres redis # then in separate terminals: dotnet run --project src/Meezi.API dotnet run --project src/Meezi.Admin.API cd web/website && npm run dev # port 3010 cd web/dashboard && npm run dev # port 3000 → maps to 3101 cd web/admin && npm run dev # port 3102 ``` --- ## Sprint 10 — billing & integrations (dev) **ZarinPal (mock):** leave `ZarinPal:MerchantId` empty. In dashboard **تنظیمات** → upgrade Pro/Business → redirected through mock pay URL back to `/fa/settings?billing=success`. **Snappfood webhook** (demo café vendor `demo_vendor`): ```powershell $body = '{"orderId":"sf-001","vendorId":"demo_vendor","customerName":"Test","customerPhone":"09121111111","total":150000,"items":[{"name":"لاته","quantity":1,"unitPrice":150000}]}' $hmac = [System.BitConverter]::ToString((New-Object System.Security.Cryptography.HMACSHA256([Text.Encoding]::UTF8.GetBytes("meezi-dev-snappfood-secret"))).ComputeHash([Text.Encoding]::UTF8.GetBytes($body))).Replace("-","").ToLower() Invoke-RestMethod -Method Post -Uri "http://localhost:5080/api/webhooks/snappfood" -Body $body -ContentType "application/json" -Headers @{ "X-Snappfood-Signature" = $hmac } ``` **Taraz:** Settings → «ارسال به تاراز» (logs only until `Taraz:Username` is set). **Hangfire:** renewal reminder job runs daily — dashboard at `http://localhost:5080/hangfire` (dev). --- ## Tables & QR - Dashboard: `/fa/tables` — floor plan, add table, print QR (PNG) - Dev QR URL in codes: `http://localhost:3101/q/{qrCode}` (see `App__QrPublicBaseUrl`) - Scan `demo_table_01` in Flutter or open manual entry on QR screen --- ## Production env (Arvan) See [DEPLOY.md](DEPLOY.md). Key additional website vars: ```env NEXT_PUBLIC_SITE_URL=https://meezi.ir MEEZI_API_URL=http://api:8080 ``` --- ## Menu images (Food-101) - Manifest: `data/menu-image-manifest.json` - API upserts images on dev seed via `EnsureMenuImagesAsync` - Optional import: `dotnet run --project tools/MenuImageImporter -- --food101 `