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:
soroush.asadi
2026-05-27 21:33:10 +03:30
commit 45cd028d1c
15 changed files with 1672 additions and 0 deletions
+154
View File
@@ -0,0 +1,154 @@
# Meezi — full stack (Postgres, Redis, API, Dashboard, Marketing Website)
#
# Setup:
# copy .env.example .env
# powershell -File scripts/docker-up-full.ps1
# — or — docker compose up -d --build
#
# If image pulls fail (Iran / MCR timeout): VPN on, or see docs/DOCKER.md
#
# URLs (defaults):
# Dashboard http://localhost:3101/fa/login
# Website http://localhost:3010/fa
# Finder http://localhost:3103/fa
# API http://localhost:5080/swagger
# Health http://localhost:5080/health
services:
postgres:
image: postgres:16-alpine
container_name: meezi-db
restart: unless-stopped
environment:
POSTGRES_DB: meezi
POSTGRES_USER: meezi
POSTGRES_PASSWORD: meezi_local_pass
ports:
- "${POSTGRES_PORT:-5434}:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U meezi -d meezi"]
interval: 5s
timeout: 5s
retries: 10
redis:
image: redis:7-alpine
container_name: meezi-redis
restart: unless-stopped
ports:
- "${REDIS_PORT:-6381}:6379"
command: redis-server --appendonly yes
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 10
api:
build:
context: .
dockerfile: docker/api/Dockerfile
args:
DOTNET_SDK_IMAGE: ${DOTNET_SDK_IMAGE:-mcr.microsoft.com/dotnet/sdk:10.0}
DOTNET_ASPNET_IMAGE: ${DOTNET_ASPNET_IMAGE:-mcr.microsoft.com/dotnet/aspnet:10.0}
container_name: meezi-api
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
ASPNETCORE_ENVIRONMENT: Development
ASPNETCORE_URLS: http://+:8080
RUN_MIGRATIONS: "true"
ConnectionStrings__DefaultConnection: Host=postgres;Port=5432;Database=meezi;Username=meezi;Password=meezi_local_pass
ConnectionStrings__Redis: redis:6379
App__PublicBaseUrl: ${NEXT_PUBLIC_API_URL:-http://localhost:5080}
App__QrPublicBaseUrl: http://localhost:${WEB_PORT:-3101}
Cors__Origins__0: http://localhost:${WEB_PORT:-3101}
Cors__Origins__1: http://localhost:${WEBSITE_PORT:-3010}
Cors__Origins__2: http://localhost:${FINDER_PORT:-3103}
Auth__MaxOtpAttemptsPerHour: "100"
Kavenegar__ApiKey: ""
Billing__DashboardBaseUrl: http://localhost:${WEB_PORT:-3101}
Snappfood__WebhookSecret: meezi-dev-snappfood-secret
ZarinPal__MerchantId: "${ZARINPAL_MERCHANT_ID:-}"
ZarinPal__Sandbox: "${ZARINPAL_SANDBOX:-true}"
ports:
- "${API_PORT:-5080}:8080"
volumes:
- api_uploads:/app/uploads
healthcheck:
# TCP probe only — no apt-get/curl in image (build works offline / without Ubuntu mirrors)
test: ["CMD-SHELL", "bash -c 'cat </dev/null >/dev/tcp/127.0.0.1/8080' || exit 1"]
interval: 10s
timeout: 5s
retries: 12
start_period: 40s
web:
build:
context: .
dockerfile: docker/web/Dockerfile
args:
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:5080}
container_name: meezi-web
restart: unless-stopped
depends_on:
api:
condition: service_healthy
environment:
PORT: "3000"
HOSTNAME: 0.0.0.0
ports:
- "${WEB_PORT:-3101}:3000"
website:
build:
context: .
dockerfile: docker/website/Dockerfile
args:
MEEZI_API_URL: http://api:8080
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-http://localhost:3010}
container_name: meezi-website
restart: unless-stopped
depends_on:
api:
condition: service_healthy
environment:
PORT: "3000"
HOSTNAME: 0.0.0.0
MEEZI_API_URL: http://api:8080
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-http://localhost:3010}
ports:
- "${WEBSITE_PORT:-3010}:3000"
finder:
build:
context: .
dockerfile: docker/finder/Dockerfile
args:
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:5080}
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_FINDER_URL:-http://localhost:3103}
container_name: meezi-finder
restart: unless-stopped
depends_on:
api:
condition: service_healthy
environment:
PORT: "3000"
HOSTNAME: 0.0.0.0
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:5080}
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_FINDER_URL:-http://localhost:3103}
ports:
- "${FINDER_PORT:-3103}:3000"
volumes:
postgres_data:
redis_data:
api_uploads: