# AGENTS.md — Balinyaar Web Client Agent-oriented guide to the frontend. For human setup/run instructions see [README.md](README.md). ## Stack - **Next.js** with the **App Router** (`src/app/`), statically exported (`output: 'export'` in `next.config.mjs` → builds to `out/`) - **React** + **TypeScript** (`strict` mode) - **Material UI (MUI)** for components and theming (Emotion under the hood) - **Jest** + **Testing Library** for unit tests - ESLint (`eslint-config-next`) + Prettier ## Commands | Task | Command | | ------------ | ------------------ | | Dev server | `npm run dev` | | Build | `npm run build` | | Lint | `npm run lint` | | Type-check | `npm run type` | | Format | `npm run format` | | Test (watch) | `npm test` | | Test (CI) | `npm run test:ci` | Always run `npm run lint` and `npm run type` after a change. Run `npm run test:ci` when you touch a component that has a `*.test.tsx`. ## Directory map ``` src/ ├── app/ Routes (App Router). Each folder = a route; page.tsx = the page. │ ├── layout.tsx Root layout: store + theme providers, global │ ├── page.tsx "/" entry (delegates to home) │ ├── home/ about/ Content pages │ ├── auth/login|signup Auth pages (LoginForm is currently a stub) │ └── me/ Authenticated user page ├── components/ │ ├── common/ Reusable App* primitives (see below) + ErrorBoundary │ └── UserInfo/ Logged-in user summary ├── hooks/ useIsAuthenticated, useIsMobile, event hooks, useWindowSize ├── layout/ PublicLayout / PrivateLayout + TopBar, SideBar, BottomBar, config ├── store/ Global state: React context + reducer (AppStore, AppReducer) ├── theme/ ThemeProvider, light/dark palettes, colors, MUI-for-Next bridge └── utils/ storage (local/session), navigation, environment, text, types ``` ## Conventions (follow these) - **Imports**: use the `@/*` alias for anything under `src/` (e.g. `import { AppButton } from '@/components'`). The alias is defined in `tsconfig.json`. - **Barrel files**: most folders export through an `index.ts(x)`. Add new public exports there (e.g. a new common component is re-exported from `src/components/common/index.tsx`, which `src/components/index.tsx` re-exports). - **Common components** live in `src/components/common//` as a folder containing `.tsx`, `index.tsx` (re-export), and an optional `.test.tsx`. Existing ones: `AppAlert`, `AppButton`, `AppIcon`, `AppIconButton`, `AppImage`, `AppLink`, `AppLoading`. Prefer reusing these over raw MUI where one exists. - **Icons**: reference icons by string name through `AppIcon`. The name→icon map is in `src/components/common/AppIcon/config.ts`; add new icons there (custom SVGs go in `AppIcon/icons/`). - **Navigation**: sidebar/bottom-bar items are arrays of `LinkToPage` defined inside `PublicLayout.tsx` / `PrivateLayout.tsx`. Add a route → add an entry there to surface it in the nav. - **Two layouts**: `PrivateLayout` (after auth) and `PublicLayout` (before auth); `CurrentLayout` picks between them based on auth state. The app name lives in the `TITLE_PRIVATE` / `TITLE_PUBLIC` constants in those files. - **Auth is a stub.** `src/hooks/auth.ts` and `src/app/auth/login/LoginForm.tsx` fake login by writing a placeholder token to session storage (`// TODO: AUTH:`). When implementing real auth, replace those spots and point requests at `NEXT_PUBLIC_API_URL` (the `server` project's JWT endpoints). - **Theming**: use the theme/palette via MUI's `sx` / `useTheme`; don't hardcode colors. Light/dark values are in `src/theme/light.ts` and `dark.ts`; dark-mode toggle flows through the store. - **Client vs server components**: files needing hooks/browser APIs start with `'use client';` (see `LoginForm.tsx`). Pages that only render markup can stay server components. ## Environment Browser-exposed config comes from `NEXT_PUBLIC_*` variables (copy `.env.sample` → `.env`). The ones actually read in code: `NEXT_PUBLIC_ENV`, `NEXT_PUBLIC_DEBUG`, `NEXT_PUBLIC_PUBLIC_URL` (see `src/config.ts`) and `NEXT_PUBLIC_VERSION` (see `src/utils/environment.ts`). `NEXT_PUBLIC_API_URL` is the backend base URL. ## Gotchas - Static export (`output: 'export'`) means **no server-side runtime** — no API routes, no SSR-only features, `images.unoptimized` is on. - Don't reintroduce the removed demo/showcase route (`src/app/dev`) or `Demo*` components — they were template content.