# AGENTS.md — shop (craftshop monorepo)

## Project structure

- `client/` — frontend (React + Vite + TypeScript + MUI), **FSD architecture**: `app/pages/widgets/features/entities/shared`
- `server/` — backend (Fastify + Prisma + SQLite)
- `shared/constants/` — JS + `.d.ts` files shared between client and server (order statuses, delivery carriers, payment methods, upload limits)

## Developer commands

### Client (`cd client`)

| Command | What it does |
|---|---|
| `npm run dev` | Vite dev server on `:5173`, proxies `/api` and `/uploads` to `http://127.0.0.1:3333` |
| `npm run build` | Runs `tsc -b` first, then `vite build` |
| `npm run lint` | ESLint (flat config) |
| `npm run lint:fix` | ESLint with `--fix` |
| `npm run format` | Prettier write all |
| `npm run format:check` | Prettier check only |
| `npm test` | vitest run |
| `npm run test:watch` | vitest watch mode |

### Server (`cd server`)

| Command | What it does |
|---|---|
| `npm run dev` | `node --env-file=.env --watch src/index.js` (requires Node 20.6+) |
| `npm run dev:classic` | `node --watch src/index.js` (loads `.env` via dotenv) |
| `npm run lint` | ESLint (flat config) |
| `npm run lint:fix` | ESLint with `--fix` |
| `npm run format` | Prettier write all |
| `npm run format:check` | Prettier check only |
| `npm test` | vitest run |
| `npm run db:reset:test` | Reset SQLite DB + re-run migrations + seed (uses `.env`) |

### Build order (when changing both packages)

```bash
cd server && npm run db:migrate   # if schema changed
cd server && npm test             # server tests first
cd client && npm run lint && npm run format:check && npm test  # then client
cd client && npm run build        # full typecheck + build
```

## Conventions

- **Language**: Отвечай пользователю **на русском**.
- **Single quotes**, no semicolons, trailing commas, 120 print width (Prettier + ESLint enforce).
- **FSD import boundaries** enforced by `eslint-plugin-boundaries`. Lower layers cannot import upper layers. If ESLint complains about an import, the architecture is wrong.
- **Aliases**: `@/` → `client/src/`, `@shared/` → `shared/` (configured in both vite.config.ts and tsconfig).
- **API requests**: Use `apiClient` (axios wrapper from `shared/api/`) with `@tanstack/react-query`. Invalidate queries after mutations.
- **UI**: Prefer MUI components over custom HTML/CSS.
- **`no-console`**: ESLint error; use `console.warn/error/info` only.
- **Admin access**: Only users with email matching `ADMIN_EMAIL` env var can access admin routes. Server auto-creates the admin user on startup.
- **Server helpers**: `slugify`, `parseMaterialsInput`, `mapProductForApi` are decorated on fastify instance, accessed via `request.server.*`.

## Testing

- **Client**: vitest + jsdom + @testing-library/react. Setup file: `client/src/testing/setup.ts`.
- **Server**: vitest with globals enabled.
- Test files live in `__tests__/` directories next to the code they test.

## OAuth

- VK callback: `{SERVER_PUBLIC_URL}/api/auth/oauth/vk/callback`
- Yandex callback: `{SERVER_PUBLIC_URL}/api/auth/oauth/yandex/callback`
- Required env vars: `VK_CLIENT_ID`, `VK_CLIENT_SECRET`, `YANDEX_CLIENT_ID`, `YANDEX_CLIENT_SECRET`, `SERVER_PUBLIC_URL`, `CLIENT_PUBLIC_URL`

## Infrastructure (deployment)

- **VPS** runs Nginx Proxy Manager (NPM), connected via Netbird peer-to-peer VPN to the dev machine
- **Local dev machine** runs the project (server + client), also a Netbird peer
- **Traffic flow**: Browser → Domain (A record → VPS IP) → NPM → Netbird tunnel → Local dev machine (`server:3333`)
- NPM manages SSL, domains, and proxy hosts
- `trustProxy: true` on Fastify — `request.ip` works correctly through NPM/Netbird chain

## Notable quirks

- `.env` is gitignored. Copy `.env.example` to `.env` for local dev.
- Vite dev server (client) relies on backend running at `127.0.0.1:3333`. Start server first.
- Rich text rendering uses `shared/ui/RichTextMessageContent` (TipTap). Pass `tone="review"`, `tone="chat"`, or `tone="default"`.
- `db:reset:test` runs `prisma migrate reset --force`, which destroys all data.
