2.8 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
npm run dev # Start dev server on port 3000
npm run build # Type-check (tsc -b) then Vite build
npm run preview # Preview production build
npm run lint # ESLint check
No test runner is configured.
Architecture
This is a React 19 + Vite frontend following Feature-Sliced Design (FSD). Layers are strictly ordered — lower layers must not import from higher ones:
app → pages → widgets → features → entities → shared
Path aliases map directly to FSD layers (@app/*, @pages/*, @widgets/*, @features/*, @entities/*, @shared/*) via vite-tsconfig-paths.
Layer responsibilities
app/— global providers (React Query, router), global CSS (styles/). Entry:App.tsxwrapsQueryProvider → RouterProvider.pages/— route-level page components. Each page composes widgets.widgets/— self-contained UI blocks (Hero, CurrencyConverter, NetworksTable, etc.). Contain their ownmodel/,ui/, and barrelindex.ts.features/— user-facing capabilities. Currently onlyauth/(hooks + API calls).shared/— cross-cutting utilities, never feature-specific:api/— fetch wrapper (base.ts), CSRF token cache (csrf.ts), in-memory access token store (tokenStore.ts)config/—routes.ts(ROUTES const),env.ts(VITE_API_URL),constants.tsui/— reusable components (Button, PrimaryButton, FormField, Pill, Title, TokenIcon, Notification) with CSS Moduleslib/— generic hooks (useDebounce, useLocalStorage) and utils (cn)
Auth flow
Authentication uses two-step email+code flows for both registration and login. The access token lives in an in-memory tokenStore (not localStorage). It is refreshed against https://app.auth.elcsa.ru/v1/jwt/refresh using an HttpOnly cookie. useAuth() triggers this refresh on app load via React Query; useIsAuthenticated() derives auth state from that query.
Every API request (via shared/api/base.ts) attaches a CSRF token fetched from /csrf/token (cached in module scope) and the Bearer token if present. On 401 it attempts one silent refresh before throwing.
Routing
ProtectedRoute redirects unauthenticated users to /login. GuestRoute redirects already-authenticated users away from /login and /register. The converter page (/converter) is public but not a guest-only route.
Styling
Plain CSS Modules (.module.css) — no Tailwind or CSS-in-JS. Global design tokens live in src/app/styles/variables.css.
Environment
VITE_API_URL must be set (used in src/shared/config/env.ts). Create a .env.local for local development.