# Balinyaar — Repository Guide (root)

The **shared, repo-wide** guide for AI coding agents. It is intentionally short. Everything specific to one
side of the stack lives in that project's own `CLAUDE.md`.

> **Read the guide for the side you are editing — and only that one.**
> Working in `client/`? Read [client/CLAUDE.md](client/CLAUDE.md).
> Working in `server/`? Read [server/CLAUDE.md](server/CLAUDE.md).
> You almost never need both. A frontend change does not touch server files, and vice-versa.

> Last verified: 2026-08-02 against commit `51e86a1`.

---

## What Balinyaar is

Balinyaar is a **trust-first home-nursing marketplace in Iran**. Independent nurses (and nursing-company
employees) list configurable services; families search, book, pay, and review. The platform holds funds in an
escrow-style ledger and pays nurses out weekly after a confirmed check-out.

**Start at [`mvp/README.md`](mvp/README.md) for the current state of the product**, in three short,
non-technical files: how to manually test any user journey, what's broken and blocking a real launch, and
what's missing that isn't clearly scheduled. That folder is the live, load-bearing answer to "what's next."

Deeper product/business knowledge — the full business-requirement write-ups, the ~54-table database model,
payments/BNPL research, market/legal research — was consolidated into [`archive/product/`](archive/product/index.md)
during the 2026-08-02 documentation cleanup. It is **reference material, not required reading**: correct as
of that date, but not actively maintained going forward. Read it when `mvp/` doesn't answer your question in
enough depth — e.g. designing a new table, or needing the full reasoning behind a business rule.

**Never infer business rules from code alone** — the code is young. If `mvp/` and `archive/product/` both go
silent on a money, auth, tenancy, or clinical-data rule, say so rather than guessing.

---

## Repository layout

This is **two independent projects in one repo**, plus their documentation. There is no root-level build,
package, or solution — each project is built, linted, and run on its own.

| Path | What it is | Stack | Guide |
| --- | --- | --- | --- |
| [`client/`](client/) | Web frontend | Next.js 16 (App Router) · React 19 · TypeScript · MUI v9 · next-intl | [client/CLAUDE.md](client/CLAUDE.md) |
| [`server/`](server/) | Backend API | ASP.NET Core (.NET 10) · Clean Architecture · CQRS · EF Core | [server/CLAUDE.md](server/CLAUDE.md) |
| [`mvp/`](mvp/README.md) | **Current truth** — plain-language test flows, launch blockers, missing MVP features | Markdown | [mvp/README.md](mvp/README.md) |
| [`archive/`](archive/README.md) | Everything else: business docs, engineering rules/contracts/flow-atlas, and the executed build history. **Reference/history, not instruction** — nothing to build from it, and nothing here is kept current | Markdown | [archive/README.md](archive/README.md) |
| [`telegram-otp-bot/`](telegram-otp-bot/) | OTP relay (standalone, the pre-launch demo rail) | Node 18+, zero deps | [telegram-otp-bot/README.md](telegram-otp-bot/README.md) |
| [`deploy/`](deploy/) | Reverse-proxy config | Caddyfile | [DEPLOY.md](DEPLOY.md) |

`AGENTS.md` files in this repo are thin pointers to the `CLAUDE.md` in the same folder. **`CLAUDE.md` is the
single source of truth at every level.**

The two projects communicate over **HTTP/JSON** (optionally gRPC). The client reads the API base URL from
`NEXT_PUBLIC_API_URL`; the server listens on `http://localhost:5002` by default.

**Deployment** is three Docker containers — one `Dockerfile` per project directory, orchestrated by the root
[`docker-compose.yml`](docker-compose.yml) — behind an existing Caddy reverse proxy on the external `caddy_net`
network, serving `balinyaar.ir` (client) and `api.balinyaar.ir` (server). The database is **not**
containerised; it is a remote SQL Server. Full runbook: [DEPLOY.md](DEPLOY.md).

`archive/` holds the executed build history, the former `docs/` (engineering rules, API contracts, the
per-flow test atlas, status/backlog) and the former `product/` (business requirements, data model, research)
— consolidated there on 2026-08-02 so the live tree stays focused on MVP work. **Anything in it is a record,
not an instruction.**

---

## Where the rules live

Three tiers. Open the `CLAUDE.md` for the side you are editing, then **one** reference file for the area you
are touching.

| Tier | Where | What |
| --- | --- | --- |
| **Hard rules** | this file · [client/CLAUDE.md](client/CLAUDE.md) · [server/CLAUDE.md](server/CLAUDE.md) | Constraints whose violation breaks the build, the gate, or a business invariant |
| **Reference** (archived) | [`archive/docs/rules/`](archive/docs/rules/index.md) | The *how* and the *why*, as of 2026-08-02 — 3 shared files, 8 client, 6 server, plus the documentation convention. Not actively maintained; read it on demand, don't expect it to track later changes |
| **Procedure** | `.claude/skills/` | Playbooks: **frontend-designer** (the design contract for `client/` UI), **backend-feature** (adding a server feature), **flow-testing** (walking a flow end to end) |

