From c089f41b68fb3ce7528699a19ce9cef0c24de787 Mon Sep 17 00:00:00 2001 From: Replit Agent Date: Sat, 6 Jun 2026 12:56:09 +0000 Subject: [PATCH] Add project documentation file detailing technical specifications and development setup Create `hammam-dev.md` at the repository root, containing a comprehensive English-language project brief for the EHSAN "Closed Donation Loop" POC, including tech stack, repo structure, and development/production run instructions. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 1fa9329f-0cec-4a2f-80e8-e26dbae3142e Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 365a3c6c-f69d-49c2-b185-bef6f758fdf7 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/4d696b13-86f2-4c9d-be0d-95b293430047/1fa9329f-0cec-4a2f-80e8-e26dbae3142e/Q5tQff9 Replit-Helium-Checkpoint-Created: true --- hammam-dev.md | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 hammam-dev.md diff --git a/hammam-dev.md b/hammam-dev.md new file mode 100644 index 0000000..b25fafa --- /dev/null +++ b/hammam-dev.md @@ -0,0 +1,107 @@ +# Hammam Dev — EHSAN "Closed Donation Loop" (POC) + +> Onboarding brief for any developer or AI coding agent (e.g. OpenClaw) taking over +> this project. Read it fully before editing. The repo is hosted on a self-hosted +> **Gitea** server and runs on a **Mac Mini** via Docker. + +## 1. What this product is +A bilingual (Arabic / English, full RTL + LTR) **proof-of-concept charity donation web +app** inspired by the Saudi "EHSAN" (إحسان) platform. Its core idea is a **Closed +Donation Loop**: + +- Beneficiaries submit support requests (housing, food, electricity, water, health, + court-ordered debt, appliances like A/C & refrigerator, etc.). +- Each request/opportunity has a **funding target**. Donations from multiple donors + **accumulate and are clamped to the target** — a case can never be over-funded. +- A case only **enters the "closed loop" fulfillment pipeline once it is fully funded**. + This is the central business rule. Do not break it. +- After funding, the flow continues to confirmation / tracking, and a simulated + WhatsApp notification log records donor/beneficiary messaging. + +This is a POC/demo: data is **in-memory mock data** (no real database, no real payments). + +## 2. Tech stack +- Monorepo: **pnpm workspaces**, Node.js 24, TypeScript 5.9. +- Web app (`artifacts/ehsan-poc`): React + Vite + **wouter** (routing) + + **TanStack Query** (data) + **Tailwind CSS** + shadcn/ui components. +- API (`artifacts/api-server`): **Express 5**, all routes mounted under `/api`, + health at `/api/healthz`. Data lives in `src/lib/mockDb.ts` (in-memory; resets on restart). +- Shared libs under `lib/`: `api-spec` (OpenAPI source of truth), `api-client-react` + (generated React Query hooks), `api-zod` (Zod schemas), `db` (Drizzle schema, not + active at runtime since data is in-memory). +- All workspace libs export TypeScript source directly (`./src/index.ts`) — no lib + pre-build step; Vite/esbuild consume the source. + +## 3. Repo map +- `artifacts/ehsan-poc/src/pages/` — screens: home, about, waqf, baraem, request, + opportunities, donate/:id, cart, login, admin, track/:id, thank-you/:id, + whatsapp-log, not-found. +- `artifacts/ehsan-poc/src/contexts/` — `LanguageContext` (ar/en + RTL), `CartContext` + (multi-case donation cart), `AuthContext` (mock admin login). +- `artifacts/ehsan-poc/src/components/` — `Riyal.tsx` (renders the NEW Saudi Riyal + symbol via an image mask), `layout/` (Header, AppLayout), `ui/` (shadcn components). +- `artifacts/api-server/src/routes/` — `health`, `requests`, `donors`, `stats`, + `whatsappLog`. Mounted in `routes/index.ts`. +- Root deploy files: `Dockerfile.web`, `Dockerfile.api`, `docker/nginx.conf`, + `docker-compose.yml`, `deploy.sh`, `scripts/push-to-gitea.sh`, `DEPLOYMENT.md`. + +## 4. How to run locally (development) +```bash +pnpm install +pnpm --filter @workspace/api-server run dev # API +pnpm --filter @workspace/ehsan-poc run dev # Web (needs PORT and BASE_PATH env) +pnpm run typecheck # full typecheck +pnpm run build # typecheck + build everything +``` +Note: `vite.config.ts` REQUIRES `PORT` and `BASE_PATH` env vars even for `build` +(it throws otherwise), e.g. +`PORT=8080 BASE_PATH=/ pnpm --filter @workspace/ehsan-poc run build`. + +## 5. How it runs in production (Mac Mini, Docker) +Two services in `docker-compose.yml`: +- `api` — Express, internal only, listens on `PORT=8080`, healthcheck `/api/healthz`. +- `web` — nginx that serves the built Vite SPA **and reverse-proxies `/api/` to + `api:8080`**. The browser always calls **same-origin `/api/...`**, so there is NO + frontend API URL to configure. + +Deploy / redeploy on the Mac Mini: +```bash +./deploy.sh # git pull gitea main → docker compose down → build → up -d +``` +App is then served on the Mac Mini at `http://localhost:8080` (override with `WEB_PORT`). + +## 6. Deployment flow (how code travels) +``` +Edit code → commit → push to Gitea (remote name: gitea, branch: main) + → on Mac Mini run ./deploy.sh → Docker rebuilds & restarts +``` +- Central repo is **Gitea** (no GitHub). Remote name everywhere is `gitea`, branch `main`. +- `scripts/push-to-gitea.sh` pushes from a dev machine; `deploy.sh` redeploys on the Mac Mini. +- An AI agent working directly on the Mac Mini clone should use this loop: + edit → test → `git commit` → `git push gitea main` → `./deploy.sh`. + +## 7. Hard rules / gotchas — do NOT break these +- **amd64 / glibc ONLY.** The pnpm workspace strips every native binary that is not + `linux-x64-gnu`. Docker build stages MUST use `node:24-bookworm-slim` (glibc, not + alpine) and `platform: linux/amd64` (runs under Rosetta on Apple Silicon). Do not + switch the build base to alpine or arm64 — rollup / tailwind-oxide / lightningcss + will fail to find native binaries. +- **Funding rule.** Donations accumulate and clamp to the target; a case enters the + fulfillment pipeline only when fully funded. Preserve this. +- **Bilingual + RTL.** Every user-facing string must exist in both Arabic and English + via `LanguageContext`. Don't hardcode single-language text. Keep RTL layout working. +- **Currency.** Saudi Riyal uses the new official symbol rendered by the `` + component (image mask), not the old "ر.س"/"SAR" text. Reuse ``. +- **Routing base.** The app is mounted under a base path via `import.meta.env.BASE_URL`. + Use it for routes/links; never hardcode root-relative `/api` in a way that escapes + the base — call same-origin `/api/...` through the proxy. +- **Data is ephemeral.** mockDb is in-memory; restarting the `api` container resets it. + If you add persistence, add a database service to `docker-compose.yml` accordingly. +- **HMR quirk (dev):** if you see "useLanguage must be used within a LanguageProvider" + while the code is correct, it's stale Fast Refresh state — restart the web dev server. +- Always run `pnpm run build` (typecheck + build) before pushing to catch type errors. + +## 8. Suggested first task for a new agent +Read `DEPLOYMENT.md`, `artifacts/ehsan-poc/src/App.tsx`, and +`artifacts/api-server/src/routes/index.ts` to confirm the routes and data model, then +summarize your understanding of the funding / closed-loop flow before making any change.