# AGENTS.md

Entry point for AI agents working in this repo. Read this first, then `.cursorrules`, then the `.ai/context/` docs.

## What this is

**BEEB BEEP — لوحة المستثمر** (Investor Dashboard): a Next.js **App Router** dashboard, fully **Arabic / RTL**, dark-themed, for investors who own vehicles (electric scooters) in the BEEB BEEP rental fleet. Investors view earnings, manage a fleet, withdraw profits, and manage their account.

- **Company / internal name:** Horizon Prosperity — شركة ازدهار الأفق (the repo is `horizon-prosperity-dashboard`).
- **User-facing brand:** **BEEB BEEP / بيب بيب**, duck-mascot logo at `public/imgs/beeb-logo.svg`. ⚠️ Note: the spelling is **inconsistent in code** — `BEEPBEEP` (`app/layout.tsx` metadata, `Sidebar.tsx`, `app/page.tsx`, `*@beepbeep.sa` placeholders), `BEEBPEEP` (`AuthLayout.tsx` header/footer, `SignupForm` success copy), and `BEEB BEEP` (logo alt). Treat all three as the same brand; don't "fix" one spelling to another as a side effect.
- **Theme:** dark by default, **yellow / gold `#FCD704`** primary. Exact palette is hardcoded inline (no token layer) — see [conventions.md](.ai/context/conventions.md). **TODO:** pull exact values from the Figma variables when available (Figma node refs currently live only as comments in `components/auth/AuthBranding.tsx`, e.g. `effect_PL7WFQ`).

**Critical framing — this is a HYBRID, mid-wiring app, not a pure mock:**

- **Auth is REAL.** Login and registration call a real backend through the `apiFetch` client (`/provider/login`, `/provider/register`), persist the session in a **Zustand** store (`useAuthStore`, cookie-backed), and gate routes client-side via `AuthGuard`. See [api-fetching.md](.ai/context/api-fetching.md) and [state-and-data.md](.ai/context/state-and-data.md).
- **Everything else is still mock.** Home, earnings, scooters, add-scooter, withdraw, profile, change-password hold **inline `const` data** and fake their actions with `setTimeout(~1500)` → a success card. Keep that pattern for those pages unless a task is explicitly to wire them.

Treat this as: *auth wired, the rest a high-fidelity mock being migrated onto the same `apiFetch` + store seams.*

## Stack

