Replace the username/password stub with Balinyaar's real credential (phone-OTP) and add the role router every authenticated screen sits behind. - services/auth rewritten for OTP over the b2 contract: types/keys/constants, clientApi+mockApi behind a config'd seam, hooks (useRequestOtp/useVerifyOtp/ useMe/useRefresh/useLogout/useSelectRole/useSessionRoleSync). Stub removed. - A1/A2 customer login + B1/B2 nurse switch as one OTP flow at /login (PhoneStep/OtpStep: auto-verify, resend countdown, wrong/expired/lockout states). - Role router: pure resolveRoleDestination + RoleRouter -> family / nurse / admin / select-role, with a splash while /me loads (no wrong-shell flash). - SelectRole first-use screen at /select-role. - Widened AuthState (roles via SessionUser), hydrated from /me by useSessionRoleSync. - Fetch-layer silent token refresh (single-flight + one retry) + shared persistAuthTokens/clearAuthTokens; useRefresh as the on-demand path. - auth i18n namespace in both locales; tests for routing branches, countdown, OtpStep state machine, RoleRouter branches; fixed jest @/ -> src alias. - Docs: client/CLAUDE.md, frontend STATUS/report, for-backend REQ-002..004. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Balinyaar — Web Client
Frontend for Balinyaar, a trust-first home-nursing marketplace in Iran. Built with Next.js 16 (App Router), React 19, TypeScript, and Material UI (MUI) v9.
It ships with internationalization (fa/en, RTL-first), a no-flash light/dark theme system, a small
library of reusable App* components, TanStack Query for server state, and public/private layout
shells wired for cookie-based authentication.
AI agents: read CLAUDE.md — it is the engineering contract (architecture, providers, data fetching, theming, i18n, cookies, and the rules every change must follow).
Requirements
- Node.js 18+ and npm
- The backend API (see
../server) running for authenticated features
Getting started
-
Install dependencies:
npm install -
Create your local environment file from the sample and adjust values:
cp .env.sample .envKey variables (all
NEXT_PUBLIC_*are exposed to the browser):Variable Purpose NEXT_PUBLIC_ENVdevelopment|preview|productionNEXT_PUBLIC_DEBUGtrueenables extra console loggingNEXT_PUBLIC_PUBLIC_URLPublic URL of the site NEXT_PUBLIC_API_URLBase URL of the backend API (the serverproject) -
Run the dev server:
npm run devOpen http://localhost:3000. The root path redirects to
/fa(default locale).
Available scripts
| Script | Description |
|---|---|
npm run dev |
Start the development server (Turbopack) with hot reload |
npm run build |
Production build |
npm run start |
Serve a production build |
npm run lint |
Lint with ESLint (flat config, eslint .) |
npm run lint:fix |
Lint and auto-fix |
npm run type |
Type-check with tsc --noEmit |
npm run check |
Type-check and lint (the quality gate) |
npm run format |
Format the codebase with Prettier |
npm test |
Run Jest in watch mode |
npm run test:ci |
Run Jest once (CI) |
Project structure
src/
├── app/[locale]/ App Router routes, grouped into (public-routes) and (private-routes).
│ [locale]/layout.tsx is the ROOT layout (renders <html>/<body>).
├── components/ Reusable UI: common App* components (AppButton, AppIcon, …) + UserInfo
├── constants/ App-wide named constants (routes, headers, …)
├── hooks/ Custom hooks (auth, layout/mobile, events, window size)
├── i18n/ next-intl routing + request config
├── layout/ PublicLayout / PrivateLayout + TopBar, SideBar, BottomBar
├── lib/ api (client/server fetch), auth (JWT/session helpers), cookies, query, toast
├── services/ Domain services: {domain}/{types,keys,apis,hooks}
├── context/ React context providers — auth/ is AuthContext (server-seeded session state)
├── theme/ ThemeProvider, palettes, tokens.css, typography, direction
└── utils/ Helpers (storage, navigation, env, text, types)
The @/* import alias maps to src/* (see tsconfig.json).
Translation files live in messages/ (en.json / fa.json) and must stay in sync.
For the full agent-oriented map of conventions and where to make changes, see CLAUDE.md.
Notes
- This is a server-rendered Next.js app (App Router + middleware + server-side cookies) — not a static export.
- Internationalization is locale-prefixed (
/fa,/en);fais the default and is RTL. - Authentication is cookie-based (
access_token/refresh_token). Session state lives inAuthContext(src/context/auth/), seeded on the server from the request cookie so the first render reflects the real session; cookies are managed throughsrc/lib/cookies/and thesrc/services/auth/hooks. The API base URL comes fromNEXT_PUBLIC_API_URL.