Перейти к основному содержимому

Frontend baseline

Зачем нужно

Документ задаёт обязательные правила для всех frontend-приложений: маршрутизация, защита маршрутов, API-клиент, состояния, формы, ошибки.

Стек

СлойТехнология
ФреймворкNext.js 14 (App Router)
React18
ЯзыкTypeScript 5.4+
State serverTanStack Query
State clientZustand
ФормыReact Hook Form + Zod
СтилиCSS Modules + токены UI Kit
МаршрутизацияApp Router
ТестыVitest, Playwright
Аналитикачерез server-side proxy, без сторонних SDK на клиенте без согласия

Маршруты

  • Публичные: / и страницы лендингов;
  • Защищённые: /app/... редирект на identity при отсутствии сессии;
  • Админские: /admin/... плюс проверка permissions на сервере (next middleware).

Маршрутизация — App Router, layout-based, серверные компоненты по умолчанию, клиентские по необходимости.

Защита маршрутов

  • Next middleware читает identity session cookie, при отсутствии — редирект на identity authorize.
  • На сервере — проверка через getServerSession() обёртку из packages/auth-client.
  • Проверка permissions — на сервере (Server Actions / Route Handlers), клиент только скрывает UI.

API-клиент

  • Общий пакет packages/api-client, единый для всех frontend.
  • Базовый URL берётся из ENV (NEXT_PUBLIC_API_BASE_URL).
  • Заголовки: Authorization, X-Request-Id, X-Actor-Context, Accept-Language.
  • Обработка 401: silent refresh; при втором 401 — logout.
  • Обработка 403, 404, 409, 422: типизированные ошибки.
  • Идемпотентные запросы: автогенерация Idempotency-Key.

TanStack Query

  • Один QueryClient на приложение;
  • queryKey наследуется по сущности: ['lms', 'courses', { filter }];
  • staleTime по умолчанию 30 секунд;
  • ошибки из API уходят через onError в общий error boundary.

Zustand

  • Только для client-only state, не дублирующего server state;
  • персист с zustand/middleware/persist только для UI-предпочтений (тема, фильтры, модалки).

Формы

  • React Hook Form + Zod-схема (общая с backend через packages/api-contracts);
  • inline-валидация по blur;
  • ошибки с сервера маппятся на поля формы по error.details[].field.

i18n

  • Базовый язык — русский, ключи в JSON по доменам;
  • locale — из URL или из cookie identity;
  • даты, числа, валюта — через Intl.

SEO

  • Storefront: SSR/SSG, sitemap, robots.txt, Open Graph;
  • защищённые приложения: noindex, nofollow.

Производительность

  • Бюджеты:
    • landing JS gzipped < 150 KB;
    • app JS gzipped < 300 KB;
    • LCP < 2.5s, INP < 200ms, CLS < 0.1;
  • Динамический импорт тяжёлых либ;
  • Изображения через next/image с явными размерами;
  • Шрифты через next/font, max 2 семейства.

Доступность

  • Обязательно WCAG 2.2 AA.
  • Все интерактивные элементы — клавиатурно доступны.
  • Modal/Drawer — с focus trap и aria-modal.
  • skip-link на главных страницах.
  • prefers-reduced-motion.

Состояния UI

Каждый экран должен покрывать:

  • loading;
  • empty;
  • success/data;
  • partial (кеш + обновление);
  • error.

Ошибки

  • error boundary на уровне layout;
  • инлайн-ошибки в формах;
  • Toast для системных сообщений;
  • Sentry-перехват необработанных ошибок.

Запрещено

  • Хранить токены в localStorage/sessionStorage доступном JS.
  • Реализовывать собственный логин-флоу.
  • Хардкодить URL, цвета, ключи API в коде вместо ENV/токенов.
  • Использовать сторонний UI-фреймворк, дублирующий UI Kit.
  • Использовать dangerouslySetInnerHTML без sanitizer.

Связанные документы