Start at [archive/docs/rules/index.md](archive/docs/rules/index.md) — it maps "working on X" to the one file
to open.

**Precedence when two sources disagree:** `archive/product/` (business truth) → the relevant `CLAUDE.md`
(engineering truth) → `archive/docs/rules/` (the reasoning behind it) → the task in front of you. **Never
silently guess on money, auth, tenancy, or clinical-data rules** — do the safe thing, and say so.

---

## Working agreements (apply to both projects)

1. **Stay within one project per change** unless the task explicitly spans both.
2. **Match the surrounding style.** Mirror existing patterns; don't introduce new ones. Each project documents
   its conventions in its own `CLAUDE.md`.
3. **Run that project's own checks before declaring work done:**
   - client: `cd client && npm run check` (type + lint + copy), plus `npm run test:ci` if you touched a tested
     component.
   - server: `cd server && dotnet build Baya.sln` (**zero new warnings**) and `dotnet test Baya.sln`.
   - What "done" means in full: [archive/docs/rules/shared/git-and-gates.md](archive/docs/rules/shared/git-and-gates.md).
4. **Read [`mvp/`](mvp/README.md) (and `archive/product/` for depth) before changing behavior.** Business rules are decisions, not guesses.
5. **Don't reintroduce template/starter scaffolding.** Both projects were derived from open-source starters;
   their branding, demo/showcase pages, and `_TITLE_`/`_DESCRIPTION_` placeholders were intentionally removed.
   Don't add them back.
6. **Configuration lives in files, not a secret store.** `dotnet user-secrets` is **not used** — the
   `<UserSecretsId>` was removed from `Baya.Web.Api.csproj`, so that store **is not even read**. Any
   instruction anywhere to set a value with it is stale. Server config (including keys) lives in
   `appsettings.*.json`; client config in `.env.development` / `.env.production`; the deployment's
   container-specific overrides in `docker-compose.yml`.
   This is a deliberate pre-launch trade for a demo deployment — **the repo therefore contains live
   credentials.** Before onboarding real users, rotate them and move the secret half out of git (see
   [DEPLOY.md](DEPLOY.md) "Going to Production"). **One value is load-bearing and must never change:**
   `Seams:FieldEncryption:Key` / `:HashKey` decrypt all existing PII and derive the phone-lookup hash.
7. **Keep docs honest, and keep the architecture map current.** If you change how something works, update the
   doc that describes it in the **same** change. Each level documents its architecture in one canonical place —
   **this file's "Repository layout"** (repo), **client/CLAUDE.md "Project structure"** (frontend),
   **server/CLAUDE.md "Project map"** (backend). When a change alters that structure — adds, removes, or
   renames a project, layer, route group, provider, or major folder, or changes a cross-project / cross-layer
   boundary — update the matching section in the same change. The full anti-drift convention (what to update
   when X changes, the `> Last verified:` stamp, length budgets) is
   [archive/docs/rules/documentation.md](archive/docs/rules/documentation.md). **Stale instructions are worse than none.**
8. **Write clean, self-documenting code.**
   - **No dead code.** Remove unused variables, imports/usings, parameters, and private members — don't leave
     them behind and don't suppress the warning. The client enforces this with ESLint
     (`@typescript-eslint/no-unused-vars` as an *error*); on the server they are build warnings and the gate is
     zero new warnings.
   - **Comment the *why*, not the *what*.** Don't write verbose comments that restate what the code already
     says. Add a comment only where a non-obvious decision, constraint, business rule, or trade-off isn't
     evident from the code itself. Prefer a clearer name over a comment.
   - Details and worked examples: [archive/docs/rules/shared/code-quality.md](archive/docs/rules/shared/code-quality.md).
9. **A mock is only sanctioned behind a DI-registered seam**, selected by configuration, defaulting to the
   mock, and recorded in [`mvp/blockers.md`](mvp/blockers.md) (or `archive/docs/status/` for the full historical
   ledger). Never an `if (mock)` branch scattered through the code.

---

## Naming

- The **server**'s C# namespaces, projects, and solution all use the `Baya*` prefix (`Baya.Web.Api`,
  `Baya.sln`). Keep new server code under the `Baya.*` convention.
- The **client** package is `balinyaar-client`; the `@/*` import alias maps to `client/src/*`.

The product/brand name is **Balinyaar** — «بالین‌یار» in Persian copy, with a ZWNJ, always. The server's
`Baya*` prefix is a legacy code namespace: **do not rename it without explicit instruction.** Full
conventions: [archive/docs/rules/shared/naming.md](archive/docs/rules/shared/naming.md).

---

## Quick start

```bash
# Frontend
cd client && npm install && npm run dev      # http://localhost:3000

# Backend
cd server && dotnet run --project src/API/Baya.Web.Api/Baya.Web.Api.csproj   # http://localhost:5002/swagger
```
