- Этот файл действует для всего репозитория. Если в подпапке появится более локальный
AGENTS.md, его правила имеют приоритет для файлов внутри этой подпапки. - Перед изменениями прочитайте конфиги и документацию области задачи. Исполняемый конфиг и
фактический код приоритетнее
README.mdи описательных документов, если они расходятся. - Не исправляйте попутно чужие или уже существующие изменения рабочего дерева. Ограничивайте diff задачей пользователя.
- Идентификаторы и код пишутся на английском. В документации, комментариях и пользовательском тексте сохраняйте язык окружающего файла; основная проектная документация сейчас на русском.
- Единственный пакетный менеджер — npm под Node.js 24. Не добавляйте Bun, pnpm или Yarn команды.
bun.lockиbunfig.tomlудалены при миграции; не восстанавливайте их.package-lock.jsonобязателен для воспроизводимыхnpm ciв Docker и GitLab CI. Обновляйте его вместе сpackage.jsonи workspace manifests.- Docker, GitLab CI, Lefthook и
@repo/apiиспользуют npm. Не добавляйте отдельный способ установки или запуска для одного из этих контуров. .npmrcвключаетsave-exact,engine-strictиlegacy-peer-deps; не меняйте эти установки без отдельного решения.
- В
next.config.tsвключёнcacheComponents: true. Директива'use cache: private'при этом остаётся экспериментальной возможностью Next.js и не должна становиться production default без отдельной оценки. - React Compiler включается только в production через
reactCompiler: isProd, а не во всех режимах. - Канонический контракт использует OpenAPI 3.2. Redocly bundle передаётся Hey API без понижения и
скрытой 3.1-копии; доказательство совместимости — полный
genи roottsc, включающий generated output. @hey-api/openapi-ts@0.99.0пока не запускается с project TypeScript 7.0.2. При прямом запускеopenapi-ts.config.tsнаправляет импортtypescriptна локальный compiler workspace версии 6.0.3; удаляйте hook лишь после успешного native TypeScript 7 probe и полного parity suite.- Контейнерный контур задан в
Dockerfile,.dockerignore,compose*.yamlиMakefile: dev использует targetdevelopment, production — non-root standalone runner, а builder получаетSENTRY_AUTH_TOKENчерез BuildKit secret. Конфигурационного блокера больше нет; development smoke подтвердил startup, health checks и маршрутизацию к двум репликам. Hot update после изменения исходника, production image и production startup ещё не проверены, поэтому не объявляйте контур production-ready. Базовый Compose пока также передаётSENTRY_AUTH_TOKENв runtime environment; подробности — вdocs/deployment.md.
- Это ESM-монорепозиторий на npm workspaces: Next.js 16 App Router, React 19, TypeScript 7, Tailwind CSS 4.
- Корневое приложение собирается в Next.js standalone output и рассчитано на Node.js 24.
- Основные инфраструктурные библиотеки: TanStack Query, Zod, nuqs, Sentry, OpenTelemetry, Adze и
Prometheus
prom-client. - UI-примитивы основаны на Base UI и shadcn-подходе; не подменяйте их Radix-компонентами без явного требования.
- Для прямых dependencies сохраняйте exact versions согласно
.npmrc; диапазоны оставляйте там, где они выражают контрактpeerDependencies.
app/— Next.js routing layer: страницы, layouts, route handlers, metadata, loading/error states и локальные компоненты маршрутов.src/modules/— доменная логика, общая для нескольких маршрутов. Директория создаётся по мере появления реальных модулей, а не заранее.src/components/— переиспользуемые составные UI-компоненты и инфраструктурные providers.src/constants/,src/hooks/,src/types/,src/utils/— shared-слой без привязки к отдельному бизнес-модулю. Новые shared-каталоги создавайте только вместе с реальным кодом.src/env/— типизированные и валидируемые переменные окружения.src/mock-mode/— выбор generated API mocks и сценария во время выполнения.src/proxy/и корневойproxy.ts— pipeline Next.js proxy/BFF и служебные request headers.src/observability/иinstrumentation*.ts— логирование, метрики, Sentry и OTEL.src/tests/— общая тестовая инфраструктура и Playwright E2E.packages/core/(@repo/core) — дизайн-система и UI-примитивы.packages/api/(@repo/api) — OpenAPI-контракт, Redocly/Hey API pipeline и публичные facets для SDK, client, Query, Zod, Faker, mocks и cache tags.docs/README.md— индекс документации и её статусов.docs/architecture.md— подробная модель слоёв и размещения кода.docs/bff-proxy.md— выбор API base URL в server/dev/prod.docs/api-codegen.md— правила OpenAPI и генерации клиента.docs/cache-and-streaming.md— действующие правила Cache Components и streaming.docs/environment.md,docs/deployment.md,docs/mock-mode.md,docs/testing-guidelines.md— профильные operational references.
Зависимости направлены сверху вниз:
| Слой | Разрешённые зависимости |
|---|---|
app/ |
src/modules/, shared src/*, packages/* |
src/modules/ |
shared src/*, packages/* |
shared src/* |
packages/* |
packages/* |
только другие packages/* |
packages/api/client-config.ts— известное исключение: файл импортирует root-levelsrc/env,src/constantsиsrc/mock-mode. Не повторяйте и не расширяйте это направление зависимостей; план развязки описан вdocs/architecture.md.- Модуль в
src/modules/<name>не импортирует другой модуль напрямую. Взаимодействие организуйте через композицию в route/layout, shared event bus или dependency injection/provider. - Эти границы пока не полностью контролируются Oxlint. Проверяйте их вручную при review.
- Бизнес-логика одного маршрута остаётся рядом с ним в
app/.../_components/. Модуль создаётся, когда логика действительно нужна минимум двум маршрутам. - Общий код начинайте в самой узкой области и поднимайте только после появления второго потребителя: компонент → маршрут → модуль → shared.
index.tsмодуля или компонента — его публичный API. Не импортируйте внутренние файлы через deep import вне этой области без причины.- Не создавайте пустые
types.ts,variants.ts,hooks/илиutils/«на будущее».
- Базовый принцип: Server Components по умолчанию, Client Components только на интерактивных листьях.
- Добавляйте
'use client'только при state/effects/event handlers/browser API или client-only библиотеке. Не расширяйте client boundary на страницу или layout без необходимости. packages/core/содержит интерактивные client-примитивы; React Query hooks и providers также client-only.- Fetch-клиенты, типы и Zod-схемы
@repo/apiдолжны оставаться universal, если конкретный API не требует server-only контекста. src/env/server.ts— server-only. Никогда не импортируйте его в Client Component.- Для явно ограниченных файлов используйте суффиксы
.server.tsи.client.ts; universal-файлы оставляйте без суффикса.
- Route-local компоненты размещайте в единственной private-директории сегмента
app/.../_components/. Общие для сегмента schemas/constants/utils размещайте рядом с route. - Переиспользуемые UI-примитивы —
packages/core; составные shared-компоненты —src/components; доменные компоненты —src/modules/<module>. - Файлы и директории компонентов называются kebab-case, React-экспорты — PascalCase.
- Типовая папка компонента может содержать реализацию,
*.test.tsx,*.stories.tsx,variants.ts,types.ts, локальныеhooks/,utils/иindex.ts, но только если эти файлы нужны. - Инфраструктурные providers без знания бизнес-сущностей находятся в
src/components/providers; providers с доменными типами принадлежат соответствующему модулю.
- Используйте алиасы:
~/*для корня,@/*дляapp/,#/*дляsrc/. - Пакеты импортируются через
@repo/coreи@repo/api, а не через~/packages/...или длинные относительные пути. - Отделяйте type-only imports через
import type; это требуетсяverbatimModuleSyntaxи линтером. - TypeScript работает в строгом режиме с
noUncheckedIndexedAccess,noImplicitReturns,noUnusedLocals,noUnusedParametersиerasableSyntaxOnly. - Не заглушайте ошибки
any,@ts-ignoreили широкими type assertions. Сначала уточните модель данных и сузьте тип. - Из-за
erasableSyntaxOnlyпредпочитайте unions иas const-объекты конструкциям TypeScript, которые генерируют runtime-код, напримерenum. - Для object shapes используйте
interface, когда правило линтера не требует иного;typeоставляйте для unions, mapped/conditional types и generated code.
- Oxlint использует корпоративный
@webpractik/oxlint-configчерезoxlint.config.ts. Общие правила не копируются в проект. Type-aware проверки включены черезoxlint-tsgolint. - Единственный formatter — Oxfmt: 4 пробела, single quotes, без semicolon, ширина 100.
- Oxfmt сортирует импорты, scripts в
package.jsonи Tailwind-классы вcva/cn. Не боритесь с его результатом ручной перестановкой. - Форматируйте только изменённые файлы через
npx oxfmt <paths>;npm run fmtформатирует весь репозиторий и может затронуть чужую работу. - Oxlint запрещает неизвестные, конфликтующие и дублирующиеся Tailwind classes, проверяет a11y, React/RSC, Next.js, import order и неиспользуемый код.
console.logзапрещён. Для приложения используйте#/observability/logger;console.warnиconsole.errorразрешены только там, где logger неприменим.- Для вариантов компонентов используйте CVA, а для объединения classes — существующий
cn. - Не отключайте lint-правила на весь файл. Если локальное отключение неизбежно, делайте его узким и объясняйте конкретную причину.
- Используется App Router и typed routes. Не добавляйте Pages Router.
next.config.tsимпортирует валидированные env и создаёт BFF rewrite; build/dev могут падать до компиляции при отсутствующих переменных. Для локального запуска сначала создайте.envиз.env.example.- Cache Components включены через
cacheComponents: true. Перед использованиемuse cache,cacheLife,cacheTag,updateTagилиrevalidateTagсверяйтесь сdocs/cache-and-streaming.mdи актуальной документацией Next.js. output: 'standalone'необходим текущей контейнерной схеме; не выключайте его без изменения deploy pipeline.- Static image imports отключены, SVG разрешены через image config. Учитывайте это при выборе
между
next/image, URL и импортом asset. - Security headers и
X-Accel-Buffering: noвключаются вне development. Не ослабляйте CSP/HSTS попутно ради локального workaround. - Root layout имеет
lang="ru", Nuqs adapter, Query provider и Toaster. Новые глобальные providers добавляйте только при действительно глобальном scope.
- Новую server env переменную добавляйте в
src/env/server.tsи.env.example. - Новую browser-visible переменную добавляйте в
src/env/client.ts,.env.exampleи используйте префиксNEXT_PUBLIC_. - В приложении потребляйте env через
serverEnvironment/clientEnvironment. Прямойprocess.envоставляйте только для framework bootstrap и уже существующих build/runtime checks. - Никогда не переносите server secrets в client schema и не коммитьте
.env. - Выбор base URL в
packages/api/client-config.ts:- server всегда использует
BACK_INTERNAL_URL; - browser в development использует относительный
NEXT_PUBLIC_BFF_PATHи Next rewrite; - browser в production использует
NEXT_PUBLIC_BACK_URLнапрямую.
- server всегда использует
NEXT_PUBLIC_BFF_PATHиBACK_INTERNAL_URLобязательны для rewrite. Не хардкодьте/bff-apiвне env/config.- Корневой proxy добавляет request header
x-url; runtime mock mode использует его для определения текущего route. Сохраняйте это поведение при изменении proxy chain.
- Исходник истины —
packages/api/openapi/openapi.yamlи его$ref-файлы вpaths/иcomponents/; каноническая версия контракта — OpenAPI 3.2.0. - Каждая операция должна иметь уникальный
operationId, обязательныйsummaryи корректныйtags; tags входят в query keys, mock metadata и generated cache helpers. - Порядок pipeline: Redocly bundle →
bundled.yaml→ Hey API → post-generation helpers → Oxfmt → roottsc, включающий generated output. bundled.yaml— игнорируемый промежуточный артефакт.openapi/иcodegen/коммитятся.packages/api/codegen/, включая types, SDK, client, Query options, Zod, Faker, cache tags и mock routes, вручную не редактируется. Hey API запускается сoutput.clean: true, поэтому ручные изменения будут удалены.- После изменения OpenAPI выполните
npm --workspace @repo/api run genи связанные tests. - Публичные импорты идут только через
@repo/api,/client,/query,/schemas,/mocksи/cache-tags; generated deep paths и внутренние aliases вродеPet2не являются контрактом. - SDK принимает
path/query/bodyи по умолчанию возвращает discriminated resultdata/error/response;throwOnError: trueбросает parsed typed error. Успешные ответы проверяются generated Zod-схемами, а204возвращаетdata: undefined. findPetsByStatusInfiniteOptionsпреобразует numericpageParamвquery.offset, сохраняя остальные filters и limit; Query options компонуйте сuseQuery/useMutation/useInfiniteQuery.- Generated Zod-схемы экспортируются через
@repo/api/schemas; не копируйте их вsrc/schemas. - Для тестов и Storybook используйте generated Faker factories и mock client, а не вручную дублированные API fixtures, если нужная фабрика уже существует.
- Сначала переиспользуйте
@repo/core; новый примитив добавляйте туда только если он не содержит бизнес-логики. - Примитивы Base UI оборачивайте тонко, сохраняйте accessibility semantics и прокидывайте props.
- Варианты держите в отдельном
variants.ts, когда они нетривиальны; объединяйте className черезcnи CVA. - Для reusable UI добавляйте Storybook stories рядом с компонентом. Storybook использует
@storybook/nextjs-vite, autodocs и a11y addon. - Интерактивное поведение проверяйте browser component test, а визуальные состояния — stories; одно не заменяет другое.
- Формы создавайте через
useAppFormиз@repo/core/form: нативный<form>,event.preventDefault(),void form.handleSubmit(), поля черезform.AppField, form-компоненты внутриform.AppForm. Zod-схемы передаются напрямую в TanStack validators через Standard Schema.
npm run testзапускает оба Vitest project и все reporters.- Unit project использует Node environment и подбирает
*.unit.test.ts(x), а такжеpackages/**/*.test.ts. - Component project использует реальный headless Chromium через
@vitest/browser-playwrightи подбирает*.component.test.ts(x),app/**/*.test.tsx,src/**/*.test.tsx. - Обычный
src/**/*.test.tsбез.unit.не попадает ни в один project. Выбирайте имя файла намеренно. - Component tests пишутся через
vitest-browser-react, не через jsdom assumptions. Next navigation/image/script заменяются тестовыми aliases изsrc/tests/mocks; Base UI Toast проверяется реальным browser-компонентом без отдельного mock alias. - Vitest загружает разрешённые env values сначала из process, затем из корневого
.env; не дублируйте env setup в каждом test file. - Playwright E2E лежат в
src/tests/e2eи выполняются в Chromium. По умолчанию config поднимаетnpm run dev;PLAYWRIGHT_SERVER_MODE=standaloneилиCI=trueпереключает его на уже собранныйnpm run prod. Самодостаточныйnpm run test:e2e:standaloneсначала создаёт свежую сборку. - Текущий GitLab pipeline запускает Vitest, но не Playwright E2E и не production build.
- Playwright использует
FRONT_PORTс default3000; это отдельная переменная от serverPORT. - При исправлении bug сначала добавьте или обновите минимальный regression test, затем проверьте, что он воспроизводит проблему и проходит с исправлением.
- Для application logs используйте Adze logger из
#/observability/logger, а не новый logging abstraction. - Server instrumentation регистрирует Vercel OTEL и Sentry в Node runtime; client Sentry инициализируется только в production.
- Не логируйте credentials, cookies, authorization headers, персональные данные или полный env.
- Prometheus использует общий registry из
src/observability/metrics; endpoint —/api/metrics. Health и readiness endpoints —/api/healthи/api/ready.
# Установка и запуск
npm ci
npm run dev
npm run build
npm run prod
# Качество
npm run tsc
npm run lint
npm run lint-fix
npm run fmt:check
npm run knip
npm run jscpd
npm run verify:fast
npm run verify
# Тесты
npm run test
npm run test:unit
npm run test:component
npm run test:coverage
npm run test:e2e
npm run test:e2e:standalone
npx vitest run src/mock-mode/runtime.unit.test.ts --project unit
npx vitest run src/components/utilities/error-boundary/error-boundary.test.tsx --project component
npx playwright test src/tests/e2e/example.spec.ts
# Storybook
npm run storybook
npm run build-storybook
# Workspace-команды
npm --workspace @repo/api run test
npm --workspace @repo/api run gen
npm --workspace @repo/api run bundle
npm --workspace @repo/api run lint:openapi
# Docker Compose
make compose-config-dev
make compose-config-prod
make compose-dev
make compose-prod- Зафиксируйте исходное состояние через
git status --shortи определите существующие чужие изменения. - Прочитайте ближайший код, tests и профильную документацию до изменения интерфейса или архитектуры.
- Делайте минимальный связный diff; не форматируйте и не рефакторьте соседний код без причины.
- Для generated code меняйте источник/генератор, затем регенерируйте; не патчите output.
- Запустите formatter check и самые узкие релевантные tests.
- Для TypeScript/React изменений дополнительно запустите
npm run tscиnpm run lint. - Для route, Next.js config, env или proxy изменений выполните
npm run build, если окружение позволяет. Для Docker/Compose дополнительно проверьте соответствующийmake compose-config-*, image build и smoke test изменённого режима. - Для UI проверьте component tests и, когда меняется реальное browser behavior, Playwright или ручной browser smoke test.
- Перед завершением перечитайте diff, сообщите точные выполненные проверки и отдельно перечислите непроверенные риски или известные блокеры.
- Изменение соответствует границам слоёв и не создаёт новый cross-module import.
- Нет ручных изменений generated API output.
- Нет случайных изменений lockfiles, артефактов tests,
.envили соседних файлов. - Изменённые файлы отформатированы; релевантные lint, types и tests проходят свежим запуском.
- Поведение, публичный API, env contract или архитектурное решение отражены в соответствующей документации.
- Итоговое сообщение не утверждает, что весь проект исправен, если был проверен только узкий scope.