| Item | Value |
| --- | --- |
| Framework | Next.js `^15.5.19`, App Router, `output: "export"` (static export — no server runtime, route handlers, or middleware) |
| UI | React `^19.1.2` |
| Language | TypeScript `^5`, `strict: true` |
| State | **Zustand `^5`** for the auth session (`lib/auth/store.ts`); local `useState` everywhere else |
| Forms | **react-hook-form `^7` + `@hookform/resolvers/yup` + `yup ^1`**, schemas built via `hooks/useValidation.ts` — **canonical** (see below) |
| Data | `apiFetch` client in `lib/api/` (the only fetch path); backend always returns HTTP 200, branch on `body.key` |
| Styling | **Tailwind CSS v3** (`tailwind.config.js`, empty theme) — utility classes + inline arbitrary hex values. No component library, no CSS vars for color |
| Icons | Remix Icon 4.5.0 via CDN `@import` in `globals.css` (`<i className="ri-*">`) — **not** `lucide-react` (don't add it back) |
| Charts | recharts `^3` |
| Font | Cairo (`next/font/google`, `--font-cairo`) |
| i18n | **None.** No catalog/library — UI copy is **Arabic string literals**. (`useValidation`'s `t()` is a private Arabic map, not real i18n.) |
| Path alias | `@/*` → repo root |

## AI reading order

1. **`AGENTS.md`** (this file) — orientation + Definition of Done.
2. **`.cursorrules`** — short enforceable rules.
3. **`.ai/context/`** — one concern per file:
   - [`overview.md`](.ai/context/overview.md) — product & domain (investors, fleet, earnings, withdrawals)
   - [`structure.md`](.ai/context/structure.md) — folder layout + where new things go
   - [`routing.md`](.ai/context/routing.md) — App Router routes, layouts, `AuthGuard`
   - [`components.md`](.ai/context/components.md) — inventory + composition/dependency map
   - [`conventions.md`](.ai/context/conventions.md) — naming, styling, RTL, theme, the form recipe
   - [`state-and-data.md`](.ai/context/state-and-data.md) — Zustand auth, what's wired vs. still mock
   - [`api-fetching.md`](.ai/context/api-fetching.md) — backend contract + the `apiFetch` client (the only fetch path)

## Core conventions (summary — full detail in conventions.md)

- **RTL-first.** App is `<html lang="ar" dir="rtl">`. Uses **physical** Tailwind props, not logical ones: text defaults `text-right`; icon padding `pr-12`/`pl-12`; absolute icons/toggles at `right-4`/`left-4`; right-to-left rows use `justify-end`/`flex-row-reverse`; numeric inputs (IBAN, amounts, national id) force `dir="ltr"`. UI copy is Arabic string literals (no i18n library).
- **Tailwind utilities only**, with inline arbitrary values. Palette: page `#13151A`, surface `#1E2128`, popover `#2A2D36`, login bg `#0E1015`, accent yellow `#FCD704`. No theme tokens, no CSS Modules/CSS-in-JS (gradients via inline `style`).
- **Imports via `@/`** alias. One default-export component per `.tsx` file, PascalCase. Feature subfolders under `components/`.
- **`'use client'`** only when the file uses state/effects/handlers/browser APIs; otherwise it's a server component.
- **Icons** = Remix Icon `<i className="ri-*-line" />` (`-fill` for active). Charts = recharts in `ResponsiveContainer`.
- **Forms (canonical)** = **react-hook-form + `yupResolver` + `useValidation`** — reference: [`LoginForm.tsx`](components/auth/LoginForm.tsx). `SignupForm` (step 1) and `ChangePasswordForm` use an older **manual `useState` + hand-rolled `validate()`** pattern; treat those as **legacy to migrate**, not a model to copy for new forms.
- **State** = `useAuthStore` (Zustand) for the session only; local `useState` for everything else. Don't add new global stores without a reason.
- **Data fetching** = **always** `apiFetch` from `@/lib/api`; **never call `fetch` directly.** The backend always returns HTTP 200 — branch on `body.key`, not status. Full contract in [api-fetching.md](.ai/context/api-fetching.md).

## Definition of Done

A change is done when:

1. **Style matches** the existing app — RTL handling correct (physical props), Tailwind arbitrary-value palette, Remix Icons, Cairo; follows the page/component/form recipes in [`conventions.md`](.ai/context/conventions.md).
2. **TypeScript strict passes** — `npx tsc --noEmit` is clean; no new `any` outside the established recharts-tooltip pattern. (`output: "export"` means type errors also fail `next build`.)
3. **`npm run lint`** is clean.
4. **No new dead code** — every component/import/dependency you add is actually rendered/used. Don't import what you don't render. (The previously-documented dead code has been removed; keep the [components.md](.ai/context/components.md) dead-code ledger empty.)
5. **Links resolve** — any `Link`/`router.push` target is a real route under `app/`.
6. **Forms** use the canonical react-hook-form + `useValidation` path; reuse existing yup builders (e.g. `validation.password()`, `validation.password_confirmation()`) rather than re-deriving rules.
7. **Data/auth wiring** — any real request goes through `apiFetch` from `@/lib/api` (never raw `fetch`), branches on `body.key`, and types its payload via `apiFetch<T>`. Auth state lives in `useAuthStore`; protected routes use `AuthGuard`. For pages **still on mock data**, keep the inline-`const` + faked-`setTimeout` pattern unless the task is explicitly to wire them — see [state-and-data.md](.ai/context/state-and-data.md).
8. **i18n** — there is no catalog; write Arabic string literals. (Only add an i18n check if a catalog is ever introduced.)
9. **Grounded** — verify against real code, not assumptions; don't contradict the audit docs without noting it.
