diff --git a/README.md b/README.md index be9fcf8..1ed51b2 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,217 @@ # ZarinPal Merchant Analytics — Frontend -Persian RTL merchant analytics panel built with SvelteKit 2, Svelte 5, strict TypeScript, and Tailwind CSS v4. +Persian-first, RTL merchant analytics dashboard built with SvelteKit 2, Svelte 5, strict TypeScript, Tailwind CSS v4, and a generated OpenAPI client contract. -Current state: design, specifications, implementation plan, and task list are approved. Phase 4 frontend implementation is authorized. +The application is a client-rendered static SPA. In development, Vite serves it and proxies same-origin `/api` requests to the Go backend. In production, it is built into static files and served by the deployment repository's unprivileged Nginx container. Authentication remains backend-owned through an HttpOnly cookie; credentials and tokens are never stored in browser storage. -## Local development +## Local setup -The dashboard is a client-rendered static SvelteKit application. During development, Vite serves it at `http://127.0.0.1:5173` and proxies same-origin `/api` requests to the Go backend at `http://127.0.0.1:8080`. This preserves the backend-owned secure session model without storing credentials in browser storage. +### Prerequisites + +- Node.js 20.19+ or 22.12+ +- npm +- The backend API running at `http://127.0.0.1:8080` +- PostgreSQL and Redis running for the backend + +The frontend does not connect directly to PostgreSQL or Redis. Those external services are required by the backend: PostgreSQL stores application/analytics data, while Redis coordinates and caches background work. Follow the backend README to start them, apply migrations, import the dataset, create the demo account, and run both `cmd/api` and `cmd/worker`. + +### 1. Configure and install + +From the frontend repository root: + +```bash +cp .env.example .env +npm ci +``` + +PowerShell equivalent: ```powershell Copy-Item .env.example .env npm ci -npm run dev -- --host 127.0.0.1 ``` -Open `http://127.0.0.1:5173`. The demo merchant credentials are created by the backend importer/bootstrap process; they are intentionally not stored in this repository. +The normal local configuration is: -Quality commands: +```dotenv +PUBLIC_API_BASE_URL=/api/v1 +PUBLIC_AI_GROWTH_ENABLED=false +PUBLIC_AI_COACH_ENABLED=false +``` -```powershell +`PUBLIC_API_BASE_URL` is browser-visible routing configuration, not a secret. Keep `/api/v1` for the same-origin Vite proxy. To use a backend at another local address, add `LOCAL_API_ORIGIN=http://127.0.0.1:8080`; this variable configures Vite only. + +Do not put database URLs, Redis passwords, session secrets, AI provider keys, or any other credential in a frontend environment variable. Every `PUBLIC_*` value is included in the browser build. + +### 2. Start the application + +```bash +npm run dev +``` + +Open `http://127.0.0.1:5173`. The Vite server proxies `/api/*` to `http://127.0.0.1:8080` by default. + +### 3. Sign in with the local demo user + +The backend creates/resets this account when its `go run ./cmd/admin` command runs with the documented values: + +```text +Username: merchant-0001 +Password: merchant-demo-2026 +``` + +If login fails, confirm the backend `.env` contains those exact `DEMO_USERNAME` and `DEMO_PASSWORD` values and rerun `go run ./cmd/admin` from the backend repository. These are public development credentials; use a different password on every internet-accessible deployment. + +## Commands + +| Command | Purpose | +| ---------------------- | --------------------------------------------------------------------- | +| `npm run dev` | Start the Vite development server on `127.0.0.1:5173` | +| `npm run generate:api` | Regenerate TypeScript API types from the sibling backend OpenAPI file | +| `npm run check` | Run Svelte and TypeScript checks | +| `npm test` | Run the Vitest suite once | +| `npm run test:watch` | Run Vitest in watch mode | +| `npm run format:check` | Check formatting without changing files | +| `npm run format` | Format the repository | +| `npm run build` | Create the production static build in `build/` | +| `npm run preview` | Preview the production build locally | + +`npm run generate:api` expects the backend repository at `../zarinpal-analytics-backend`. If your checkout uses another layout, update the input path in `package.json` or copy the OpenAPI contract into the expected sibling location before running it. + +Before submitting a change, run: + +```bash npm run generate:api +npm run format:check npm run check npm test npm run build ``` -`PUBLIC_API_BASE_URL` is public routing configuration, not a secret. Keep its default `/api/v1` for the local Vite proxy and the production same-origin Nginx proxy. +## Production deployment on a remote server -- [`DESIGN.md`](DESIGN.md): visual language, interaction rules, responsive behavior, and current design-system state. -- [`docs/DASHBOARD-SPEC.md`](docs/DASHBOARD-SPEC.md): approved product requirements and acceptance criteria for implementation planning. -- [`docs/DASHBOARD-UX-SPEC.md`](docs/DASHBOARD-UX-SPEC.md): detailed screen map, RTL layouts, async states, data presentation, accessibility, and authorized export workflows. -- [`tasks/plan.md`](tasks/plan.md): approved SDD Phase 2 dependency order, risk spikes, vertical slices, and approval gates. -- [`tasks/todo.md`](tasks/todo.md): approved SDD Phase 3 task list and dependency order for authorized Phase 4 implementation. -- [`AGENTS.md`](AGENTS.md): durable rules for future coding agents and contributors. +Deploy the frontend and backend together through the `zarinpal-analytics-deployment` repository. Its Compose stack builds this static SPA, serves it through Nginx, runs the Go API and worker, and keeps PostgreSQL/Redis private. A separate shared Caddy deployment owns the public domain and HTTPS. + +The examples use `analytics.example.com`; replace it with your own domain and replace repository URL placeholders with your template/fork URLs. + +### 1. Prepare the server + +1. Provision an Ubuntu server with a public IP. +2. Install Git, Docker Engine, and the Docker Compose plugin. +3. Permit inbound TCP 80/443 and restrict SSH to trusted addresses. +4. Never expose PostgreSQL 5432 or Redis 6379 publicly. + +### 2. Install the main Caddy router + +Clone and follow the [Caddy deployment repository](https://git.amiirkhl.ir/Interanet/caddy-deployment.git): + +```bash +git clone https://git.amiirkhl.ir/Interanet/caddy-deployment.git ~/caddy-deployment +cd ~/caddy-deployment +``` + +Start Caddy according to that repository's README. Its container must join an external Docker network named `caddy_proxy`. If the repository does not create it, run `docker network create caddy_proxy` once before starting Caddy. + +### 3. Clone the application repositories + +```bash +git clone ~/zarinpal-analytics-deployment +cd ~/zarinpal-analytics-deployment +git clone backend +git clone frontend +``` + +Keep all three repositories on clean `main` branches matching `origin/main`; the guarded deployment script checks this layout. + +### 4. Configure production + +```bash +cp .env.example .env +cp backend/.env.production.example backend/.env +cp frontend/.env.production.example frontend/.env +chmod 600 .env backend/.env frontend/.env +``` + +Replace every placeholder. In particular: + +- Set `FRONTEND_ORIGIN=https://analytics.example.com` and `COOKIE_SECURE=true` in `backend/.env`. +- Generate distinct PostgreSQL, Redis, session, and cursor secrets with `openssl rand -hex 32`. +- Replace the public local demo password before exposing the site. +- Keep `PUBLIC_API_BASE_URL=/api/v1` in `frontend/.env` for same-origin routing. +- Enable frontend AI switches only when the matching backend capability, provider key, and budgets are configured. +- Never place a private value in `frontend/.env`. + +Place the dataset at the private absolute path configured by `IMPORT_FILE`, for example `/srv/zarinpal-data/challenge_data.csv.gz`. + +### 5. Run the first deployment + +From `~/zarinpal-analytics-deployment`, run in order: + +```bash +docker compose config --quiet +docker compose build backend frontend +docker compose up -d postgres redis +docker compose --profile tools run --rm migrate +docker compose --profile import run --rm importer +docker compose --profile tools run --rm admin +docker compose up -d backend worker frontend +docker compose ps +``` + +The migration, importer, and admin containers are intentional one-off tools. The API, worker, and frontend are long-running. Wait for every service to become healthy and inspect problems with: + +```bash +docker compose logs --tail=200 postgres redis backend worker frontend +``` + +### 6. Point the domain to the application + +Create an `A` record for `analytics.example.com` pointing to the server's public IPv4 address. Add `AAAA` only when IPv6 is actually configured. + +In the Caddy deployment, add this site to the `Caddyfile` or equivalent template: + +```caddyfile +analytics.example.com { + @backend path /api/* /healthz + + handle @backend { + reverse_proxy zarinpal-backend:8080 { + flush_interval -1 + } + } + + handle { + reverse_proxy zarinpal-frontend:8080 + } +} +``` + +Validate and reload Caddy with the commands documented in its repository. Once DNS resolves and ports 80/443 reach the server, Caddy obtains and renews the HTTPS certificate automatically. + +Verify the public site and API routing: + +```bash +curl -I https://analytics.example.com/ +curl https://analytics.example.com/healthz +``` + +Open the site, sign in with the production demo credentials configured in `backend/.env`, and confirm that dashboard data loads without browser console errors. + +### 7. Deploy later updates + +```bash +cd ~/zarinpal-analytics-deployment +git pull --ff-only origin main +git -C backend pull --ff-only origin main +git -C frontend pull --ff-only origin main +bash scripts/deploy.sh +``` + +Later deployments rebuild both images and apply migrations. They do not rerun the one-time importer or reset the demo account. Never run `docker compose down -v` in production because it deletes persistent volumes. + +## Project documentation + +- [`DESIGN.md`](DESIGN.md) defines the visual language, accessibility, RTL, responsive, and interaction rules. +- [`docs/DASHBOARD-SPEC.md`](docs/DASHBOARD-SPEC.md) defines dashboard product behavior. +- [`docs/DASHBOARD-UX-SPEC.md`](docs/DASHBOARD-UX-SPEC.md) defines screen flows and async/data states. +- [`AGENTS.md`](AGENTS.md) defines durable contributor and automation rules.