chore: initial project structure and root configuration
Adds root-level config files: solution (.slnx), NuGet, global.json, Docker Compose files for all services (API, dashboard, website, finder, admin), environment example, and developer documentation. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# Meezi — Production deployment (Arvan Cloud)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Arvan Cloud account (Iran region)
|
||||
- Domain `meezi.ir` DNS pointed to Arvan load balancer
|
||||
- ZarinPal merchant ID (production, sandbox off)
|
||||
- Kavenegar API key
|
||||
- PostgreSQL 16 + Redis managed or VMs
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Suggested host |
|
||||
|---------|----------------|
|
||||
| API | `api.meezi.ir` → ASP.NET container port 8080 |
|
||||
| Dashboard | `app.meezi.ir` or `meezi.ir` → Next.js standalone |
|
||||
| QR landing | `meezi.ir/q/*` → same Next.js app (`/q/[code]` route) |
|
||||
| Postgres | Private network only |
|
||||
| Redis | Private network only |
|
||||
|
||||
## Environment variables (API)
|
||||
|
||||
```
|
||||
ConnectionStrings__DefaultConnection=Host=...;Database=meezi;...
|
||||
ConnectionStrings__Redis=...
|
||||
Jwt__Key=<32+ char secret>
|
||||
App__PublicBaseUrl=https://api.meezi.ir
|
||||
App__QrPublicBaseUrl=https://meezi.ir
|
||||
Billing__DashboardBaseUrl=https://app.meezi.ir
|
||||
ZarinPal__MerchantId=<merchant>
|
||||
ZarinPal__Sandbox=false
|
||||
Kavenegar__ApiKey=<key>
|
||||
Snappfood__WebhookSecret=<secret>
|
||||
Taraz__Username=<moadian-user>
|
||||
Taraz__Password=<moadian-pass>
|
||||
Taraz__CertificatePath=/secrets/taraz.pfx
|
||||
RUN_MIGRATIONS=true
|
||||
Cors__Origins__0=https://app.meezi.ir
|
||||
Cors__Origins__1=https://meezi.ir
|
||||
```
|
||||
|
||||
### ZarinPal / Taraz validation
|
||||
|
||||
1. **Sandbox first:** set `ZarinPal__Sandbox=true` and a sandbox merchant; complete subscribe flow; confirm redirect `?billing=success` and JWT refresh on settings.
|
||||
2. **Production:** set `ZarinPal__Sandbox=false` and production `ZarinPal__MerchantId`; verify callback URL is reachable from ZarinPal.
|
||||
3. **Taraz:** with real credentials, submit from Settings → تاراز; confirm tracking in API logs (stub logs until full SDK wired).
|
||||
|
||||
## Environment variables (Web)
|
||||
|
||||
```
|
||||
NEXT_PUBLIC_API_URL=https://api.meezi.ir
|
||||
```
|
||||
|
||||
## Routing
|
||||
|
||||
- Customer QR codes encode `https://meezi.ir/q/{qrCode}` (see `App:QrPublicBaseUrl`).
|
||||
- Next.js route [`web/dashboard/src/app/q/[code]/page.tsx`](web/dashboard/src/app/q/[code]/page.tsx) resolves via public `GET /api/q/{code}`.
|
||||
- Flutter app parses scanned URL and calls the same API.
|
||||
|
||||
## Arvan checklist
|
||||
|
||||
- [ ] Postgres + Redis on private network (no public ports)
|
||||
- [ ] `api_uploads` persistent volume mounted at `/app/uploads`
|
||||
- [ ] `RUN_MIGRATIONS=true` on API deploy only
|
||||
- [ ] Hangfire `/hangfire` behind VPN or basic auth
|
||||
- [ ] CORS origins: dashboard + marketing domain
|
||||
- [ ] `App__QrPublicBaseUrl=https://meezi.ir`
|
||||
- [ ] `Billing__DashboardBaseUrl=https://app.meezi.ir` (locale path added by API)
|
||||
- [ ] TLS on load balancer for `api.*` and `app.*`
|
||||
- [ ] Kavenegar + ZarinPal production keys in Arvan secrets (not in git)
|
||||
|
||||
## Deploy steps
|
||||
|
||||
1. Build and push Docker images (`docker compose` Dockerfiles in `docker/`).
|
||||
2. Run EF migrations on API startup (`RUN_MIGRATIONS=true`) once per release.
|
||||
3. Configure Hangfire dashboard behind auth in production.
|
||||
4. Smoke test: OTP login, POS terminal register, create order, menu images visible, ZarinPal subscribe (sandbox first).
|
||||
|
||||
## CI suggestion
|
||||
|
||||
- `dotnet build` + `dotnet test` on PR
|
||||
- `npm run build` in `web/dashboard`
|
||||
- Deploy on tag to Arvan registry
|
||||
Reference in New Issue
Block a user