Light up the two faces of the configurable service catalog over a new cached services/catalog domain (consumes the b5 contract; unlocks f6 search). - services/catalog: types/keys/constants/apis(client+mock+seam)/hooks/index + names.ts. Categories & option groups are session-cached reference data (Infinity staleTime, like geography); variant mutations invalidate myVariantsLists() and setQueryData the edited row. Mock-primary (USE_CATALOG_MOCK), one-line swap; mock reproduces the 400 missing-required and (nurse,category,option-set) 409 duplicate rules. - Customer Home (A5): greeting+avatar, search bar (navigates toward f6), data-driven category grid (loading/empty/error), patient nudge from the cached f2 query. Deferred /search placeholder stub. - Nurse Services & prices (B7) at /nurse/services: offerings list (active vs deactivated, edit, soft-deactivate w/ confirm, reactivate, no delete) and a 3-step variant builder (category -> required/optional options -> price+unit+ duration). Required-group gate; Toman->IRR digit-string at the field boundary (no float); live unit-aware estimated total (never from price alone); editable auto display_name; inline 409 duplicate warning; locked category edit form. - Shared, tested components: CategoryTile, PriceDisplay, VariantCard. Money util: tomanToRial + multiplyIrr (integer-safe) + tests. - i18n: catalog/services/search namespaces + home additions + nav.services (both locales, in sync). Icons, routes (SEARCH, NURSE_SERVICES), nurse nav. Gate: npm run check green; npm run test:ci green (147 tests, +18 across 4 suites); npm run build green with NEXT_PUBLIC_API_URL set. Docs: client/CLAUDE.md (Project Structure, caching note, namespaces), STATUS, for-backend REQ-010 (pagination param casing), phase report, mocks registry. 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.