From 4aeb1dd6b28dd8ce9479ccac3b0693a354976b69 Mon Sep 17 00:00:00 2001 From: "S.Gromov" Date: Mon, 20 Apr 2026 06:40:34 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20Progressive=20Disclosure=20=D0=B4=D0=BE?= =?UTF-8?q?=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 11 +- CONTRIBUTING.md | 250 +-- OLD_parts/1-assistent.md | 19 - OLD_parts/10-stores.md | 84 - OLD_parts/11-css.md | 227 -- OLD_parts/12-components.md | 88 - OLD_parts/13-hooks.md | 68 - OLD_parts/14-api-hooks.md | 124 -- OLD_parts/15-api.md | 242 --- OLD_parts/3-general-principles.md | 21 - OLD_parts/4-arkhitektura.md | 22 - OLD_parts/5-code-style.md | 74 - OLD_parts/6-naming.md | 18 - OLD_parts/7-docs.md | 69 - OLD_parts/8-typing.md | 187 -- OLD_parts/9-localization.md | 12 - README.md | 84 +- README_RU.md | 60 - concat-md.js | 107 - docs/en/applied/api.md | 5 - docs/en/applied/components.md | 7 - docs/en/applied/fonts.md | 5 - docs/en/applied/hooks.md | 5 - docs/en/applied/images-sprites.md | 5 - docs/en/applied/localization.md | 5 - docs/en/applied/page-level.md | 7 - docs/en/applied/project-structure.md | 7 - docs/en/applied/stores.md | 5 - docs/en/applied/styles.md | 7 - docs/en/applied/svg-sprites.md | 5 - docs/en/applied/templates-generation.md | 7 - docs/en/applied/video.md | 5 - docs/en/basics/architecture.md | 7 - docs/en/basics/code-style.md | 7 - docs/en/basics/documentation.md | 7 - docs/en/basics/naming.md | 7 - docs/en/basics/tech-stack.md | 7 - docs/en/basics/typing.md | 7 - docs/en/index.md | 57 - docs/en/workflow/creating-app.md | 7 - docs/en/workflow/creating-components.md | 7 - docs/en/workflow/creating-pages.md | 7 - docs/en/workflow/data-fetching.md | 7 - docs/en/workflow/getting-started.md | 7 - docs/en/workflow/localization.md | 7 - docs/en/workflow/state-management.md | 7 - docs/en/workflow/styling.md | 7 - docs/ru/applied/api.md | 0 docs/ru/applied/fonts.md | 0 docs/ru/applied/hooks.md | 0 docs/ru/applied/images-sprites.md | 0 docs/ru/applied/localization.md | 0 docs/ru/applied/stores.md | 0 docs/ru/applied/svg-sprites.md | 5 - docs/ru/applied/video.md | 0 docs/ru/basics/architecture.md | 471 ---- docs/ru/index.md | 60 - docs/ru/workflow.md | 87 - docs/ru/workflow/code-generation.md | 32 - docs/ru/workflow/creating-app.md | 31 - docs/ru/workflow/creating-components.md | 22 - docs/ru/workflow/creating-pages.md | 27 - docs/ru/workflow/data-fetching.md | 7 - docs/ru/workflow/localization.md | 7 - docs/ru/workflow/state-management.md | 7 - docs/ru/workflow/styling.md | 23 - generated/en/RULES.md | 137 -- generated/ru/RULES.md | 1901 ----------------- package.json | 2 +- scripts/build-ai.js | 88 + scripts/nextjs.build.js | 70 + src/base/applied/api.md | 5 + {docs/ru => src/base}/applied/components.md | 8 +- src/base/applied/fonts.md | 5 + src/base/applied/hooks.md | 5 + src/base/applied/images-sprites.md | 5 + src/base/applied/localization.md | 5 + src/base/applied/stores.md | 5 + {docs/ru => src/base}/applied/styles.md | 18 +- src/base/applied/svg-sprites.md | 7 + .../base}/applied/templates-generation.md | 21 +- src/base/applied/video.md | 5 + {docs/ru => src/base}/applied/vscode.md | 4 +- src/base/basics/architecture.md | 658 ++++++ {docs/ru => src/base}/basics/code-style.md | 4 +- {docs/ru => src/base}/basics/documentation.md | 4 +- .../base/basics}/getting-started.md | 4 +- {docs/ru => src/base}/basics/naming.md | 4 +- {docs/ru => src/base}/basics/tech-stack.md | 4 +- {docs/ru => src/base}/basics/typing.md | 4 +- src/base/triggers/develop/add-api-request.md | 35 + src/base/triggers/develop/add-dependency.md | 24 + src/base/triggers/develop/add-font.md | 28 + src/base/triggers/develop/add-icon.md | 29 + src/base/triggers/develop/add-image.md | 30 + src/base/triggers/develop/add-localization.md | 28 + src/base/triggers/develop/add-video.md | 27 + src/base/triggers/develop/connect-store.md | 31 + src/base/triggers/develop/create-component.md | 38 + src/base/triggers/develop/create-entity.md | 34 + src/base/triggers/develop/create-feature.md | 37 + src/base/triggers/develop/create-hook.md | 36 + src/base/triggers/develop/create-store.md | 36 + src/base/triggers/develop/create-widget.md | 32 + src/base/triggers/develop/generate-module.md | 37 + src/base/triggers/develop/setup-vscode.md | 24 + src/base/triggers/develop/style-component.md | 35 + src/nextjs/DEVELOP.md | 51 + src/nextjs/REVIEW.md | 43 + {docs/ru => src/nextjs}/applied/page-level.md | 8 +- .../nextjs}/applied/project-structure.md | 4 +- .../triggers/develop/add-server-data.md | 33 + src/nextjs/triggers/develop/create-layout.md | 34 + src/nextjs/triggers/develop/create-page.md | 36 + src/nextjs/triggers/develop/create-project.md | 52 + 115 files changed, 1861 insertions(+), 4690 deletions(-) delete mode 100644 OLD_parts/1-assistent.md delete mode 100644 OLD_parts/10-stores.md delete mode 100644 OLD_parts/11-css.md delete mode 100644 OLD_parts/12-components.md delete mode 100644 OLD_parts/13-hooks.md delete mode 100644 OLD_parts/14-api-hooks.md delete mode 100644 OLD_parts/15-api.md delete mode 100644 OLD_parts/3-general-principles.md delete mode 100644 OLD_parts/4-arkhitektura.md delete mode 100644 OLD_parts/5-code-style.md delete mode 100644 OLD_parts/6-naming.md delete mode 100644 OLD_parts/7-docs.md delete mode 100644 OLD_parts/8-typing.md delete mode 100644 OLD_parts/9-localization.md delete mode 100644 README_RU.md delete mode 100644 concat-md.js delete mode 100644 docs/en/applied/api.md delete mode 100644 docs/en/applied/components.md delete mode 100644 docs/en/applied/fonts.md delete mode 100644 docs/en/applied/hooks.md delete mode 100644 docs/en/applied/images-sprites.md delete mode 100644 docs/en/applied/localization.md delete mode 100644 docs/en/applied/page-level.md delete mode 100644 docs/en/applied/project-structure.md delete mode 100644 docs/en/applied/stores.md delete mode 100644 docs/en/applied/styles.md delete mode 100644 docs/en/applied/svg-sprites.md delete mode 100644 docs/en/applied/templates-generation.md delete mode 100644 docs/en/applied/video.md delete mode 100644 docs/en/basics/architecture.md delete mode 100644 docs/en/basics/code-style.md delete mode 100644 docs/en/basics/documentation.md delete mode 100644 docs/en/basics/naming.md delete mode 100644 docs/en/basics/tech-stack.md delete mode 100644 docs/en/basics/typing.md delete mode 100644 docs/en/index.md delete mode 100644 docs/en/workflow/creating-app.md delete mode 100644 docs/en/workflow/creating-components.md delete mode 100644 docs/en/workflow/creating-pages.md delete mode 100644 docs/en/workflow/data-fetching.md delete mode 100644 docs/en/workflow/getting-started.md delete mode 100644 docs/en/workflow/localization.md delete mode 100644 docs/en/workflow/state-management.md delete mode 100644 docs/en/workflow/styling.md delete mode 100644 docs/ru/applied/api.md delete mode 100644 docs/ru/applied/fonts.md delete mode 100644 docs/ru/applied/hooks.md delete mode 100644 docs/ru/applied/images-sprites.md delete mode 100644 docs/ru/applied/localization.md delete mode 100644 docs/ru/applied/stores.md delete mode 100644 docs/ru/applied/svg-sprites.md delete mode 100644 docs/ru/applied/video.md delete mode 100644 docs/ru/basics/architecture.md delete mode 100644 docs/ru/index.md delete mode 100644 docs/ru/workflow.md delete mode 100644 docs/ru/workflow/code-generation.md delete mode 100644 docs/ru/workflow/creating-app.md delete mode 100644 docs/ru/workflow/creating-components.md delete mode 100644 docs/ru/workflow/creating-pages.md delete mode 100644 docs/ru/workflow/data-fetching.md delete mode 100644 docs/ru/workflow/localization.md delete mode 100644 docs/ru/workflow/state-management.md delete mode 100644 docs/ru/workflow/styling.md delete mode 100644 generated/en/RULES.md delete mode 100644 generated/ru/RULES.md create mode 100644 scripts/build-ai.js create mode 100644 scripts/nextjs.build.js create mode 100644 src/base/applied/api.md rename {docs/ru => src/base}/applied/components.md (88%) create mode 100644 src/base/applied/fonts.md create mode 100644 src/base/applied/hooks.md create mode 100644 src/base/applied/images-sprites.md create mode 100644 src/base/applied/localization.md create mode 100644 src/base/applied/stores.md rename {docs/ru => src/base}/applied/styles.md (83%) create mode 100644 src/base/applied/svg-sprites.md rename {docs/ru => src/base}/applied/templates-generation.md (85%) create mode 100644 src/base/applied/video.md rename {docs/ru => src/base}/applied/vscode.md (96%) create mode 100644 src/base/basics/architecture.md rename {docs/ru => src/base}/basics/code-style.md (94%) rename {docs/ru => src/base}/basics/documentation.md (93%) rename {docs/ru/workflow => src/base/basics}/getting-started.md (86%) rename {docs/ru => src/base}/basics/naming.md (93%) rename {docs/ru => src/base}/basics/tech-stack.md (87%) rename {docs/ru => src/base}/basics/typing.md (89%) create mode 100644 src/base/triggers/develop/add-api-request.md create mode 100644 src/base/triggers/develop/add-dependency.md create mode 100644 src/base/triggers/develop/add-font.md create mode 100644 src/base/triggers/develop/add-icon.md create mode 100644 src/base/triggers/develop/add-image.md create mode 100644 src/base/triggers/develop/add-localization.md create mode 100644 src/base/triggers/develop/add-video.md create mode 100644 src/base/triggers/develop/connect-store.md create mode 100644 src/base/triggers/develop/create-component.md create mode 100644 src/base/triggers/develop/create-entity.md create mode 100644 src/base/triggers/develop/create-feature.md create mode 100644 src/base/triggers/develop/create-hook.md create mode 100644 src/base/triggers/develop/create-store.md create mode 100644 src/base/triggers/develop/create-widget.md create mode 100644 src/base/triggers/develop/generate-module.md create mode 100644 src/base/triggers/develop/setup-vscode.md create mode 100644 src/base/triggers/develop/style-component.md create mode 100644 src/nextjs/DEVELOP.md create mode 100644 src/nextjs/REVIEW.md rename {docs/ru => src/nextjs}/applied/page-level.md (78%) rename {docs/ru => src/nextjs}/applied/project-structure.md (95%) create mode 100644 src/nextjs/triggers/develop/add-server-data.md create mode 100644 src/nextjs/triggers/develop/create-layout.md create mode 100644 src/nextjs/triggers/develop/create-page.md create mode 100644 src/nextjs/triggers/develop/create-project.md diff --git a/AGENTS.md b/AGENTS.md index cd32e81..05d4712 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,6 +3,11 @@ При работе с документацией следовать правилам из CONTRIBUTING.md. - Язык документации и коммитов — русский. -- После изменений в `.md`-файлах — запустить `npm run docs` для обновления RULES.md. -- При добавлении нового раздела — обновить сайдбар (`.vitepress/config.ts`) - и порядок файлов (`concat-md.js`). +- Исходники документации — в `src/`, только `.md` файлы. +- Скрипты и манифесты сборки — в `scripts/`. +- Общие правила — в `src/base/`. +- Фреймворк-специфичные — в `src/{framework}/`. +- Точки входа (`DEVELOP.md`, `REVIEW.md`) — в `src/{framework}/`. +- После изменений в `.md`-файлах — запустить `npm run build:ai` для пересборки `dist/ai/`. +- При добавлении нового раздела — добавить файл в `src/` и путь в манифест `scripts/{fw}.build.js`. +- Frontmatter каждого `.md`-файла содержит поля `title`, `scope`, `keywords`, `when`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 136381d..975e100 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,201 +1,129 @@ -# Правила работы над документацией +# Правила написания документации -Мета-документ: как устроен проект, как писать и редактировать разделы. +Как писать и редактировать разделы стайлгайда. -## О проекте +## Типы разделов -Документационный сайт с правилами и стандартами фронтенд-разработки на Next.js + TypeScript. - -- Движок: VitePress -- Языки: русский (основной), английский -- Русская версия: `docs/ru/` -- Английская версия: `docs/en/` - -## Команды - -| Команда | Что делает | -|---------|-----------| -| `npm run dev` | Локальный сервер разработки | -| `npm run build` | Сборка статического сайта | -| `npm run docs` | Генерация `generated/{lang}/RULES.md` — единый файл для AI-ассистентов | - -## Структура файлов - -``` -docs/ -├── ru/ # Русская версия (основная) -│ ├── index.md # Главная страница -│ ├── basics/ # Базовые правила -│ │ ├── tech-stack.md -│ │ ├── architecture.md -│ │ ├── code-style.md -│ │ ├── naming.md -│ │ ├── documentation.md -│ │ └── typing.md -│ └── applied/ # Прикладные разделы -│ ├── vscode.md -│ ├── project-structure.md -│ ├── components.md -│ ├── page-level.md -│ ├── templates-generation.md -│ ├── styles.md -│ ├── images-sprites.md -│ ├── svg-sprites.md -│ ├── video.md -│ ├── api.md -│ ├── stores.md -│ ├── hooks.md -│ ├── fonts.md -│ └── localization.md -├── en/ # Английская версия (зеркало ru/) -.vitepress/ -├── config.ts # Конфигурация VitePress, сайдбары, локали -generated/ -├── ru/RULES.md # Сгенерированный единый файл (ru) -└── en/RULES.md # Сгенерированный единый файл (en) -concat-md.js # Скрипт генерации RULES.md -``` - -### Добавление нового раздела - -1. Создать `.md`-файл в нужной папке (`basics/` или `applied/`). -2. Добавить пункт в сайдбар — `.vitepress/config.ts` (оба языка, если есть перевод). -3. Добавить файл в массив `fileOrder` — `concat-md.js` (для генерации RULES.md). - -## Два типа документации - -### Базовые правила +### Базовые правила (`basics/`) **Отвечает на вопрос:** «Каким должен быть любой код?» -Универсальные стандарты, **не привязанные к конкретной области**. -Правило базовое, если оно применимо ко всему коду одинаково: именование переменных, оформление импортов, когда использовать `type` vs `interface`. +Универсальные стандарты, не привязанные к конкретной области. +Правило базовое, если оно применимо ко всему коду одинаково. -Примеры в базовых правилах допускаются, но служат иллюстрацией принципа, а не инструкцией по конкретной области. +**Граница:** если правило касается только одной области — оно прикладное. -**Граница:** если правило касается только одной области (только стили, только компоненты, только API) — оно живёт в прикладном разделе, не в базовых. - -### Прикладные разделы +### Прикладные разделы (`applied/`) **Отвечает на вопрос:** «Как работать с X?» Полное описание конкретной области: структура файлов, правила, именование, типизация, примеры. -**Граница:** прикладной раздел не дублирует базовые правила. -Если правило уже описано в базовых — прикладной раздел ссылается на него, но не повторяет. +**Граница:** не дублирует базовые правила. Если правило уже описано в базовых — ссылается, но не повторяет. -## Структура прикладного раздела +### Триггеры (`triggers/`) -Шаблон ниже описывает все допустимые секции. Раздел включает только те секции, которые для него релевантны — пустые секции не создаются. +**Отвечает на вопрос:** «Как выполнить задачу X?» -```markdown -# {Название} +Конкретная инструкция: какие разделы прочитать, какие шаги выполнить. Триггер ссылается на basics/ и applied/, но не дублирует их. Группируются по роли: `triggers/develop/`, `triggers/review/`, `triggers/architect/`. -Краткое описание: о чём раздел и какие аспекты работы с областью он охватывает. +Структура триггера: -## Что нужно знать +- **Заголовок** — глагол + объект ("Создать компонент", "Добавить иконку") +- **Описание** — одно предложение: что делает триггер +- **Прочитай перед началом** — ссылки на basics/ и applied/ +- **Шаги** — нумерованный список действий со ссылками +- **Смежные триггеры** — ссылки на связанные задачи +- **Проверь себя** — чеклист из 2-5 пунктов для самопроверки -Неочевидная информация, которую читатель должен знать перед чтением раздела. -Если для раздела нет такой вводной — секция не создаётся. +### Фреймворк-специфичные (`{framework}/`) -## Структура +Разделы и триггеры, которые применимы только к конкретному фреймворку. Те же категории — `applied/` и `triggers/`. -Файловая организация: какие файлы создавать и куда класть. -Обязательно — дерево файлов через code-block. +**Граница:** если правило одинаково для всех фреймворков — оно в `base/`. -## Правила - -Конкретные требования, специфичные для области. Делятся на две подсекции: - -### Реализация - -Как написан код внутри файла: синтаксис, паттерны, API. -Отвечает на вопрос: «Как писать код?» - -Примеры: объявление через `const`, деструктуризация пропсов, формат вызова `cl()`, способ подключения стилей, структура хука. - -### Организация - -Как компонент/модуль встроен в проект: файловые границы, зоны ответственности, экспорт. -Отвечает на вопрос: «Где что лежит и за что отвечает?» - -Примеры: один компонент — один файл, вложенные компоненты в `ui/`, логика выносится в `model/`. - -Формат обеих подсекций — маркированный список. -Для неочевидных случаев — блоки «Хорошо / Плохо». -Если в области нет правил одной из категорий — подсекция не создаётся. - -## Именование - -Соглашения по именам, специфичные для этой области. -Только то, что НЕ покрыто в базовом разделе «Именование». - -## Типизация - -Правила типизации, специфичные для этой области. -Только то, что НЕ покрыто в базовом разделе «Типизация». - -## Документирование - -Что и как документировать в этой области. -Только то, что НЕ покрыто в базовом разделе «Документирование». - -## Примеры - -Полноценные примеры кода. -Каждый пример с путём к файлу и пояснениями. - -``` - -### Порядок секций - -Порядок фиксированный: контекст → структура → правила → специализации базовых правил → примеры. - -Логика: читатель сначала понимает «что это», потом «где это лежит», потом «как это делать», и в конце видит полный пример. - -### Секции-расширения базовых правил - -«Именование», «Типизация», «Документирование» в прикладном разделе — это **точки расширения** базовых правил. - -- В базовых описано общее: `camelCase` для переменных, `type` vs `interface`, формат JSDoc. -- В прикладном разделе описано специфичное: как именовать CSS-классы (стили), как типизировать пропсы компонентов (компоненты), как документировать хуки (хуки). - -Если для области нет специфики по именованию, типизации или документированию — секция не создаётся. - -## Конвенции оформления - -### Frontmatter +## Frontmatter Каждый `.md`-файл начинается с YAML frontmatter: ```yaml --- title: Название раздела +scope: basics | applied | triggers +keywords: [ключевое слово 1, ключевое слово 2] +when: "Когда агенту читать этот раздел" --- ``` -Значение `title` совпадает с текстом `h1`-заголовка в файле. +| Поле | Описание | +|------|----------| +| `title` | Название раздела. Совпадает с `h1` в файле | +| `scope` | Тип: `basics`, `applied` или `triggers` | +| `keywords` | Ключевые слова для поиска агентом | +| `when` | Описание ситуации, когда раздел релевантен | + +## Структура прикладного раздела + +Раздел включает только релевантные секции — пустые не создаются. + +```markdown +# {Название} + +Краткое описание: о чём раздел. + +## Что нужно знать + +Неочевидная вводная информация (если есть). + +## Структура + +Файловая организация. Обязательно — дерево файлов. + +## Правила + +### Реализация + +Как писать код: синтаксис, паттерны, API. + +### Организация + +Где что лежит: файловые границы, зоны ответственности, экспорт. + +## Именование + +Специфичные для области соглашения (не покрытые в basics/naming). + +## Типизация + +Специфичные для области правила (не покрытые в basics/typing). + +## Документирование + +Специфичные для области правила (не покрытые в basics/documentation). + +## Примеры + +Полноценные примеры кода с путями к файлам. +``` + +Порядок фиксированный: контекст -> структура -> правила -> специализации базовых -> примеры. + +## Конвенции оформления ### Заголовки - Один `h1` на файл — совпадает с `title` из frontmatter. -- Сразу после `h1` — вводный абзац (одно-два предложения). -- Основные секции — `h2`. -- Подсекции внутри `h2` — `h3`. -- `h4` не используется. +- Сразу после `h1` — вводный абзац. +- Основные секции — `h2`. Подсекции — `h3`. `h4` не используется. ### Примеры кода - Блоки кода с указанием языка: ` ```tsx `, ` ```css `, ` ```bash `, ` ```text `. -- Путь к файлу указывается перед блоком кода текстом или комментарием внутри блока. +- Путь к файлу — перед блоком кода или комментарием внутри. - Дерево файлов — ` ```text ` с символами `├──`, `└──`, `│`. ### Блоки «Хорошо / Плохо» -Используются для контрастного сравнения правильного и неправильного подхода. - -Формат: - ```markdown **Хорошо:** @@ -212,16 +140,16 @@ title: Название раздела ### Таблицы -Используются для структурированных перечислений: настройки, команды, соответствия. Формат — стандартный Markdown: `| Ключ | Описание |`. ### Ссылки между разделами -Прикладной раздел может ссылаться на другие разделы, но не дублирует их содержимое. +Ссылаться можно, дублировать содержимое — нет. ## Принципы -1. **Не дублировать.** Одна мысль живёт в одном месте. Остальные ссылаются. -2. **Базовое vs прикладное.** Если правило применимо ко всему коду — оно базовое. Если только к одной области — прикладное. -3. **Пустые секции не создавать.** Если для раздела нет специфики по именованию — секции «Именование» в нём нет. -4. **Примеры обязательны.** Прикладной раздел без примеров кода — незавершён. +1. **Не дублировать.** Одна мысль — одно место. Остальные ссылаются. +2. **Базовое vs прикладное.** Применимо ко всему коду — базовое. К одной области — прикладное. +3. **Общее vs специфичное.** Одинаково для всех фреймворков — в `base/`. Для одного — в `{framework}/`. +4. **Пустые секции не создавать.** +5. **Примеры обязательны.** Прикладной раздел без примеров — незавершён. diff --git a/OLD_parts/1-assistent.md b/OLD_parts/1-assistent.md deleted file mode 100644 index 33a8f3f..0000000 --- a/OLD_parts/1-assistent.md +++ /dev/null @@ -1,19 +0,0 @@ -# Ассистент - -## Для ассистента - -- Всегда используй Русский язык для общения и генерации документации/комментариев/коммитов. -- Всегда следуй этим правилам при генерации кода и ответах. -- Всегда пиши план действий перед генерацией кода. -- Всегда спрашивай разрешения у пользователя перед генерацией кода. -- Всегда проверяй, что код соответствует линтингу и форматированию. -- Всегда сверяйся с чек-листом при генерации кода. -- Не предлагай решения, которые противоречат этим правилам этого файла. -- Если не уверен — уточни у пользователя, не гадай, не придумывай. - -## Обязательность чек-листов - -- Все чек-листы, приведённые в правилах, обязательны к исполнению. -- Ассистент обязан сверяться с чек-листом при выполнении любой задачи, связанной с кодом. -- Нельзя сокращать, игнорировать или опускать пункты чек-листа — каждый пункт должен быть выполнен или явно отмечен как невыполнимый с объяснением причины. -- В каждом ответе, связанном с генерацией или изменением кода, ассистент обязан ссылаться на соответствующий чек-лист и подтверждать его выполнение. diff --git a/OLD_parts/10-stores.md b/OLD_parts/10-stores.md deleted file mode 100644 index 04d8ce6..0000000 --- a/OLD_parts/10-stores.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Stores ---- - -# Stores - -## Сторы (Stores) - -> В этом разделе собраны основные правила и рекомендации по созданию и оформлению сторов. Следуйте этим принципам, чтобы обеспечить чистую архитектуру, удобство поддержки и единый стиль работы с состоянием в проекте. -> В проекте для организации состояния используется только библиотека Zustand. - -### Структура -- Store размещается в файле `.store.ts` в папке `stores/` на своём уровне абстракции согласно архитектуре проекта. -- Интерфейс состояния описывается в этом же файле с суффиксом `State` (PascalCase). -- Для каждого store создаётся отдельный хук доступа (например, `useTodoStore`). -- Для глобальных сторов используйте только `shared/store`. - -### Именование -- Соблюдайте [правила именования файлов и папок](#правила-именования-файлов-и-папок): -- Файл store — `.store.ts` (kebab-case). -- Имя интерфейса состояния — PascalCase с суффиксом `State`. -- Имя хука — camelCase с префиксом `use`. - -### Требования -- В store допускается только хранение состояния и методы управления им, без бизнес-логики, асинхронных операций и side-effects (см. раздел "Правила организации и использовалья Store"). -- Для методов, изменяющих состояние через set, если используется функция — тело функции в фигурных скобках, return с новой строки после стрелки. -- Не дублируйте логику между сторами. - -### Типизация -- Всегда указывайте типы для всех полей состояния и методов. -- Не используйте неявное приведение типов и не полагайтесь на автоматический вывод, если это может снизить читаемость или безопасность. - -### Документирование -- Документируйте только назначение store и смысл полей, строго по [правилам документирования кода](#правило-для-документирования-кода). - -### Экспорт -- Экспортируйте хук доступа к store и интерфейс состояния через `index.ts` слоя/компонента. - -### Примеры - -```ts -import { create } from 'zustand'; -import { TodoItem } from './types/todo-item.interface'; - -/** - * Состояние хранилища задач. - */ -export interface TodoStoreState { - /** Массив задач. */ - items: TodoItem[]; - /** Добавить задачу. */ - addTodo: (item: TodoItem) => void; - /** Удалить задачу. */ - removeTodo: (id: string) => void; -} - -/** - * Хук для доступа к хранилищу задач. - */ -export const useTodoStore = create((set) => ({ - items: [], - addTodo: (item) => set((state) => { - return { - items: [...state.items, item], - }; - }), - removeTodo: (id) => set((state) => { - return { - items: state.items.filter((t) => t.id !== id), - }; - }), -})); -``` - -### Чек-лист - -- [ ] Store размещён в `stores/.store.ts` на своём уровне абстракции согласно архитектуре проекта. -- [ ] Именование файлов и сущностей соответствует [правилам именования файлов и папок](#правила-именования-файлов-и-папок). -- [ ] Все поля и методы строго типизированы (см. [общие правила типизации](#общие-правила-типизации)). -- [ ] В store только состояние и методы управления им, без бизнес-логики и side-effects. -- [ ] Для методов, изменяющих состояние через set, используется функция с return с новой строки. -- [ ] Документировано только назначение store и смысл полей (см. [правила документирования кода](#правило-для-документирования-кода)). -- [ ] Нет неиспользуемого или невалидного кода. -- [ ] Экспорт через индексный файл. diff --git a/OLD_parts/11-css.md b/OLD_parts/11-css.md deleted file mode 100644 index d736f27..0000000 --- a/OLD_parts/11-css.md +++ /dev/null @@ -1,227 +0,0 @@ ---- -title: CSS ---- - -# CSS - -## Правила оформления и стилизации CSS-кода - -- **Препроцессоры** - Используй PostCSS и модули для стилизации. - -- **Архитектура написания стилей** - Используй подход **Mobile First** - Используй CSS переменные для стилизации. - Используй Custom Media Queries для адаптивных стилей. - Используй BEM для именования классов. - Между каждым CSS-правилом (селектором) должен быть один пустой сброс строки, пример: - ```css - .todo-list { - max-width: 600px; - padding: var(--space-3); - - @media (--md) { - max-width: 800px; - } - } - - .todo-list__text { - font-size: 18px; - - @media (--md) { - font-size: 22px; - } - } - ``` - Запрещено писать правила подряд без пустой строки: - ```css - /* Так делать нельзя! */ - .todo-list { ... } - .todo-list__text { ... } - ``` - -- **Методология именования классов** - Использовать методологию **BEM** для именования классов. - - Блок: kebab-case, пример `.user-bar { }` - - Елемент: kebab-case, соеденный с блоком двойным нижним подчеркиванием, пример `.user-bar__slide { }` - - Модификатор: kebab-case, отдельный самостоятельный класс, **не соединяется** с блоком/елементом, имя модификатора всегда начинается с нижнего подчеркивания, пример: `._red { }` - -- **Единицы измерения** - Используй `px` как основная единица измирения, так-же допускается использовать остальные единицы измерения если того требует реализуемый дизайн. - -- **Импорт стилей** - Стили компонента должны импортироваться только внутри соответствующего компонента. - Запрещено импортировать стили одного компонента в другой. - Запрещено импортировать `css переменные` в файлы стилей, они доступны глобально. - Запрещено импортировать `custom media` в файлы стилей, они доступны глобально. - -- **Переменные** - Все значения переменных нужно писать в `/shared/styles` или в Mantine ThemeProvider. - Все что не является цветами, брекпоинтами, отступами, скруглением допускаются использоваться в компонентах. - Обязательное создавай CSS перменные для: - - "Цветов", пример: `--color-danger: red;`. - - "Брекпоинты", описываем в (Сustom media) пример: `@custom-media --md (min-width: 62em);`. - - "Отспупы (--space)", , пример: `--space-1: 4px;`, `--space-2: 8px;`, `--space-3: 12px;` итд.. - - "Скругление углов (--radius)", пример: `--radius-1: 4px;`,`--radius-2: 8px;`,`--radius-3: 12px;` итд.. - -- **Вложенность селекторов** - Запрещено использовать вложенность селекторов. - Разрешено использовать вложенность только для: - - Псевдо-классов `:hover`, `:active` итд.. - - Псевдо-елементов `::before`, `::after` - - Медиа запросов `@media` - - Классы **модификаторы** по методологии BEM - Каждый вложенный селектор отделяется 1 пустой строкой. - -- **Медиа запросы** - Строго запрещено использовать `@media` без вложения в селектор. - Строго запрещено использовать в теле `@media` любые селекторы. - Разрешено использовать только Custom Media Queries (например, `@media (--md) {}`). - Запрещено использовать любые произвольные значения breakpoints (например, max-width: 768px). - **Пример как правильно писать @media** - ```css - .todo-list { - max-width: 600px; - padding: 24px; - - @media (--md) { - max-width: 800px; - } - } - - .todo-list__text { - font-size: 18px; - - @media (--md) { - font-size: 22px; - } - } - - ``` - **Пример как неправильно писать @media** - ```css - // Медиа запрос не вложен в селектор - @media (--md) { - .todo-list { - max-width: 600px; - padding: 24px; - } - .todo-list__text { - font-size: 18px; - } - } - // Используется стандартный `min-width: 992px` вмето Custom Media Queries - @media (min-width: 992px) { - // Внутри @media запроса используются селекторы - .todo-list { - max-width: 600px; - padding: 24px; - } - .todo-list__text { - font-size: 18px; - } - } - ``` - -- **Глобальные стили и сбросы** - Все глобальные стили (например, сбросы) должны располагаться в отдельном файле, например, `src/app/styles/global.css`. - -- **Использование Mantine и PostCSS** - Для стандартных визуальных компонентов (кнопки, инпуты, layout, grid, notifications и т.д.) использовать только Mantine и его ThemeProvider. - Запрещено использовать в Mantine компонентах его props/styling, вмето этого нужно добавлять кастомные стили PostCSS. - Кастомные стили допускаются только в случае, если требуемый дизайн невозможно реализовать средствами Mantine. - При написании кастомных стилей стараться использовать переменные и токены Mantine, если это возможно. - -- **Порядок CSS-свойств** - В стилях рекомендуется придерживаться логического порядка свойств: - 1. Позиционирование (position, top, left, z-index и т.д.) - 2. Блочная модель (display, width, height, margin, padding и т.д.) - 3. Оформление (background, border, box-shadow и т.д.) - 4. Текст (font, color, text-align и т.д.) - 5. Прочее (transition, animation и т.д.) - -- **Комментарии** - В стилях запрещено использовать комментарии. - -- **Дублирования** - Не дублировать стили между компонентами. Общие стили выносить в shared/styles или использовать переменные. - -- **Примеры кода стилей** - Пример как хорошо: - ```css - /* Блок BEM */ - .user-bar { - display: none; - color: black; - - /* Медиа запрос custom media и отделяется 1 пустой строкой */ - @media (--md) { - display: flex; - } - } - - /* Елемент BEM отделяется 1 пустой строкой*/ - .user-bar__button-next { - background-color: #f0f0f0; - - /* Псевдо-класс отделяется 1 пустой строкой*/ - &:hover { - background-color: #e0e0e0; - } - - /* Модификатор BEM отделяется 1 пустой строкой*/ - &._blue { - background-color: #2b2bbe; - } - - /* Модификатор BEM отделяется 1 пустой строкой*/ - &._green { - background-color: #29c53d; - } - } - ``` - Пример как плохо писать: - ```css - .user-bar { - display: none; - color: black; - &__button { - &_next { - background-color: #f0f0f0; - &:hover { - background-color: #e0e0e0; - } - &._blue { - background-color: #2b2bbe; - } - &._green { - background-color: #29c53d; - } - } - } - } - @media (min-width: 992px) { - .user-bar { - display: flex; - } - } - ``` - -**Чек лист для проверки стилизации.** -- [ ] Используется PostCSS и CSS-модули для стилизации. -- [ ] Применён подход Mobile First. -- [ ] Именование классов строго по BEM: - - [ ] Модификатор — отдельный класс, начинается с нижнего подчёркивания (например, `._red`, `._active`) -- [ ] Все CSS-переменные (цвета, брейкпоинты, отступы, скругления) определены только в `/shared/styles` или через Mantine ThemeProvider. -- [ ] Для медиа-запросов используются только custom media переменные из `/shared/styles/media.css`. -- [ ] Соблюдается правила вложености селекторов. -- [ ] Соблюдается правила отступов селекторов. -- [ ] Глобальные стили (reset) вынесены в отдельный файл, остальные стили — модульные. -- [ ] Для стандартных UI-элементов используются только компоненты Mantine, кастомные стили — только при необходимости. -- [ ] В Mantine-компонентах не используются props/styling для стилизации, только PostCSS. -- [ ] Кастомные стили используют переменные и токены Mantine, если это возможно. -- [ ] В стилях нет комментариев. -- [ ] Стили компонента импортируются только внутри соответствующего компонента. -- [ ] Нет импорта стилей одного компонента в другой. -- [ ] Нет импорта файлов переменных и custom media — они доступны глобально. -- [ ] Нет дублирования стилей между компонентами, общие стили вынесены в shared/styles или используются переменные. diff --git a/OLD_parts/12-components.md b/OLD_parts/12-components.md deleted file mode 100644 index 37786ce..0000000 --- a/OLD_parts/12-components.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Компоненты ---- - -# Компоненты - -## Правила создания и работы с компонентами. - -### 1. Структура компонента -Ассистент при создании/рефакторинге компонента должен **строго** придерживаться следующей структуры файлов и папок: - -``` -component-name/ - index.ts - component-name.tsx - styles/ - component-name.module.css - locales/ - ru.json - en.json - types/ - component-name.interface.ts - component-name.type.ts - component-name.enum.ts - schemas/ - schema-name.schema.ts - utils/ - util-name.util.ts - hooks/ - use-hook-name.hook.ts - stores/ - store-name.store.ts - ui/ - ... # вложенные компоненты для component-name -``` - -Пояснения к структуре компонента: -**Обязательные файлы** обязательны для всех компонентов, даже если они пустые. - - component-name/: Папка компонента корень для всего компонента. - - index.ts: экспортирует главный компонент, интерфейс и всё, что может быть переиспользовано. - - component-name.tsx: главный компонент. - - styles/component-name.module.css: стили компонента. - - locales/ru.json: локализация на русском языке. - - locales/en.json: локализация на английском языке. - - types/component-name.interface.ts: интерфейс пропсов компонента. -**Не обязательные файлы** добавляются только при необходимости - - types/component-name.type.ts: типы компонента. - - types/component-name.enum.ts: enum компонента. - - schemas/schema-name.schema.ts: схемы валидации. - - utils/util-name.util.ts: утилиты компонента. - - hooks/use-hook-name.hook.ts: хуки компонента. - - stores/store-name.store.ts: хранилища состояния компонента. - - ui/: Папка для вложенных компонентов. - -### Требования к компоненту -- Использовать `memo()` для всех компонентов, которые принимают пропсы. -- Использовать `useMemo` для всех вычислений, которые передаются в пропсы других компонентов. -- Использовать `useCallback` для всех функций/методов, которые передаются в пропсы других компонентов. - -### Требования к вложенным компонентам -- Вложенный компонент — это полноценный компонент, который обязан полностью соблюдать все правила, описанные для компонентов (структура, именование, документация, типизация, стилизация и т.д.). -- Все вложенные компоненты размещаются только в папке ui/ основного компонента. - -**Пояснение** -Нет необходимости повторять структуру и требования — вложенный компонент подчиняется тем же правилам, что и любой другой компонент, только располагается в папке ui/ родительского компонента. - -### Требования к локализации -- Все добавленные локализации обязательно подключать в экземпляр `app/i18n` (чтобы новые namespace были доступны для i18next). - ---- - -### Чек-лист для создания нового компонента -- [ ] Главный компонент размещён в корне и назван по правилу PascalCase. -- [ ] Создан файл стилей в папке `styles/`, имя в kebab-case, используется BEM. -- [ ] Все классы применяются через `className={styles['component-name']}`. -- [ ] Создана папка `locales/` с файлами `ru.json` и `en.json`. -- [ ] Создан файл интерфейса пропсов в папке `types/`, даже если интерфейс пустой. -- [ ] Создан файл `index.ts` с экспортом главного компонента и интерфейса. -- [ ] Внутренние компоненты (если есть) размещены в папке `ui/`. -- [ ] Все важные части кода документированы по TSDoc (см. раздел 16). -- [ ] Остальные файлы (schemas, дополнительные типы, enum) добавлены только при необходимости. -- [ ] Именование файлов и папок соответствует правилам (см. выше). -- [ ] Нет неиспользуемого или невалидного кода. -- [ ] Для компонентов с пропсами используется `React.memo`. -- [ ] Для вычислений, передаваемых в пропсы, используется `useMemo`. -- [ ] Для функций, передаваемых в пропсы, используется `useCallback`. -- [ ] Все тексты вынесены в локализационные файлы и используются через i18n. -- [ ] Новые namespace подключены в экземпляр i18n. diff --git a/OLD_parts/13-hooks.md b/OLD_parts/13-hooks.md deleted file mode 100644 index c0b1878..0000000 --- a/OLD_parts/13-hooks.md +++ /dev/null @@ -1,68 +0,0 @@ -# Хуки (React Hooks) - -> В проекте для создания пользовательских хуков используется только React (функциональные компоненты и хуки). -> В этом разделе собраны основные правила и рекомендации по созданию и оформлению хуков. Следуйте этим принципам, чтобы обеспечить чистую архитектуру, переиспользуемость и единый стиль работы с хуками в проекте. - -## Рекомендации по использованию сторонних хуков -- Если есть возможность, используйте хуки Mantine в компонентах и кастомных хуках для работы с состоянием, темизацией, медиа-запросами и другими возможностями библиотеки. -- Не дублируйте функциональность, уже реализованную в Mantine. - -## Структура -- Каждый хук размещается в отдельном файле с именем `use-.hook.ts` в папке `hooks/` на своём уровне абстракции согласно архитектуре проекта. -- Имя хука — в стиле camelCase с префиксом `use` (например, `useTodoFilter`). -- Для сложных возвращаемых структур использовать отдельные типы или интерфейсы, размещая их в папке `types/` на своём уровне абстракции. - -## Именование -- Соблюдайте [правила именования файлов и папок](#правила-именования-файлов-и-папок): - - Файл хука — `use-.hook.ts` (kebab-case). - - Имя хука — camelCase с префиксом `use`. - -## Требования -- Хук должен быть строго типизирован: все параметры, возвращаемые значения и внутренние переменные должны иметь явные типы. -- Не хранить бизнес-логику, связанную с несколькими слоями — хук должен быть изолирован в рамках своего слоя/feature. -- Не дублировать логику между хуками — общие части выносить в shared. -- Не использовать side-effects вне useEffect/useLayoutEffect. -- Для мемоизации возвращаемых значений и функций использовать useMemo и useCallback. -- Не использовать устаревшие или неразрешённые паттерны React. - -## Типизация -- Всегда явно указывать типы для всех параметров, возвращаемых значений и состояния внутри хука. -- Не используйте неявное приведение типов и не полагайтесь на автоматический вывод, если это может снизить читаемость или безопасность. - -## Документирование -- Документируйте только назначение хука (описание), строго по [правилам документирования кода](#правило-для-документирования-кода). - -## Экспорт -- Экспортируйте хук только именованным экспортом через `index.ts` слоя/компонента. - -## Примеры - -```ts -import { useMemo } from 'react'; -import { TodoItem } from '../types/todo-item.interface'; -import { TodoStatus } from '../types/todo-status.enum'; - -/** - * Хук фильтрации задач по статусу. - */ -export const useTodoFilter = (items: TodoItem[], filter: TodoStatus): TodoItem[] => { - return useMemo(() => { - if (filter === TodoStatus.ALL) return items; - if (filter === TodoStatus.ACTIVE) return items.filter((t) => !t.completed); - return items.filter((t) => t.completed); - }, [items, filter]); -}; -``` - -## Чек-лист - -- [ ] Хук размещён в файле `use-.hook.ts` в папке `hooks/` на своём уровне абстракции согласно архитектуре проекта. -- [ ] Именование файлов и сущностей соответствует [правилам именования файлов и папок](#правила-именования-файлов-и-папок). -- [ ] Все параметры, возвращаемые значения и внутренние переменные строго типизированы. -- [ ] Вся бизнес-логика изолирована в рамках слоя/feature. -- [ ] Нет дублирования логики между хуками. -- [ ] Для мемоизации используется useMemo/useCallback. -- [ ] Не используются side-effects вне useEffect/useLayoutEffect. -- [ ] Документировано только назначение хука (см. [правила документирования кода](#правило-для-документирования-кода)). -- [ ] Нет неиспользуемого или невалидного кода. -- [ ] Экспорт только именованный через индексный файл. diff --git a/OLD_parts/14-api-hooks.md b/OLD_parts/14-api-hooks.md deleted file mode 100644 index 93234e5..0000000 --- a/OLD_parts/14-api-hooks.md +++ /dev/null @@ -1,124 +0,0 @@ -# Хуки API (React Hooks) - -> В проекте для работы с API-хуками используется только React и библиотека SWR для получения данных (GET-запросы). -> В этом разделе собраны основные правила и рекомендации по созданию и оформлению хуков для работы с API. Следуйте этим принципам, чтобы обеспечить чистую архитектуру, переиспользуемость и единый стиль работы с API-хуками в проекте. - -## Описание и назначение API-хуков - -API-хуки предназначены для получения данных с сервера (GET-запросы) и используются в компонентах или других хуках. -В проекте для этого применяется библиотека SWR, которая обеспечивает кэширование, автоматическое обновление и удобную работу с асинхронными запросами. - -**Fetcher** — это функция, которую использует SWR для выполнения запроса к API. В проекте fetcher обычно экспортируется из файла клиента (например, `backendFetcher` из `shared/api/backend/client.ts`) и инкапсулирует логику обращения к конкретному API-клиенту. - -**API-клиент** — это отдельный модуль (папка), отвечающий за взаимодействие с конкретным внешним или внутренним API. -API-клиент включает: -- инициализацию экземпляра HTTP-клиента (например, Axios), -- настройку базового URL, интерцепторов и общих обработчиков ошибок, -- организацию всех сущностей и методов для работы с этим API (например, users, auth, orders и т.д.), -- экспорт всех функций, типов и fetcher через индексные файлы. - -Каждый API-клиент размещается в папке `src/shared/api//` и имеет собственную структуру согласно архитектуре проекта. - -## Структура -- Каждый API-хук размещается в отдельном файле с именем `use-.hook-api.ts` в папке `hooks/api//` на своём уровне абстракции согласно архитектуре проекта. -- Имя хука — в стиле camelCase с префиксом `use` (например, `useGetUser`). -- Для сложных возвращаемых структур используйте отдельные типы или интерфейсы, размещая их в папке `types/` на своём уровне абстракции. - -## Именование -- Соблюдайте [правила именования файлов и папок](#правила-именования-файлов-и-папок): - - Файл хука — `use-.hook-api.ts` (kebab-case). - - Имя хука — camelCase с префиксом `use`. - -## Требования -- Хук должен быть строго типизирован: все параметры, возвращаемые значения и внутренние переменные должны иметь явные типы. -- Для получения данных используйте только SWR. -- Не дублируйте логику между хуками — общие части выносите в shared. -- Не используйте side-effects вне useEffect/useLayoutEffect. - -## Типизация -- Всегда явно указывайте типы для всех параметров, возвращаемых значений и состояния внутри хука. -- Придерживайтесь [общих правил типизации проекта](#общие-правила-типизации). -- Не используйте неявное приведение типов и не полагайтесь на автоматический вывод, если это может снизить читаемость или безопасность. - -## Документирование -- Документируйте только назначение хука (описание), строго по [правилам документирования кода](#правило-для-документирования-кода). - -## Экспорт -- Экспортируйте хук только именованным экспортом через `index.ts` слоя/компонента. - -## Пример API хука - -```ts -// use-get-me.hook-api.ts -import useSWR from 'swr'; -import { backendFetcher } from 'shared/api/backend/client'; -import { UserDto } from 'shared/api/backend/entities/users/get-me.api'; - -/** - * Хук для получения информации о текущем пользователе. - */ -export const useGetMe = () => { - const { data, error, isLoading } = useSWR('/users/me', backendFetcher); - - return { - data, - error, - isLoading, - }; -}; -``` - -### Пример использования хука в компоненте - -```tsx -import React from 'react'; -import { useGetMe } from 'shared/hooks/api/backend/use-get-me.hook-api'; - -export const UserInfo: React.FC = () => { - const { data, error, isLoading } = useGetMe(); - - if (isLoading) { - return
Загрузка...
; - } - - if (error) { - return
Ошибка загрузки данных
; - } - - if (!data) { - return
Нет данных о пользователе
; - } - - return ( -
-
Имя: {data.name}
-
Email: {data.email}
-
- ); -}; -``` - -## Чек-лист для создания API-хука - -- [ ] Для каждого GET-запроса создан отдельный хук. -- [ ] Хук размещён в `hooks/api//use-.hook-api.ts` на своём уровне абстракции согласно архитектуре проекта. -- [ ] Именование файлов и сущностей соответствует [правилам именования файлов и папок](#правила-именования-файлов-и-папок). -- [ ] Используется SWR для получения данных. -- [ ] Все параметры, возвращаемые значения и внутренние переменные строго типизированы. -- [ ] Нет дублирования логики между хуками. -- [ ] Не используются side-effects вне useEffect/useLayoutEffect. -- [ ] Документировано только назначение хука (см. [правила документирования кода](#правило-для-документирования-кода)). -- [ ] Нет неиспользуемого или невалидного кода. -- [ ] Экспорт только именованный через индексный файл. - ---- - -## Чек-лист для использования API-хука - -- [ ] Импортируется только нужный хук через публичные экспорты (`index.ts`). -- [ ] Использование хука строго по назначению (только для получения данных). -- [ ] Если требуется получить данные через GET-запрос в компоненте — обязательно используется соответствующий API-хук. - **Запрещено вызывать GET-методы API напрямую в компонентах, только через хуки.** -- [ ] Обработка состояний загрузки, ошибки и данных реализована корректно. -- [ ] Не происходит дублирования логики, связанной с получением данных. -- [ ] Нет неиспользуемого или невалидного кода. diff --git a/OLD_parts/15-api.md b/OLD_parts/15-api.md deleted file mode 100644 index 17d2cb6..0000000 --- a/OLD_parts/15-api.md +++ /dev/null @@ -1,242 +0,0 @@ -# API - -> В этом разделе собраны основные правила и рекомендации по созданию, оформлению и использованию API-клиентов и функций для работы с сервером. Следуйте этим принципам, чтобы обеспечить единый стиль, безопасность и удобство поддержки API-слоя в проекте. - -## Описание и назначение API-клиента - -API-клиент — это модуль (папка), отвечающий за взаимодействие с конкретным внешним или внутренним API. -В проекте для HTTP-запросов используется только Axios. -API-клиент инкапсулирует: -- инициализацию экземпляра Axios, -- настройку базового URL, интерцепторов, обработчиков ошибок, -- организацию всех сущностей и методов для работы с этим API (например, users, auth, orders и т.д.), -- экспорт всех функций, типов и fetcher через индексные файлы. - -Каждый API-клиент размещается в папке `src/shared/api//` и имеет собственную структуру согласно архитектуре проекта. - - -## Использование методов API - -- Все методы API должны использоваться строго внутри блока `try...catch`. -- При вызове методов API всегда используйте полный путь, например: - `await api.backend.createUser({ email, password });` -- Запрещено вызывать методы API вне блока `try...catch` даже в тестах, утилитах и других вспомогательных функциях. - - -## Структура клиента -```text -src/shared/api/backend/ -│ -├── client.ts -├── index.ts -└── entities/ - ├── users/ - │ ├── get-me.api.ts - │ ├── create-user.api.ts - │ ├── update-user.api.ts - │ └── index.ts - ├── auth/ - │ ├── login.api.ts - │ ├── register.api.ts - │ └── index.ts - └── index.ts -``` - -## Описание ключевых элементов - -- **client.ts** - Экземпляр Axios с настройками, интерцепторами, экспортом fetcher для SWR. - -- **index.ts** - Главная точка экспорта: экспортирует client, fetcher, все сущности и их методы. - -- **entities/** - Папка для бизнес-сущностей (например, users, auth, orders и т.д.). - -- **`/`** - Папка для отдельной сущности. Имя — в kebab-case, отражает бизнес-область (например, users, auth). - -- **`.api.ts`** - Файл для каждой операции (CRUD, спец. действия). - Внутри: - - DTO (интерфейсы запроса/ответа) - - Функция, реализующая запрос через client - -- **index.ts (внутри ``/)** - Экспортирует все методы и типы этой сущности. - -- **index.ts (внутри entities/)** - Экспортирует все сущности (users, auth и т.д.). - - -## Именование - -- Соблюдайте [правила именования файлов и папок](#правила-именования-файлов-и-папок): - - Файл клиента — `client.ts`. - - Файл функции — `-.api.ts` (например, `create-user.api.ts`). - - DTO — в папке `dto/` (например, `create-user.dto.ts`). - - Все функции и типы экспортируются через индексные файлы на каждом уровне (сущность, entities, клиент). - - -## Требования - -- Для каждого действия (CRUD, спец. действия) — отдельная функция и файл. -- Все функции используют общий экземпляр Axios из `client.ts`. -- Все функции строго типизированы (используются DTO). -- DTO объявляется в отдельном файле в папке `dto/` перед функцией, которая его использует. -- Для каждого GET метода обязательно должен быть создан API-хук. -- Все API-хуки должны создаваться строго по [документации раздела "Хуки для API"](#хуки-для-api-api-hooks). - - -## Типизация - -- Все функции и DTO строго типизированы. -- Все интерфейсы, типы и enum размещены в папке `types/` на своём уровне абстракции. -- Все DTO размещены в папке `dto/` на своём уровне абстракции. -- Придерживайтесь [общих правил типизации проекта](#общие-правила-типизации). - - -## Документирование - -- Документируйте только назначение функций и DTO. -- В описании указывается только смысл функции/типа. - - -## Экспорт - -- Все функции и типы экспортируются через индексные файлы на каждом уровне (сущность, entities, клиент). - - -## Примеры - -### Пример клиента API - -```ts -// client.ts -import axios, { AxiosInstance } from "axios"; -export { AxiosError, isAxiosError } from 'axios'; -export type { AxiosResponse } from 'axios'; - -/** - * Экземпляр HTTP-клиента для работы с backend API. - */ -export const backendHttpClient: AxiosInstance = axios.create({ - baseURL: '/api', - timeout: 10000, -}); - -// Интерцептор запроса -backendHttpClient.interceptors.request.use( - (config) => { - // Здесь можно добавить авторизационные заголовки или другую логику - return config; - }, - (error) => Promise.reject(error) -); - -// Интерцептор ответа -backendHttpClient.interceptors.response.use( - (response) => response, - (error) => { - // Здесь можно обработать ошибки (например, показать уведомление) - return Promise.reject(error); - } -); -``` - -### Пример DTO - -```ts -// dto/create-user.dto.ts -/** - * DTO для создания пользователя. - */ -export interface CreateUserDto { - /** Email пользователя. */ - email: string; - /** Пароль пользователя. */ - password: string; -} -``` - -### Пример API-функции - -```ts -// create-user.api.ts -import { backendHttpClient } from '../client'; -import { CreateUserDto } from './dto/create-user.dto'; - -/** - * Создать пользователя. - */ -export const createUser = (data: CreateUserDto) => backendHttpClient.post('/users', data); -``` - -### Пример index.ts (в папке сущности) - -```ts -export * from './create-user.api'; -export * from './get-user.api'; -``` - -### Пример использования API-функции в компоненте - -```tsx -import React, { useState } from 'react'; -import { api } from 'shared/api'; - -export const CreateUserForm: React.FC = () => { - const [email, setEmail] = useState(''); - const [password, setPassword] = useState(''); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - try { - await api.backend.createUser({ email, password }); - console.log('Пользователь создан!'); - } catch { - console.log('Ошибка создания пользователя'); - } - }; - - return ( -
- setEmail(e.target.value)} - placeholder="Email" - required - /> - setPassword(e.target.value)} - placeholder="Пароль" - required - /> - -
- ); -}; -``` - - -## Чек-лист для создания клиента -- [ ] Новый клиент размещён в `src/shared/api//`. -- [ ] В корне клиента есть client.ts (экземпляр Axios) и index.ts (главный экспорт). -- [ ] Все бизнес-сущности размещены в entities/, каждая — в отдельной папке. -- [ ] Для каждой операции создан отдельный файл ``.api.ts с DTO и функцией. -- [ ] DTO объявлен непосредственно перед функцией. -- [ ] В каждой папке сущности есть свой index.ts для экспорта методов и типов. -- [ ] В папке entities/ есть общий index.ts для экспорта всех сущностей. -- [ ] Все экспорты организованы через индексные файлы. -- [ ] Для каждого GET-метода создан отдельный SWR-хук (см. правила API-хуков). -- [ ] Нет дублирования кода и неиспользуемых файлов. - -## Чек-лист для использования API -- [ ] Импортируется только нужный метод через публичные экспорты (index.ts). -- [ ] Все вызовы API обёрнуты в try...catch. -- [ ] Используются только строго типизированные методы. -- [ ] Не происходит обращения к Axios напрямую — только через client. -- [ ] Нет дублирования логики и неиспользуемого кода. diff --git a/OLD_parts/3-general-principles.md b/OLD_parts/3-general-principles.md deleted file mode 100644 index 94ce72b..0000000 --- a/OLD_parts/3-general-principles.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Общие принципы ---- - -# Общие принципы - -## Стек технологий и библиотеки -- Использовать **TypeScript** для всех файлов логики и компонентов. -- Использовать **FSD (Feature-Sliced Design)**: разделять код на features, entities, processes, widgets, shared. -- Использовать **React** (функциональные компоненты, хуки). -- Использовать **Mantine UI** для UI-компонентов. -- Использовать **Axios** в качестве клиента для работы с API. -- Использовать **SWR** для data fetching (GET-запросы). -- Использовать **Zustand** для глобального состояния. -- Использовать **i18n** для локализации. -- Использовать **Vitest** для тестирования. -- Использовать **PostCSS модули** для стилизации. -- Использовать **BEM** для именований классов в стилях -- Использовать **Mobile First** подход для написания стилей. -- Использовать **Context7** примеров использования библиотек. -- Использовать **i18n** (i18next) для локализации всех пользовательских текстов. diff --git a/OLD_parts/4-arkhitektura.md b/OLD_parts/4-arkhitektura.md deleted file mode 100644 index eaf7289..0000000 --- a/OLD_parts/4-arkhitektura.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Архитектура ---- - -# Архитектура - -## Архитектура проекта -В проекте используется FSD (Feature-Sliced Design) архитектура. - -- **FSD-границы** - - Не нарушать границы слоёв (например, feature не может импортировать из widgets). - - Бизнес-логика должна быть вынесена в хуки или сервисы. -- **Импорты** - - Внутри слоя — относительные импорты. - - Между слоями — абсолютные импорты. -- **Требования** - - Не смешивать логику разных слоёв. - - Не хранить бизнес-логику в UI-компонентах. -- **Именование** - - Файлы и папки kebab-case. - ---- diff --git a/OLD_parts/5-code-style.md b/OLD_parts/5-code-style.md deleted file mode 100644 index 297395b..0000000 --- a/OLD_parts/5-code-style.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Стиль кода ---- - -# Стиль кода - -## Отступы - - Используем 2 пробела для отступов во всём проекте. Не используем табы. - - -## Кавычки - -Используем **одинарные кавычки** для строк в JavaScript/TypeScript, и **двойные кавычки** для атрибутов в JSX/TSX. - -**Пример:** - -```ts -// JavaScript/TypeScript -const message = 'Привет, мир!'; -const name = 'ProjectName'; -``` - -```tsx -// JSX/TSX - - -``` - -## Строгая типизация - -всегда указывать типы для пропсов, возвращаемых значений, параметров функций. - -## Ранние возвраты - -(early return) для повышения читаемости. - -## Мемоизация - -Старайся оптимизировать код если это возможно. - -## Документирование - -Документируем ТОЛЬКО ОПИСАНИЕ (функций, компонентов, типов и их полей). - -## any, unknown - -запрещено использовать без крайней необходимости. - -## Классы в TSX - -Для стилизации компонентов используем CSS-модули и методологию BEM. Классы подключаются через объект стилей, импортированный из соответствующего `.module.css` файла. - -> Объект стилей всегда импортируется с именем `s` (сокращённо от style), а не `styles`. - -**Пример:** - -```tsx -import s from './my-component.module.css'; - -export const MyComponent = () => ( -
- - Текст - -
-); -``` - -- Имя класса всегда берётся из объекта `s`. -- Для модификаторов используется отдельный класс с нижним подчёркиванием (например, `s._active`). -- Не используйте строковые литералы с классами напрямую — только через объект `s`. diff --git a/OLD_parts/6-naming.md b/OLD_parts/6-naming.md deleted file mode 100644 index 8275ba6..0000000 --- a/OLD_parts/6-naming.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Именование ---- - -# Именование - -## Именование файлов и папок -- Папка компонента: kebab-case, совпадает с названием компонента, пример: `component-name`. -- React-компонент: kebab-case, совпадает с названием компонента, пример: `component-name.tsx`. -- Стили: kebab-case, шаблон: `.module.css`, пример: `style-name.module.css`. -- Интерфейсы: kebab-case, шаблон: `.interface.ts`, пример: `interface-name.interface.ts`. -- Типы: kebab-case, шаблон: `.type.ts`, пример: `type-name.type.ts`. -- Enum: kebab-case, шаблон: `.enum.ts`, пример: `enum-name.enum.ts`. -- Схемы: kebab-case, шаблон: `.schema.ts`, пример: `schema-name.schema.ts`. -- Локализация: kebab-case, пример: `ru.json`, `en.json`. -- Утилиты: kebab-case, шаблон: `.util.ts`, пример: `util-name.util.ts` -- React Hooks: kebab-case, шаблон: `use-.hook.ts`, пример: `use-hook-name.hook.ts` -- Хранилища состояния компонента: kebab-case, шаблон: `.store.ts`, пример: `store-name.store.ts` diff --git a/OLD_parts/7-docs.md b/OLD_parts/7-docs.md deleted file mode 100644 index 2d58d42..0000000 --- a/OLD_parts/7-docs.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Документирование ---- - -# Документирование - -## Правило для документирования кода - -- Документировать разрешено только описание (назначение) функций, компонентов, типов, интерфейсов, enum и их полей. -- Строго запрещено документировать параметры, возвращаемые значения, типы пропсов, аргументы, возвращаемые значения функций, компоненты, хуки и т.д. -- В интерфейсах, типах и enum разрешено документировать только смысл (описание) каждого поля или значения. -- В React-компонентах, функциях, хранилищах, схемах, утилитах разрешено документировать только назначение (описание), без детализации параметров и возвращаемых значений. -- Описание должно быть кратким, информативным и реально помогать понять структуру и бизнес-логику. -- Не допускается избыточная или дублирующая очевидное документация. -- В конце описания всегда ставить точку. - -**Примеры правильного документирования** -```tsx -/** - * Список задач пользователя. - */ -export const TodoList = memo(() => { ... }); - -/** - * Интерфейс задачи. - */ -export interface TodoItem { - /** Уникальный идентификатор задачи. */ - id: string; - /** Текст задачи. */ - text: string; - /** Статус выполнения задачи. */ - completed: boolean; -} - -/** - * Перечисление фильтров задач. - */ -export enum TodoFilter { - /** Все задачи. */ - All = 'all', - /** Только активные задачи. */ - Active = 'active', - /** Только выполненные задачи. */ - Completed = 'completed', -} -``` - -**Примеры неправильного документирования** -```ts -// ❌ Не нужно:/ -/** - * @param id - идентификатор задачи - * @returns объект задачи - */ - -// ❌ Не нужно:/ -/** - * @param props - пропсы компонента - * @returns JSX.Element - */ - -// ❌ Не нужно:/ -/** - * id — идентификатор задачи - * text — текст задачи - * completed — статус выполнения - */ -``` diff --git a/OLD_parts/8-typing.md b/OLD_parts/8-typing.md deleted file mode 100644 index e16c47b..0000000 --- a/OLD_parts/8-typing.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: Типизация ---- - -# Типизация - -## Общие правила типизации - -> Данный раздел определяет единые требования к типизации для всего проекта. Соблюдение этих правил обеспечивает читаемость, предсказуемость и безопасность кода. - -- Использовать только строгую типизацию TypeScript для всех файлов логики, компонентов, хуков, API, сторов и утилит. -- Всегда явно указывать типы для: - - Пропсов компонентов - - Параметров функций и методов - - Возвращаемых значений функций и методов - - Всех переменных состояния (в том числе в store) - - Всех значимых переменных и констант, если их тип не очевиден из присваивания -- Не использовать `any` и `unknown` без крайней необходимости. Если использование неизбежно — обязательно добавить комментарий с обоснованием. -- Все интерфейсы, типы и enum всегда размещать в папке `types/` на своём уровне абстракции (например, `features/todo/types/`). -- Для DTO всегда использовать отдельную папку `dto/` на уровне сущности или слоя. -- Для сложных структур использовать отдельные интерфейсы или типы, размещая их в соответствующих файлах в папке `types/`. -- Для DTO, enum, схем и других сущностей — всегда создавать отдельные типы/интерфейсы с осмысленными именами. -- Ключи enum всегда писать ЗАГЛАВНЫМИ_БУКВАМИ (SCREAMING_SNAKE_CASE). -- Не использовать неявное приведение типов и не полагаться на автоматический вывод, если это может снизить читаемость или безопасность. -- Для массивов и объектов всегда указывать тип элементов/ключей. -- Для возвращаемых значений асинхронных функций всегда указывать тип Promise. -- Типизацию коллбеков и функций, передаваемых в пропсы, указывать инлайн, не выносить в отдельные типы. -- Для типизации внешних библиотек использовать официальные типы или создавать собственные декларации при необходимости. -- Не использовать устаревшие или не рекомендуемые паттерны типизации (например, `Function`, `Object`, `{}`). ---- - -### Примеры - -#### Интерфейс и типы для сущностей (всегда в папке types/) - -```ts -// features/todo/types/todo-item.interface.ts - -/** - * Интерфейс задачи. - */ -export interface TodoItem { - /** Уникальный идентификатор задачи. */ - id: string; - /** Текст задачи. */ - text: string; - /** Статус выполнения задачи. */ - completed: boolean; -} -``` - -#### Типизация enum (всегда в папке types/) - -```ts -// features/todo/types/todo-status.enum.ts - -/** - * Перечисление статусов задачи. - */ -export enum TodoStatus { - /** Активная задача. */ - ACTIVE = 'active', - /** Выполненная задача. */ - COMPLETED = 'completed', -} -``` - -#### Типизация пропсов компонента - -```ts -import { FC, memo } from 'react'; -import { TodoItem } from './types/todo-item.interface'; - -/** - * Список задач. - */ -export interface TodoListProps { - /** Массив задач. */ - items: TodoItem[]; -} - -export const TodoList: FC = memo(({ items }) => ( -
    - {items.map((item) => ( -
  • {item.text}
  • - ))} -
-)); -``` - -#### Типизация функций и коллбеков (инлайн) - -```ts -/** - * Функция фильтрации задач. - */ -export const getCompletedTodos = (items: TodoItem[]): TodoItem[] => { - return items.filter((t) => t.completed); -}; - -/** - * Колбэк для обработки клика (инлайн). - */ -const handleClick = (id: string): void => { - console.log('Clicked:', id); -}; -``` - -#### Типизация асинхронных функций - -```ts -/** - * Получить задачи с сервера. - */ -export const fetchTodos = async (): Promise => { - const response = await fetch('/api/todos'); - return response.json(); -}; -``` - -#### Типизация состояния в store (интерфейс в types/) - -```ts -// features/todo/types/todo-store.interface.ts - -/** - * Состояние хранилища задач. - */ -export interface TodoStoreState { - /** Массив задач. */ - items: TodoItem[]; - /** Добавить задачу. */ - addTodo: (item: TodoItem) => void; - /** Удалить задачу. */ - removeTodo: (id: string) => void; -} -``` - -#### Типизация DTO (всегда в папке dto/) - -```ts -// features/todo/dto/create-todo.dto.ts - -/** - * DTO для создания задачи. - */ -export interface CreateTodoDto { - /** Текст задачи. */ - text: string; -} - -// features/todo/dto/todo-response.dto.ts - -/** - * DTO ответа сервера. - */ -export interface TodoResponseDto { - /** Созданная задача. */ - todo: TodoItem; -} -``` - -#### Типизация внешних библиотек - -```ts -import type { AxiosResponse } from 'axios'; - -export const getData = async (): Promise> => { - // ... -}; -``` -### Чек-лист проверки типизации - -- [ ] Все пропсы компонентов явно типизированы через интерфейс или тип в папке `types/`. -- [ ] Все параметры и возвращаемые значения функций и методов явно типизированы. -- [ ] Все переменные состояния (в том числе в store) имеют явные типы. -- [ ] Все интерфейсы, типы и enum размещены в папке `types/` на своём уровне абстракции. -- [ ] Ключи всех enum написаны ЗАГЛАВНЫМИ_БУКВАМИ (SCREAMING_SNAKE_CASE). -- [ ] Все DTO размещены в папке `dto/` на своём уровне абстракции. -- [ ] Не используется `any` и `unknown` без крайней необходимости и поясняющего комментария. -- [ ] Для сложных структур используются отдельные интерфейсы или типы. -- [ ] Для массивов и объектов указан тип элементов/ключей. -- [ ] Для асинхронных функций указан тип Promise с конкретным типом результата. -- [ ] Типы коллбеков и функций, передаваемых в пропсы, указаны инлайн. -- [ ] Не используются устаревшие типы (`Function`, `Object`, `{}`). -- [ ] Для внешних библиотек используются официальные типы или собственные декларации. -- [ ] Нет неявного приведения типов, все типы читаемы и прозрачны. diff --git a/OLD_parts/9-localization.md b/OLD_parts/9-localization.md deleted file mode 100644 index 089e517..0000000 --- a/OLD_parts/9-localization.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Локализация ---- - -# Локализация - -## Правила использования локализации - -- Все пользовательские тексты должны быть вынесены в локализационные файлы. -- Для каждого компонента создавать папку `locales/` с файлами `ru.json`, `en.json` и т.д. -- Новые namespace обязательно регистрировать в экземпляре i18n (см. `app/i18n.ts`). -- В коде использовать только функцию перевода из i18n, не использовать "жёстко" прописанные строки. diff --git a/README.md b/README.md index cdd8f00..56835a5 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,53 @@ -# NextJS Style Guide +# Style Guide -Rules and standards for NextJS and TypeScript development: architecture, typing, styles, components, API, and infrastructure. +Репозиторий с правилами и стандартами фронтенд-разработки. Исходники документации собираются в разные форматы под разные фреймворки. -## Documentation Structure +## Структура -### Processes +```text +src/ # Исходники — только .md файлы +├── base/ # Общие правила (не поставляется отдельно) +│ ├── basics/ # Базовые: стиль кода, именование, типизация +│ ├── applied/ # Прикладные: компоненты, стили, хуки, API +│ └── triggers/ # Триггеры: создание компонента, стилизация и т.д. +│ +└── nextjs/ # Next.js — самостоятельная единица + ├── applied/ # Next.js-специфичные: page-level, project-structure + ├── triggers/ # Next.js-специфичные триггеры: create-page, create-layout + ├── DEVELOP.md # Точка входа для агента-разработчика + └── REVIEW.md # Точка входа для агента-ревьювера -**What to do** in a specific situation — step-by-step instructions. +scripts/ # Скрипты и манифесты сборки +├── build-ai.js # Скрипт сборки +└── nextjs.build.js # Манифест: какие файлы, куда, как называются -| Section | Answers the question | -|---------|---------------------| -| Getting Started | What tools to install before starting development? | -| Creating an App | How to create a new project, where to get a template? | -| Creating Pages | How to add a page: routing and screen? | -| Creating Components | How to generate components using templates? | -| Styling | What to use: Mantine, tokens, or PostCSS? | -| Data Fetching | How to fetch data: SWR, codegen, sockets? | -| State Management | When and how to create a store (Zustand)? | -| Localization | How to add translations and work with i18next? | +dist/ # Собранные версии (gitignore) +├── ai/{framework}/ # Для AI-агентов +└── vitepress/{framework}/ # Для людей (планируется) +``` -### Basic Rules +## Сборка -**What the code should look like** — standards not tied to a specific technology. +```bash +npm run build:ai # Собрать все фреймворки +``` -| Section | Answers the question | -|---------|---------------------| -| Tech Stack | What stack do we use? | -| Architecture | How are FSD layers, dependencies, and public API structured? | -| Code Style | How to format code: indentation, quotes, imports, early return? | -| Naming | How to name files, variables, components, hooks? | -| Documentation | How to write JSDoc: what to document and what not? | -| Typing | How to type: type vs interface, any/unknown? | +## Манифест -### Applied Sections +Каждый фреймворк имеет манифест `scripts/{framework}.build.js`. Ключ — путь в выходной папке, значение — путь исходника в `src/`. -**How a specific area works** — rules, structure, and code examples for specific technologies and tools. +Скрипт только копирует файлы по манифесту. Никакой генерации. -| Section | Answers the question | -|---------|---------------------| -| Project Structure | How are folders and files organized by FSD? | -| Components | How is a component structured: files, props, clsx? | -| Page-level Components | How to define layout, page, loading, error, not-found? | -| Templates & Code Generation | How do templates work: syntax, variables, modifiers? | -| Styles | How to write CSS: PostCSS Modules, nesting, media, tokens? | -| Images | _(not filled)_ | -| SVG Sprites | _(not filled)_ | -| Video | _(not filled)_ | -| API | _(not filled)_ | -| Stores | _(not filled)_ | -| Hooks | _(not filled)_ | -| Fonts | _(not filled)_ | -| Localization | _(not filled)_ | +## Добавление раздела -## For Assistants +1. Создать `.md` в `src/base/` (общий) или `src/{framework}/` (специфичный). +2. Добавить frontmatter: `title`, `scope`, `keywords`, `when`. +3. Добавить путь в манифест `scripts/{framework}.build.js`. +4. Обновить точку входа (`DEVELOP.md` и/или `REVIEW.md`). +5. `npm run build:ai`. -Full documentation in a single MD file: https://gromlab.ru/docs/frontend-style-guide/raw/branch/main/generated/en/RULES.md +## Добавление фреймворка + +1. Создать `src/{framework}/` с `.md` файлами и точками входа. +2. Создать `scripts/{framework}.build.js`. +3. `npm run build:ai`. diff --git a/README_RU.md b/README_RU.md deleted file mode 100644 index 0ead4f8..0000000 --- a/README_RU.md +++ /dev/null @@ -1,60 +0,0 @@ -# NextJS Style Guide - -Правила и стандарты разработки на NextJS и TypeScript: архитектура, типизация, стили, компоненты, API и инфраструктурные разделы. - -## Для ассистентов - -Полная документация в одном MD файле: https://gromlab.ru/docs/nextjs-style-guide/raw/branch/main/generated/ru/RULES.md - -## Структура документации - -### Workflow - -**Что делать и в каком порядке** — пошаговые инструкции. - -| Раздел | Отвечает на вопрос | -|--------|-------------------| -| Начало работы | Что нужно знать перед началом разработки? | -| Создание проекта | Как начать новый проект? | -| Генерация кода | Какие модули должны генерироваться из шаблонов? | -| Добавление страницы | Как добавить новую страницу в проект? | -| Добавление UI-модуля | Как создать компонент, фичу, виджет, сущность или layout? | -| Стилизация | Как стилизовать компоненты в проекте? | -| Получение данных | Как получать данные с сервера? | -| Управление состоянием | Как работать с состоянием? | -| Локализация | Как добавлять переводы и подключать локализацию? | - -### Базовые правила - -**Каким должен быть код** — стандарты, не привязанные к конкретной технологии. - -| Раздел | Отвечает на вопрос | -|--------|-------------------| -| Технологии и библиотеки | Какой стек используем? | -| Архитектура | Как устроены слои FSD, зависимости, публичный API? | -| Стиль кода | Как оформлять код: отступы, кавычки, импорты, early return? | -| Именование | Как называть файлы, переменные, компоненты, хуки? | -| Документирование | Как писать JSDoc: что документировать, а что нет? | -| Типизация | Как типизировать: type vs interface, any/unknown? | - -### Прикладные разделы - -**Как это настроить и использовать** — конфигурация, структура и примеры кода для конкретных областей. - -| Раздел | Отвечает на вопрос | -|--------|-------------------| -| Настройка VS Code | Как настроить редактор для проекта? | -| Структура проекта | Как организованы папки и файлы по FSD? | -| Компоненты | Как устроен компонент: файлы, пропсы, clsx? | -| Page-level компоненты | Как описывать layout, page, loading, error, not-found? | -| Шаблоны и генерация кода | Как работают шаблоны, синтаксис и инструменты генерации? | -| Стили | Как писать CSS: PostCSS Modules, вложенность, медиа, токены? | -| Изображения | _(не заполнен)_ | -| SVG-спрайты | _(не заполнен)_ | -| Видео | _(не заполнен)_ | -| API | _(не заполнен)_ | -| Stores | _(не заполнен)_ | -| Хуки | _(не заполнен)_ | -| Шрифты | _(не заполнен)_ | -| Локализация | _(не заполнен)_ | - diff --git a/concat-md.js b/concat-md.js deleted file mode 100644 index b1f89e9..0000000 --- a/concat-md.js +++ /dev/null @@ -1,107 +0,0 @@ -import path from "path"; -import fs from "fs"; - -// Явный порядок файлов внутри каждого языка -const fileOrder = [ - // index - "index.md", - // workflow - "workflow.md", - // basics - "basics/tech-stack.md", - "basics/naming.md", - "basics/architecture.md", - "basics/code-style.md", - "basics/documentation.md", - "basics/typing.md", - // applied - "applied/project-structure.md", - "applied/components.md", - "applied/page-level.md", - "applied/templates-generation.md", - "applied/styles.md", - "applied/images-sprites.md", - "applied/svg-sprites.md", - "applied/video.md", - "applied/api.md", - "applied/stores.md", - "applied/hooks.md", - "applied/fonts.md", - "applied/localization.md", - "applied/vscode.md", -]; - -// Удалить frontmatter из содержимого md-файла -const stripFrontmatter = (content) => - content.replace(/^---[\s\S]*?---\n*/m, ""); - -// Сдвинуть уровень заголовков на 1 вниз (h1→h2, h2→h3, ...) -// Не трогает заголовки внутри блоков кода -const shiftHeadings = (content) => { - const lines = content.split("\n"); - let inCodeBlock = false; - - return lines - .map((line) => { - if (line.startsWith("```")) inCodeBlock = !inCodeBlock; - if (inCodeBlock) return line; - if (/^#{1,5}\s/.test(line)) return "#" + line; - return line; - }) - .join("\n"); -}; - -// Собрать RULES.md с мета-якорями для каждого файла -const buildRules = (lang) => { - const srcDir = `./docs/${lang}`; - const outDir = `./generated/${lang}`; - const outFile = path.join(outDir, "RULES.md"); - - if (!fs.existsSync(srcDir)) { - console.log(`Пропуск ${lang}: папка ${srcDir} не найдена`); - return; - } - - fs.mkdirSync(outDir, { recursive: true }); - - const parts = []; - - for (const file of fileOrder) { - const filePath = path.join(srcDir, file); - if (!fs.existsSync(filePath)) continue; - - const raw = fs.readFileSync(filePath, "utf8"); - const content = stripFrontmatter(raw).trim(); - if (!content) continue; - - // Мета-якорь: путь VitePress без расширения - const route = "/" + file.replace(/\.md$/, ""); - // index.md остаётся без сдвига (его h1 — главный заголовок документа) - const processed = file === "index.md" ? content : shiftHeadings(content); - parts.push(`\n${processed}`); - } - - fs.writeFileSync(outFile, parts.join("\n\n"), "utf8"); - console.log(`RULES.md (${lang}) создан: ${outFile}`); -}; - -// Собираем RULES.md для обоих языков -buildRules("ru"); -buildRules("en"); - -// Генерируем README из index.md -const buildReadme = (lang, outFile) => { - const indexPath = `./docs/${lang}/index.md`; - - if (!fs.existsSync(indexPath)) { - console.log(`Пропуск README (${lang}): ${indexPath} не найден`); - return; - } - - const content = stripFrontmatter(fs.readFileSync(indexPath, "utf8")); - fs.writeFileSync(outFile, content, "utf8"); - console.log(`${outFile} создан из ${indexPath}`); -}; - -buildReadme("en", "./README.md"); -buildReadme("ru", "./README_RU.md"); diff --git a/docs/en/applied/api.md b/docs/en/applied/api.md deleted file mode 100644 index 92e2c05..0000000 --- a/docs/en/applied/api.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: API ---- - -# API diff --git a/docs/en/applied/components.md b/docs/en/applied/components.md deleted file mode 100644 index 62b33e6..0000000 --- a/docs/en/applied/components.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Components ---- - -# Components - -Rules for creating UI components across all FSD layers. diff --git a/docs/en/applied/fonts.md b/docs/en/applied/fonts.md deleted file mode 100644 index f44d50c..0000000 --- a/docs/en/applied/fonts.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fonts ---- - -# Fonts diff --git a/docs/en/applied/hooks.md b/docs/en/applied/hooks.md deleted file mode 100644 index a0c4376..0000000 --- a/docs/en/applied/hooks.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Hooks ---- - -# Hooks diff --git a/docs/en/applied/images-sprites.md b/docs/en/applied/images-sprites.md deleted file mode 100644 index 9014879..0000000 --- a/docs/en/applied/images-sprites.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Images ---- - -# Images diff --git a/docs/en/applied/localization.md b/docs/en/applied/localization.md deleted file mode 100644 index c0c5eb3..0000000 --- a/docs/en/applied/localization.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Localization ---- - -# Localization diff --git a/docs/en/applied/page-level.md b/docs/en/applied/page-level.md deleted file mode 100644 index 7da2c23..0000000 --- a/docs/en/applied/page-level.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Page-level Components ---- - -# Page-level Components - -Next.js App Router special files used by the framework by convention: `layout.tsx`, `page.tsx`, `loading.tsx`, `error.tsx`, `not-found.tsx`, `template.tsx`. diff --git a/docs/en/applied/project-structure.md b/docs/en/applied/project-structure.md deleted file mode 100644 index bbf5def..0000000 --- a/docs/en/applied/project-structure.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Project Structure ---- - -# Project Structure - -Base project structure and principles of module organization at folder and file level. diff --git a/docs/en/applied/stores.md b/docs/en/applied/stores.md deleted file mode 100644 index d0cf77d..0000000 --- a/docs/en/applied/stores.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Stores ---- - -# Stores diff --git a/docs/en/applied/styles.md b/docs/en/applied/styles.md deleted file mode 100644 index 7af40ac..0000000 --- a/docs/en/applied/styles.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Styles ---- - -# Styles - -CSS writing rules: PostCSS Modules, nesting, media queries, variables, formatting. diff --git a/docs/en/applied/svg-sprites.md b/docs/en/applied/svg-sprites.md deleted file mode 100644 index 45e5895..0000000 --- a/docs/en/applied/svg-sprites.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: SVG Sprites ---- - -# SVG Sprites diff --git a/docs/en/applied/templates-generation.md b/docs/en/applied/templates-generation.md deleted file mode 100644 index c137721..0000000 --- a/docs/en/applied/templates-generation.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Templates & Code Generation ---- - -# Templates & Code Generation - -Template tools, syntax, and examples for code generation. diff --git a/docs/en/applied/video.md b/docs/en/applied/video.md deleted file mode 100644 index 7b6cd18..0000000 --- a/docs/en/applied/video.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Video ---- - -# Video diff --git a/docs/en/basics/architecture.md b/docs/en/basics/architecture.md deleted file mode 100644 index b908f6b..0000000 --- a/docs/en/basics/architecture.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Architecture ---- - -# Architecture - -Architecture based on FSD (Feature-Sliced Design) and strict module boundaries. diff --git a/docs/en/basics/code-style.md b/docs/en/basics/code-style.md deleted file mode 100644 index 85bec4b..0000000 --- a/docs/en/basics/code-style.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Code Style ---- - -# Code Style - -Unified code formatting rules: indentation, line breaks, quotes, import order, and readability. diff --git a/docs/en/basics/documentation.md b/docs/en/basics/documentation.md deleted file mode 100644 index 094808e..0000000 --- a/docs/en/basics/documentation.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Documentation ---- - -# Documentation - -Documentation should help understand the purpose of an entity, not duplicate its types or obvious details. diff --git a/docs/en/basics/naming.md b/docs/en/basics/naming.md deleted file mode 100644 index c5aebc0..0000000 --- a/docs/en/basics/naming.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Naming ---- - -# Naming - -Naming should be predictable, concise, and reflect the meaning of the entity. diff --git a/docs/en/basics/tech-stack.md b/docs/en/basics/tech-stack.md deleted file mode 100644 index c43318f..0000000 --- a/docs/en/basics/tech-stack.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Tech Stack ---- - -# Tech Stack - -Base technology stack and libraries used in projects. diff --git a/docs/en/basics/typing.md b/docs/en/basics/typing.md deleted file mode 100644 index faa1d11..0000000 --- a/docs/en/basics/typing.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Typing ---- - -# Typing - -Typing is required for all public interfaces, functions, and components. diff --git a/docs/en/index.md b/docs/en/index.md deleted file mode 100644 index cdd8f00..0000000 --- a/docs/en/index.md +++ /dev/null @@ -1,57 +0,0 @@ -# NextJS Style Guide - -Rules and standards for NextJS and TypeScript development: architecture, typing, styles, components, API, and infrastructure. - -## Documentation Structure - -### Processes - -**What to do** in a specific situation — step-by-step instructions. - -| Section | Answers the question | -|---------|---------------------| -| Getting Started | What tools to install before starting development? | -| Creating an App | How to create a new project, where to get a template? | -| Creating Pages | How to add a page: routing and screen? | -| Creating Components | How to generate components using templates? | -| Styling | What to use: Mantine, tokens, or PostCSS? | -| Data Fetching | How to fetch data: SWR, codegen, sockets? | -| State Management | When and how to create a store (Zustand)? | -| Localization | How to add translations and work with i18next? | - -### Basic Rules - -**What the code should look like** — standards not tied to a specific technology. - -| Section | Answers the question | -|---------|---------------------| -| Tech Stack | What stack do we use? | -| Architecture | How are FSD layers, dependencies, and public API structured? | -| Code Style | How to format code: indentation, quotes, imports, early return? | -| Naming | How to name files, variables, components, hooks? | -| Documentation | How to write JSDoc: what to document and what not? | -| Typing | How to type: type vs interface, any/unknown? | - -### Applied Sections - -**How a specific area works** — rules, structure, and code examples for specific technologies and tools. - -| Section | Answers the question | -|---------|---------------------| -| Project Structure | How are folders and files organized by FSD? | -| Components | How is a component structured: files, props, clsx? | -| Page-level Components | How to define layout, page, loading, error, not-found? | -| Templates & Code Generation | How do templates work: syntax, variables, modifiers? | -| Styles | How to write CSS: PostCSS Modules, nesting, media, tokens? | -| Images | _(not filled)_ | -| SVG Sprites | _(not filled)_ | -| Video | _(not filled)_ | -| API | _(not filled)_ | -| Stores | _(not filled)_ | -| Hooks | _(not filled)_ | -| Fonts | _(not filled)_ | -| Localization | _(not filled)_ | - -## For Assistants - -Full documentation in a single MD file: https://gromlab.ru/docs/frontend-style-guide/raw/branch/main/generated/en/RULES.md diff --git a/docs/en/workflow/creating-app.md b/docs/en/workflow/creating-app.md deleted file mode 100644 index 119b9b6..0000000 --- a/docs/en/workflow/creating-app.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Creating an App ---- - -# Creating an App - -How to create a new application: choosing a project template and initialization. diff --git a/docs/en/workflow/creating-components.md b/docs/en/workflow/creating-components.md deleted file mode 100644 index 6c71dd2..0000000 --- a/docs/en/workflow/creating-components.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Creating Components ---- - -# Creating Components - -Generating components using templates, working with child components. diff --git a/docs/en/workflow/creating-pages.md b/docs/en/workflow/creating-pages.md deleted file mode 100644 index 5edd2fa..0000000 --- a/docs/en/workflow/creating-pages.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Creating Pages ---- - -# Creating Pages - -Page creation pattern: routing (page.tsx) and screen. diff --git a/docs/en/workflow/data-fetching.md b/docs/en/workflow/data-fetching.md deleted file mode 100644 index a20cf89..0000000 --- a/docs/en/workflow/data-fetching.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Data Fetching ---- - -# Data Fetching - -How to fetch data: SWR, API client codegen, sockets. diff --git a/docs/en/workflow/getting-started.md b/docs/en/workflow/getting-started.md deleted file mode 100644 index a503150..0000000 --- a/docs/en/workflow/getting-started.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Getting Started ---- - -# Getting Started - -Setting up the environment and installing tools before starting development. diff --git a/docs/en/workflow/localization.md b/docs/en/workflow/localization.md deleted file mode 100644 index 6231664..0000000 --- a/docs/en/workflow/localization.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Localization ---- - -# Localization - -How to add translations and work with i18next. diff --git a/docs/en/workflow/state-management.md b/docs/en/workflow/state-management.md deleted file mode 100644 index 05cfa65..0000000 --- a/docs/en/workflow/state-management.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: State Management ---- - -# State Management - -When and how to create a store (Zustand), what to store locally vs globally. diff --git a/docs/en/workflow/styling.md b/docs/en/workflow/styling.md deleted file mode 100644 index 495de7e..0000000 --- a/docs/en/workflow/styling.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Styling ---- - -# Styling - -Styling tools priority and rules for their application. diff --git a/docs/ru/applied/api.md b/docs/ru/applied/api.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/ru/applied/fonts.md b/docs/ru/applied/fonts.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/ru/applied/hooks.md b/docs/ru/applied/hooks.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/ru/applied/images-sprites.md b/docs/ru/applied/images-sprites.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/ru/applied/localization.md b/docs/ru/applied/localization.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/ru/applied/stores.md b/docs/ru/applied/stores.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/ru/applied/svg-sprites.md b/docs/ru/applied/svg-sprites.md deleted file mode 100644 index 2c1a175..0000000 --- a/docs/ru/applied/svg-sprites.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: SVG-спрайты ---- - -# SVG-спрайты diff --git a/docs/ru/applied/video.md b/docs/ru/applied/video.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/ru/basics/architecture.md b/docs/ru/basics/architecture.md deleted file mode 100644 index 2a58206..0000000 --- a/docs/ru/basics/architecture.md +++ /dev/null @@ -1,471 +0,0 @@ ---- -title: Архитектура ---- - -# Архитектура - -Раздел описывает архитектуру проекта: из каких слоёв состоит приложение, -как организован код внутри слоёв и какие правила управляют зависимостями. - -## Что нужно знать - -SLM Design (Scoped Layered Module Design) — архитектурный подход -к проектированию фронтенд-приложений, предложенный Громовым Сергеем в 2026 г. - -Вырос на основе: - -- [Feature-Sliced Design](https://feature-sliced.design) — слои и направление зависимостей -- Screaming Architecture — структура говорит сама за себя -- Colocation Principle — код рядом с местом использования - -Переосмыслив эти подходы, SLM Design отличается от FSD в трёх аспектах: -где живёт код (колокация), как он организован (модули) -и как масштабируется (подъём при переиспользовании). - -## Терминология - -Архитектура оперирует четырьмя ключевыми понятиями: - -- **Слой** — содержит модули -- **Модуль** — содержит сегменты -- **Компонент** — содержит сегменты -- **Сегмент** — папка внутри модуля или компонента, группирующая код по назначению: UI-элементы (`ui/`), хуки (`hooks/`), типы (`types/`), стили (`styles/`) и другие - -Модуль и компонент устроены одинаково — оба имеют сегменты. Разница в том, где они живут и обязателен ли UI. - -```text -Слой -└── Модуль - ├── Сегменты (hooks/, stores/, types/, styles/, lib/...) - └── ui/ - └── Компонент - ├── Сегменты (hooks/, stores/, types/, styles/, lib/...) - └── ui/ - └── Компонент → ... -``` - -### Слой - -Архитектурный уровень. Содержит только модули. Определяет назначение кода и правила зависимостей. - -### Модуль - -Единица первого уровня слоя, объединённая по смыслу. Может содержать компонент, логику, типы, стили — или любую комбинацию. Имеет публичный API (`index.ts`) и внутреннюю структуру из сегментов. - -Модуль — не обязательно UI. Feature `analytics` может быть только стором и сервисом. Entity `session` может быть только типами и хуком. - -Модуль не может содержать вложенных модулей. Вложенные единицы с UI размещаются в сегменте `ui/` как компоненты. - -### Компонент - -Вложенная единица внутри сегмента `ui/` модуля (или другого компонента). Публичный `.tsx` файл обязателен. Именуется без суффикса слоя. - -Компонент может иметь собственные сегменты (`hooks/`, `styles/`, `types/` и т.д.), `index.ts` и свой `ui/` с ещё более вложенными компонентами. - -Отличия от модуля: - -| | Модуль | Компонент | -|--|--------|-----------| -| Где живёт | В корне слоя | В `ui/` модуля или другого компонента | -| Публичный `.tsx` | С суффиксом слоя, опционален | Без суффикса, обязателен | -| Может не иметь UI | Да | Нет | - -Пример: - -```text -features/auth-by-email/ # модуль -├── auth-by-email.feature.tsx # публичный .tsx модуля (с суффиксом, опционален) -├── ui/ # сегмент: компоненты -│ ├── login-form/ # компонент -│ │ ├── login-form.tsx # публичный .tsx компонента (без суффикса, обязателен) -│ │ ├── ui/ # вложенные компоненты -│ │ │ └── password-field/ -│ │ │ └── password-field.tsx -│ │ ├── hooks/ -│ │ │ └── use-validation.hook.ts -│ │ ├── styles/ -│ │ │ └── login-form.module.css -│ │ └── index.ts -│ └── reset-password/ # компонент -│ ├── reset-password.tsx -│ └── index.ts -├── hooks/ -│ └── use-auth.hook.ts -├── stores/ -│ └── auth.store.ts -└── index.ts -``` - -### Сегмент - -Техническая папка внутри модуля или компонента, группирующая код по назначению. Набор не фиксирован — включаются только те сегменты, которые нужны. - -| Сегмент | Назначение | -|---------|-----------| -| `ui/` | Вложенные компоненты | -| `hooks/` | React-хуки | -| `stores/` | Сторы состояния | -| `types/` | Интерфейсы, типы, enums, DTO | -| `styles/` | Стили | -| `lib/` | Утилиты | -| `services/` | Внешние источники данных | -| `helpers/` | Вспомогательные функции | -| `config/` | Константы, конфигурация | - -## Ключевой принцип - -> Модуль живёт на самом низком уровне, где он используется. -> Поднимается выше только при переиспользовании в 2+ местах. - -Если модуль используется только в одном месте — он остаётся на текущем уровне. -Как только он начинает использоваться в 2+ местах — выносится на уровень выше. -В крайнем случае — в `shared/`, где он доступен всем. - -## Слои - -Каждый нижний слой не знает о существовании верхних. Импорты идут строго сверху вниз. - -``` -app → layouts → screens → widgets → features → entities → shared -``` - -| Слой | Что лежит | Импортирует | -|------|-----------|-------------| -| **App** | Роутинг, провайдеры, глобальные стили. Композиция layout + screen для маршрута. | Все слои ниже | -| **Layouts** | Каркас страницы, общий для группы маршрутов. | widgets, features, entities, shared | -| **Screens** | Контент конкретной страницы. | widgets, features, entities, shared | -| **Widgets** | Составные блоки с данными/логикой, переиспользуемые в 2+ местах. | features, entities, shared | -| **Features** | Пользовательское действие или интерактивный сценарий. | entities, shared | -| **Entities** | Бизнес-сущность с отображением и типами. | shared | -| **Shared** | Переиспользуемые компоненты, утилиты, стили без бизнес-логики. | ничего | - -Принципы: - -- Импорты строго сверху вниз -- Модули одного слоя не знают друг о друге -- Layout получает контекстно-зависимые блоки через пропсы от app, а не импортирует их сам -- `entities/` и `features/` создаются осознанно — это не результат «вынесения» компонента из screen - -### App - -Точка входа приложения: роутинг (Next.js App Router), провайдеры, глобальные стили. -Находится на самом высоком уровне абстракции — может импортировать любой слой ниже. -Никакой бизнес-логики — только композиция. - -```text -app/ -├── layout.tsx # RootLayout: провайдеры, глобальные стили -├── page.tsx # Главная: MainLayout + HomeScreen -├── knv-new/ -│ └── page.tsx # КНВ: MainLayout + KnvScreen -└── catalog/ - └── page.tsx # Каталог: MainLayout + CatalogScreen -``` - -```tsx -// app/knv-new/page.tsx -import { MainLayout } from '@/layouts/main' -import { KnvScreen } from '@/screens/knv' - -export default function KnvNewPage() { - return ( - - - - ) -} -``` - -Если layout требует разный контент в зависимости от страницы — app передаёт его через пропсы: - -```tsx -// app/knv-new/page.tsx -import { MainLayout } from '@/layouts/main' -import { KnvScreen } from '@/screens/knv' -import { KnvHeader } from '@/widgets/knv-header' - -export default function KnvNewPage() { - return ( - }> - - - ) -} -``` - -### Layouts - -Каркас страницы — общие элементы, одинаковые для группы маршрутов (header, footer, sidebar). - -Если компонент внутри layout начинает использоваться в 2+ местах — он выносится в `widgets/` или `shared/ui/`. - -```text -src/layouts/ -└── main/ - ├── main.layout.tsx - ├── ui/ - │ ├── header/ - │ │ └── header.tsx - │ └── footer/ - │ └── footer.tsx - └── index.ts -``` - -### Screens - -Контент конкретной страницы. Собирает локальные секции и переиспользуемые модули из нижних слоёв. - -Если компонент внутри screen начинает использоваться в 2+ местах — он выносится в `widgets/` или `shared/ui/`. - -```text -src/screens/ -└── knv/ - ├── knv.screen.tsx - ├── ui/ - │ ├── hero-section/ - │ │ └── hero-section.tsx - │ ├── products-section/ - │ │ └── products-section.tsx - │ └── diseases-section/ - │ └── diseases-section.tsx - └── index.ts -``` - -### Widgets - -Составные блоки с данными и логикой, переиспользуемые в 2+ местах. - -Если блок с логикой нужен только в одном месте — это компонент внутри `screens/{name}/ui/` или `layouts/{name}/ui/`, а не widget. - -```text -src/widgets/ -└── popular-products-slider/ - ├── popular-products-slider.widget.tsx - ├── ui/ - │ └── slider-card/ - │ └── slider-card.tsx - ├── hooks/ - │ └── use-products.hook.ts - └── index.ts -``` - -### Features - -Пользовательское действие или интерактивный сценарий: авторизация, заказ, добавление в корзину. - -Feature создаётся осознанно, когда есть действие пользователя с бизнес-логикой. Компонент опционален — feature может экспортировать хуки, сторы, компоненты или всё вместе. - -```text -src/features/ -└── auth-by-email/ - ├── auth-by-email.feature.tsx - ├── ui/ - │ ├── login-form/ - │ │ └── login-form.tsx - │ └── reset-password/ - │ └── reset-password.tsx - ├── hooks/ - │ └── use-auth.hook.ts - ├── stores/ - │ └── auth.store.ts - └── index.ts -``` - -### Entities - -Бизнес-сущность с отображением и типами: препарат, заболевание, врач, пользователь. - -Entity создаётся осознанно, когда появляется бизнес-сущность. Компонент опционален — entity может быть только типами и хуком. - -Отличие от `shared/ui/`: entity-компонент знает о бизнес-домене (принимает `Product`, а не абстрактные пропсы). - -```text -src/entities/ -├── product/ -│ ├── product.entity.tsx -│ ├── ui/ -│ │ └── product-card/ -│ │ └── product-card.tsx -│ ├── types/ -│ │ └── product.type.ts -│ └── index.ts -│ -├── session/ -│ ├── types/ -│ │ └── session.type.ts -│ ├── hooks/ -│ │ └── use-session.hook.ts -│ └── index.ts -``` - -### Shared - -Переиспользуемые компоненты, утилиты, стили без бизнес-логики. Не знает о бизнес-домене — работает с абстрактными данными. - -Структурирован как набор сегментов: - -```text -src/shared/ -├── ui/ -│ ├── icon/ -│ │ └── icon.tsx -│ ├── carousel/ -│ │ ├── carousel.tsx -│ │ ├── ui/ -│ │ │ ├── carousel-slide/ -│ │ │ │ └── carousel-slide.tsx -│ │ │ └── carousel-dots/ -│ │ │ └── carousel-dots.tsx -│ │ └── index.ts -│ ├── container/ -│ └── button/ -├── lib/ -│ ├── format-date.ts -│ └── cn.ts -├── styles/ -│ ├── variables.css -│ └── media.css -└── sprites/ -``` - -## Модуль - -### Структура - -```text -{name}/ -├── {name}.{суффикс}.tsx # компонент (опционален) -├── ui/ # вложенные компоненты -├── hooks/ # хуки -├── stores/ # сторы -├── types/ # типы, интерфейсы, enums -├── styles/ # стили -├── lib/ # утилиты -├── services/ # внешние источники данных -├── helpers/ # вспомогательные функции -├── config/ # константы, конфигурация -└── index.ts # публичный API -``` - -### Именование компонента - -Суффикс слоя получают **только модули первого уровня слоя** — те, что лежат непосредственно в корне слоя. Все компоненты (в `ui/`, любой глубины) именуются без суффикса. Без исключений. - -| Слой | Суффикс | Пример | -|------|---------|--------| -| Layouts | `.layout.tsx` | `main.layout.tsx` | -| Screens | `.screen.tsx` | `knv.screen.tsx` | -| Widgets | `.widget.tsx` | `popular-products-slider.widget.tsx` | -| Features | `.feature.tsx` | `auth-by-email.feature.tsx` | -| Entities | `.entity.tsx` | `product.entity.tsx` | - -Примеры: - -```text -features/auth-by-email/auth-by-email.feature.tsx # модуль первого уровня → суффикс -features/auth-by-email/ui/login-form/login-form.tsx # компонент в ui/ → без суффикса -shared/ui/carousel/carousel.tsx # компонент в shared → без суффикса -``` - -### Правила импорта - -Три уровня правил: - -**Между слоями** — импорты строго сверху вниз: - -``` -app → layouts → screens → widgets → features → entities → shared -``` - -**Внутри модуля (не shared)** — сегменты доступны друг другу и компонентам. Компоненты внутри одного `ui/` не импортируют друг друга: - -```text -features/auth-by-email/ -├── ui/ -│ ├── login-form/ # НЕ может импортировать reset-password -│ └── reset-password/ # НЕ может импортировать login-form -``` - -Если двум компонентам нужен общий код — он поднимается на уровень выше: - -```text -features/auth/ui/login-form/ui/email-input/ # нужен соседу -→ features/auth/ui/email-input/ # поднимаем на уровень -→ shared/ui/email-input/ # если нужен за пределами фичи -``` - -Компоненты наследуют правила зависимостей **родительского слоя**: - -- Компонент внутри `features/auth/ui/login-form/` может импортировать `entities/` и `shared/` — как и сам feature -- Компонент внутри `widgets/hero/ui/hero-stats/` может импортировать `features/`, `entities/`, `shared/` — как и сам widget - -**Shared** — без ограничений на внутренние импорты. Компоненты в `shared/ui/` могут импортировать друг друга (`button` использует `icon`), `ui/` может использовать `lib/` и другие сегменты. Shared — фундамент, его компоненты строятся друг на друге. - -Правила импорта между слоями enforceable через ESLint — настройка границ слоёв и запрет обратных зависимостей. - -## Жизненный цикл модуля - -Модуль не проектируется «на вырост». Он рождается на самом низком уровне -и поднимается только когда появляется реальная потребность. - -Пример пути компонента `product-card`: - -1. **Начало:** `screens/catalog/ui/product-card/` — нужен только на странице каталога. -2. **Переиспользование:** появился на странице поиска — выносим выше. - Куда именно зависит от природы: - - Составной блок с данными и логикой → `widgets/product-card/` - - Представление бизнес-сущности → `entities/product/ui/product-card/` - - Абстрактный UI без бизнес-логики → `shared/ui/product-card/` - -Основной триггер подъёма — переиспользование в 2+ местах. -Но если очевидно что модуль будет переиспользоваться — разумно разместить его на нужном уровне сразу. - -Как происходит подъём на практике: - -1. Разработчик обнаруживает что компонент нужен в другом месте -2. Определяет целевой слой по природе компонента (widget / entity / shared) -3. Перемещает папку, обновляет импорты, добавляет суффикс если это модуль первого уровня слоя -4. Ревью подтверждает что подъём обоснован - -Подъём — это обычный рефакторинг в рамках задачи, а не отдельная активность. - -## Граничные случаи - -| Ситуация | Решение | Почему | -|----------|---------|--------| -| Фильтр каталога только на одной странице, но с хуками и стором | Модуль в `screens/catalog/` с сегментами `hooks/`, `stores/` | Не feature — feature это действие пользователя с бизнес-логикой (авторизация, заказ), а не UI с состоянием | -| Компонент используется в 2 местах на одной странице | Остаётся в `screens/{name}/ui/` | Переиспользование внутри одного screen — не повод выносить в widget | -| Entity без UI (только типы и хук) | Нормально | Модуль не обязан иметь UI. `entities/session/` с типами и хуком — валидный модуль | -| Компонент нужен и в layout, и в screen | Выносить в `widgets/` или `shared/ui/` | Два разных слоя используют один компонент → переиспользование → подъём | -| Модуль screen содержит бизнес-логику (хуки, стор, сервисы) | Нормально | Это не значит что он должен стать feature. Модуль с логикой внутри screen — обычное дело, пока он не переиспользуется | -| Компонент в `shared/ui/button` хочет использовать `shared/ui/icon` | Разрешено | Shared — исключение: внутренние импорты без ограничений. Это фундамент, его компоненты строятся друг на друге | - -## Запрещено - -- **Не создавать feature без бизнес-логики** — кнопка без состояния и сайд-эффектов это компонент в `ui/`, а не feature -- **Не класть доменные типы в shared** — если тип знает о Product, Disease, User — он живёт в `entities/`, не в `shared/` -- **Не создавать entity или feature как результат «вынесения»** — они создаются осознанно: появилась бизнес-сущность → entity, появилось действие пользователя → feature -- **Не импортировать соседние компоненты в `ui/` (кроме shared)** — если двум компонентам нужен общий код, он поднимается на уровень выше -- **Не хранить в shared «помойку для всего»** — shared содержит переиспользуемые компоненты и утилиты без бизнес-логики, а не код который «непонятно куда положить» - -## Почему так, а не иначе - -### Почему `ui/` а не `modules/` - -Внутри сегмента `ui/` всегда лежат единицы с обязательным UI (компоненты). Название точно отражает содержимое. `modules/` был нейтральнее, но скрывал природу вложенных единиц и создавал путаницу — модуль внутри модуля размывал понятие «модуль как единица слоя». - -### Почему модуль и компонент — разные понятия - -Модуль — единица первого уровня слоя, может не иметь UI. Компонент — вложенная единица с обязательным UI. Разделение снимает вопрос «а если нет `.tsx` — это всё ещё компонент?» и делает название сегмента `ui/` честным. - -### Почему shared без ограничений на внутренние импорты - -Shared — фундамент. Его компоненты строятся друг на друге: `button` использует `icon`, `carousel` использует `button`. Запрещать это — бороться с реальностью. Поднимать некуда — shared уже нижний слой. - -### Почему нет слоя pages - -Роутинг живёт в `app/` (Next.js App Router). Отдельный слой `pages` конфликтовал бы с файловой структурой Next.js и дублировал ответственность `app/`. - -### Почему компоненты в одном `ui/` не импортируют друг друга (кроме shared) - -Независимые компоненты легко выносить в другой слой при переиспользовании. Если компонент A зависит от соседа B — при подъёме A придётся тянуть B. Это усложняет рефакторинг и нарушает принцип колокации. diff --git a/docs/ru/index.md b/docs/ru/index.md deleted file mode 100644 index 0ead4f8..0000000 --- a/docs/ru/index.md +++ /dev/null @@ -1,60 +0,0 @@ -# NextJS Style Guide - -Правила и стандарты разработки на NextJS и TypeScript: архитектура, типизация, стили, компоненты, API и инфраструктурные разделы. - -## Для ассистентов - -Полная документация в одном MD файле: https://gromlab.ru/docs/nextjs-style-guide/raw/branch/main/generated/ru/RULES.md - -## Структура документации - -### Workflow - -**Что делать и в каком порядке** — пошаговые инструкции. - -| Раздел | Отвечает на вопрос | -|--------|-------------------| -| Начало работы | Что нужно знать перед началом разработки? | -| Создание проекта | Как начать новый проект? | -| Генерация кода | Какие модули должны генерироваться из шаблонов? | -| Добавление страницы | Как добавить новую страницу в проект? | -| Добавление UI-модуля | Как создать компонент, фичу, виджет, сущность или layout? | -| Стилизация | Как стилизовать компоненты в проекте? | -| Получение данных | Как получать данные с сервера? | -| Управление состоянием | Как работать с состоянием? | -| Локализация | Как добавлять переводы и подключать локализацию? | - -### Базовые правила - -**Каким должен быть код** — стандарты, не привязанные к конкретной технологии. - -| Раздел | Отвечает на вопрос | -|--------|-------------------| -| Технологии и библиотеки | Какой стек используем? | -| Архитектура | Как устроены слои FSD, зависимости, публичный API? | -| Стиль кода | Как оформлять код: отступы, кавычки, импорты, early return? | -| Именование | Как называть файлы, переменные, компоненты, хуки? | -| Документирование | Как писать JSDoc: что документировать, а что нет? | -| Типизация | Как типизировать: type vs interface, any/unknown? | - -### Прикладные разделы - -**Как это настроить и использовать** — конфигурация, структура и примеры кода для конкретных областей. - -| Раздел | Отвечает на вопрос | -|--------|-------------------| -| Настройка VS Code | Как настроить редактор для проекта? | -| Структура проекта | Как организованы папки и файлы по FSD? | -| Компоненты | Как устроен компонент: файлы, пропсы, clsx? | -| Page-level компоненты | Как описывать layout, page, loading, error, not-found? | -| Шаблоны и генерация кода | Как работают шаблоны, синтаксис и инструменты генерации? | -| Стили | Как писать CSS: PostCSS Modules, вложенность, медиа, токены? | -| Изображения | _(не заполнен)_ | -| SVG-спрайты | _(не заполнен)_ | -| Видео | _(не заполнен)_ | -| API | _(не заполнен)_ | -| Stores | _(не заполнен)_ | -| Хуки | _(не заполнен)_ | -| Шрифты | _(не заполнен)_ | -| Локализация | _(не заполнен)_ | - diff --git a/docs/ru/workflow.md b/docs/ru/workflow.md deleted file mode 100644 index ff67388..0000000 --- a/docs/ru/workflow.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Workflow ---- - -# Workflow - -Порядок действий при разработке — от создания проекта до реализации фич. - -## Создание проекта - -Инициализация нового проекта из готового шаблона. - -1. Создать проект из шаблона: - ```bash - npx tiged git@gromlab.ru:templates/nextjs.git my-app - cd my-app - npm install - ``` -2. Проект готов к разработке — стек, структура FSD, конфигурация - редактора и шаблоны генерации уже настроены. - -## Генерация кода - -Создание модулей из шаблонов `.templates/` вместо ручного создания файлов. - -1. Определить тип модуля и соответствующий шаблон: - - | Модуль | Слой | Шаблон | - |------------|--------------|-------------| - | Компонент | `shared/ui/` | `component` | - | Фича | `features/` | `feature` | - | Виджет | `widgets/` | `widget` | - | Сущность | `entities/` | `entity` | - | Layout | `layouts/` | `layout` | - | Экран | `screens/` | `screen` | - | Стор | `model/` | `store` | - -2. Сгенерировать модуль из шаблона. -3. Если подходящего шаблона нет — сначала создать шаблон, затем использовать. - -Ручное создание файловой структуры модулей запрещено. - -## Добавление страницы - -Создание нового маршрута: экран + точка входа для роутинга. - -1. Сгенерировать экран из шаблона `screen` в `src/screens/`. -2. Заполнить экран логикой и стилями. -3. Создать `page.tsx` в нужном маршруте `src/app/`. - -`page.tsx` — тонкая обёртка: только `metadata` и рендер экрана. -Логика, стили и хуки размещаются в экране, не в `page.tsx`. - -## Добавление UI-модуля - -Создание компонента, фичи, виджета, сущности или layout. - -1. Сгенерировать модуль из соответствующего шаблона в целевой слой. -2. Заполнить модуль логикой и стилями. -3. Дочерние компоненты — генерировать из шаблона `component` в папку `ui/` - внутри родителя. - -Дочерние компоненты не экспортируются через `index.ts` родителя. - -## Стилизация - -Выбор инструмента стилизации по приоритету. - -1. Использовать Mantine-компоненты и их пропсы. -2. Если Mantine не покрывает — использовать CSS-токены - (`--color-*`, `--space-*`, `--radius-*`). -3. Если нужна кастомная стилизация — PostCSS Modules. - -Инлайн-стили (`style`), магические значения и глобальные стили -вне `app/styles/` запрещены. - -## Получение данных - -*Раздел в разработке* — SWR, генерация API-клиентов, сокеты. - -## Управление состоянием - -*Раздел в разработке* — когда создавать стор, что хранить локально и глобально. - -## Локализация - -*Раздел в разработке* — переводы и i18next. diff --git a/docs/ru/workflow/code-generation.md b/docs/ru/workflow/code-generation.md deleted file mode 100644 index 0c67d74..0000000 --- a/docs/ru/workflow/code-generation.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Генерация кода ---- - -# Генерация кода - -Как создавать модули в проекте с помощью шаблонов — какие модули покрыты генерацией и когда стоит создавать новые шаблоны. - -## Какие модули генерируются из шаблонов - -| Модуль | Слой | Шаблон | -|---|---|---| -| Компонент | `shared/ui/` | `component` | -| Фича | `features/` | `feature` | -| Виджет | `widgets/` | `widget` | -| Сущность | `entities/` | `entity` | -| Layout | `layouts/` | `layout` | -| Экран | `screens/` | `screen` | -| Стор | `model/` | `store` | - -## Что нужно знать - -В проекте принято создавать модули из шаблонов `.templates/`. Шаблоны задают единообразную файловую структуру и сокращают рутину — не нужно вручную создавать папки, файлы типов, стилей и экспорты. - -Если для нужного модуля нет подходящего шаблона — стоит сначала создать шаблон, а затем использовать его. - -## Когда создавать новый шаблон - -- Повторяющаяся структура появляется больше одного раза. -- Существующий шаблон не покрывает нужный тип модуля. - -Инструменты и синтаксис шаблонов — [Шаблоны и генерация кода](/applied/templates-generation). diff --git a/docs/ru/workflow/creating-app.md b/docs/ru/workflow/creating-app.md deleted file mode 100644 index 5c35719..0000000 --- a/docs/ru/workflow/creating-app.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Создание проекта ---- - -# Создание проекта - -Как начать новый проект, соответствующий стандартам этого руководства. - -## Что нужно знать - -Новый проект создаётся из готового шаблона. Шаблон содержит настроенный стек, структуру FSD, конфигурацию редактора и шаблоны генерации кода — проект готов к разработке сразу после установки зависимостей. - -### Создание из шаблона - -```bash -npx tiged git@gromlab.ru:templates/nextjs.git my-app -cd my-app -npm install -``` - -## Что входит в шаблон - -- Next.js + TypeScript (App Router) -- Mantine UI + PostCSS Modules -- Biome (линтинг и форматирование) -- Zustand, SWR -- Структура FSD (`screens/`, `widgets/`, `features/`, `entities/`, `shared/`) -- Шаблоны генерации (`.templates/`) -- Конфигурация VS Code (`.vscode/`) -- CSS-токены (цвета, отступы, радиусы, медиа) -- Open Graph метаданные diff --git a/docs/ru/workflow/creating-components.md b/docs/ru/workflow/creating-components.md deleted file mode 100644 index ff98f95..0000000 --- a/docs/ru/workflow/creating-components.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Добавление UI-модуля ---- - -# Добавление UI-модуля - -Как создать компонент, фичу, виджет, сущность или layout в проекте. - -## Что нужно знать - -Все UI-модули создаются только из шаблонов `.templates/`. Ручное создание файловой структуры запрещено. Если подходящего шаблона нет — сначала создать шаблон в `.templates/`, затем использовать его. - -## Порядок действий - -1. [Сгенерировать](/applied/templates-generation) модуль из соответствующего шаблона в целевой слой. -2. Заполнить модуль логикой и стилями. - -## Дочерние компоненты - -Если модулю нужны внутренние подкомпоненты — [генерировать](/applied/templates-generation) их из шаблона `component` в папку `ui/` внутри родительского модуля. Дочерние компоненты не экспортируются через `index.ts` родителя. - -Правила написания компонентов — [Компоненты](/applied/components). diff --git a/docs/ru/workflow/creating-pages.md b/docs/ru/workflow/creating-pages.md deleted file mode 100644 index 685cde2..0000000 --- a/docs/ru/workflow/creating-pages.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Добавление страницы ---- - -# Добавление страницы - -Как добавить новую страницу в проект по стандартам этого руководства. - -## Что нужно знать - -Страница в проекте — это два файла: экран в `src/screens/` (вся логика, стили, зависимости) и `page.tsx` в `src/app/` (точка входа для роутинга Next.js). Экран генерируется из шаблона, `page.tsx` создаётся вручную. - -## Порядок действий - -1. [Сгенерировать](/applied/templates-generation) экран из шаблона `screen` в папку `src/screens/`. - -2. Заполнить экран логикой и стилями. - -3. Создать `page.tsx` в нужном маршруте `src/app/`. Файл страницы должен быть тонким — только `metadata` и рендер экрана. Никакой логики, стилей и хуков в `page.tsx` не размещается — всё это живёт в экране. - -## Правила - -- Ручное создание файловой структуры экрана запрещено — только [генерация](/applied/templates-generation) из шаблона. -- Логика, стили и зависимости размещаются в экране, не в `page.tsx`. -- Каждая страница содержит `metadata` с `title` и `description`. - -Примеры `page.tsx` и `metadata` — [Page-level компоненты](/applied/page-level). diff --git a/docs/ru/workflow/data-fetching.md b/docs/ru/workflow/data-fetching.md deleted file mode 100644 index 60f95b2..0000000 --- a/docs/ru/workflow/data-fetching.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Получение данных ---- - -# Получение данных - -Как получать данные с сервера — SWR, генерация API-клиентов, сокеты. diff --git a/docs/ru/workflow/localization.md b/docs/ru/workflow/localization.md deleted file mode 100644 index a5d1145..0000000 --- a/docs/ru/workflow/localization.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Локализация ---- - -# Локализация - -Как добавлять переводы и подключать локализацию через i18next. diff --git a/docs/ru/workflow/state-management.md b/docs/ru/workflow/state-management.md deleted file mode 100644 index 8630e62..0000000 --- a/docs/ru/workflow/state-management.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Управление состоянием ---- - -# Управление состоянием - -Как работать с состоянием — когда создавать стор, что хранить локально и глобально. diff --git a/docs/ru/workflow/styling.md b/docs/ru/workflow/styling.md deleted file mode 100644 index 4bf352f..0000000 --- a/docs/ru/workflow/styling.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Стилизация ---- - -# Стилизация - -Как стилизовать компоненты в проекте — приоритет инструментов и правила их применения. - -## Приоритет стилизации - -Основной UI-фреймворк проекта — **Mantine**. При стилизации компонентов придерживаться следующего приоритета: - -1. **Mantine-компоненты и их пропсы** — в первую очередь использовать встроенные возможности Mantine (пропсы, `classNames`, `styles`). -2. **Глобальные CSS-токены** (`--color-*`, `--space-*`, `--radius-*`) — для значений, которые не покрываются Mantine. -3. **PostCSS Modules** — когда Mantine не покрывает задачу и нужна кастомная стилизация. - -## Что запрещено - -- **Инлайн-стили** — использование атрибута `style` в компонентах строго запрещено. -- **Магические значения** — произвольные цвета, отступы и скругления запрещены, использовать токены. -- **Глобальные стили** вне `app/styles/` запрещены. - -Правила написания CSS, вложенность, медиа-запросы и токены — [Стили](/applied/styles). diff --git a/generated/en/RULES.md b/generated/en/RULES.md deleted file mode 100644 index af892fd..0000000 --- a/generated/en/RULES.md +++ /dev/null @@ -1,137 +0,0 @@ - -# NextJS Style Guide - -Rules and standards for NextJS and TypeScript development: architecture, typing, styles, components, API, and infrastructure. - -## Documentation Structure - -### Processes - -**What to do** in a specific situation — step-by-step instructions. - -| Section | Answers the question | -|---------|---------------------| -| Getting Started | What tools to install before starting development? | -| Creating an App | How to create a new project, where to get a template? | -| Creating Pages | How to add a page: routing and screen? | -| Creating Components | How to generate components using templates? | -| Styling | What to use: Mantine, tokens, or PostCSS? | -| Data Fetching | How to fetch data: SWR, codegen, sockets? | -| State Management | When and how to create a store (Zustand)? | -| Localization | How to add translations and work with i18next? | - -### Basic Rules - -**What the code should look like** — standards not tied to a specific technology. - -| Section | Answers the question | -|---------|---------------------| -| Tech Stack | What stack do we use? | -| Architecture | How are FSD layers, dependencies, and public API structured? | -| Code Style | How to format code: indentation, quotes, imports, early return? | -| Naming | How to name files, variables, components, hooks? | -| Documentation | How to write JSDoc: what to document and what not? | -| Typing | How to type: type vs interface, any/unknown? | - -### Applied Sections - -**How a specific area works** — rules, structure, and code examples for specific technologies and tools. - -| Section | Answers the question | -|---------|---------------------| -| Project Structure | How are folders and files organized by FSD? | -| Components | How is a component structured: files, props, clsx? | -| Page-level Components | How to define layout, page, loading, error, not-found? | -| Templates & Code Generation | How do templates work: syntax, variables, modifiers? | -| Styles | How to write CSS: PostCSS Modules, nesting, media, tokens? | -| Images | _(not filled)_ | -| SVG Sprites | _(not filled)_ | -| Video | _(not filled)_ | -| API | _(not filled)_ | -| Stores | _(not filled)_ | -| Hooks | _(not filled)_ | -| Fonts | _(not filled)_ | -| Localization | _(not filled)_ | - -## For Assistants - -Full documentation in a single MD file: https://gromlab.ru/docs/frontend-style-guide/raw/branch/main/generated/en/RULES.md - - -## Tech Stack - -Base technology stack and libraries used in projects. - - -## Naming - -Naming should be predictable, concise, and reflect the meaning of the entity. - - -## Architecture - -Architecture based on FSD (Feature-Sliced Design) and strict module boundaries. - - -## Code Style - -Unified code formatting rules: indentation, line breaks, quotes, import order, and readability. - - -## Documentation - -Documentation should help understand the purpose of an entity, not duplicate its types or obvious details. - - -## Typing - -Typing is required for all public interfaces, functions, and components. - - -## Project Structure - -Base project structure and principles of module organization at folder and file level. - - -## Components - -Rules for creating UI components across all FSD layers. - - -## Page-level Components - -Next.js App Router special files used by the framework by convention: `layout.tsx`, `page.tsx`, `loading.tsx`, `error.tsx`, `not-found.tsx`, `template.tsx`. - - -## Templates & Code Generation - -Template tools, syntax, and examples for code generation. - - -## Styles - -CSS writing rules: PostCSS Modules, nesting, media queries, variables, formatting. - - -## Images - - -## SVG Sprites - - -## Video - - -## API - - -## Stores - - -## Hooks - - -## Fonts - - -## Localization \ No newline at end of file diff --git a/generated/ru/RULES.md b/generated/ru/RULES.md deleted file mode 100644 index 6b4456e..0000000 --- a/generated/ru/RULES.md +++ /dev/null @@ -1,1901 +0,0 @@ - -# NextJS Style Guide - -Правила и стандарты разработки на NextJS и TypeScript: архитектура, типизация, стили, компоненты, API и инфраструктурные разделы. - -## Для ассистентов - -Полная документация в одном MD файле: https://gromlab.ru/docs/nextjs-style-guide/raw/branch/main/generated/ru/RULES.md - -## Структура документации - -### Workflow - -**Что делать и в каком порядке** — пошаговые инструкции. - -| Раздел | Отвечает на вопрос | -|--------|-------------------| -| Начало работы | Что нужно знать перед началом разработки? | -| Создание проекта | Как начать новый проект? | -| Генерация кода | Какие модули должны генерироваться из шаблонов? | -| Добавление страницы | Как добавить новую страницу в проект? | -| Добавление UI-модуля | Как создать компонент, фичу, виджет, сущность или layout? | -| Стилизация | Как стилизовать компоненты в проекте? | -| Получение данных | Как получать данные с сервера? | -| Управление состоянием | Как работать с состоянием? | -| Локализация | Как добавлять переводы и подключать локализацию? | - -### Базовые правила - -**Каким должен быть код** — стандарты, не привязанные к конкретной технологии. - -| Раздел | Отвечает на вопрос | -|--------|-------------------| -| Технологии и библиотеки | Какой стек используем? | -| Архитектура | Как устроены слои FSD, зависимости, публичный API? | -| Стиль кода | Как оформлять код: отступы, кавычки, импорты, early return? | -| Именование | Как называть файлы, переменные, компоненты, хуки? | -| Документирование | Как писать JSDoc: что документировать, а что нет? | -| Типизация | Как типизировать: type vs interface, any/unknown? | - -### Прикладные разделы - -**Как это настроить и использовать** — конфигурация, структура и примеры кода для конкретных областей. - -| Раздел | Отвечает на вопрос | -|--------|-------------------| -| Настройка VS Code | Как настроить редактор для проекта? | -| Структура проекта | Как организованы папки и файлы по FSD? | -| Компоненты | Как устроен компонент: файлы, пропсы, clsx? | -| Page-level компоненты | Как описывать layout, page, loading, error, not-found? | -| Шаблоны и генерация кода | Как работают шаблоны, синтаксис и инструменты генерации? | -| Стили | Как писать CSS: PostCSS Modules, вложенность, медиа, токены? | -| Изображения | _(не заполнен)_ | -| SVG-спрайты | _(не заполнен)_ | -| Видео | _(не заполнен)_ | -| API | _(не заполнен)_ | -| Stores | _(не заполнен)_ | -| Хуки | _(не заполнен)_ | -| Шрифты | _(не заполнен)_ | -| Локализация | _(не заполнен)_ | - - -## Workflow - -Порядок действий при разработке — от создания проекта до реализации фич. - -### Создание проекта - -Инициализация нового проекта из готового шаблона. - -1. Создать проект из шаблона: - ```bash - npx tiged git@gromlab.ru:templates/nextjs.git my-app - cd my-app - npm install - ``` -2. Проект готов к разработке — стек, структура FSD, конфигурация - редактора и шаблоны генерации уже настроены. - -### Генерация кода - -Создание модулей из шаблонов `.templates/` вместо ручного создания файлов. - -1. Определить тип модуля и соответствующий шаблон: - - | Модуль | Слой | Шаблон | - |------------|--------------|-------------| - | Компонент | `shared/ui/` | `component` | - | Фича | `features/` | `feature` | - | Виджет | `widgets/` | `widget` | - | Сущность | `entities/` | `entity` | - | Layout | `layouts/` | `layout` | - | Экран | `screens/` | `screen` | - | Стор | `model/` | `store` | - -2. Сгенерировать модуль из шаблона. -3. Если подходящего шаблона нет — сначала создать шаблон, затем использовать. - -Ручное создание файловой структуры модулей запрещено. - -### Добавление страницы - -Создание нового маршрута: экран + точка входа для роутинга. - -1. Сгенерировать экран из шаблона `screen` в `src/screens/`. -2. Заполнить экран логикой и стилями. -3. Создать `page.tsx` в нужном маршруте `src/app/`. - -`page.tsx` — тонкая обёртка: только `metadata` и рендер экрана. -Логика, стили и хуки размещаются в экране, не в `page.tsx`. - -### Добавление UI-модуля - -Создание компонента, фичи, виджета, сущности или layout. - -1. Сгенерировать модуль из соответствующего шаблона в целевой слой. -2. Заполнить модуль логикой и стилями. -3. Дочерние компоненты — генерировать из шаблона `component` в папку `ui/` - внутри родителя. - -Дочерние компоненты не экспортируются через `index.ts` родителя. - -### Стилизация - -Выбор инструмента стилизации по приоритету. - -1. Использовать Mantine-компоненты и их пропсы. -2. Если Mantine не покрывает — использовать CSS-токены - (`--color-*`, `--space-*`, `--radius-*`). -3. Если нужна кастомная стилизация — PostCSS Modules. - -Инлайн-стили (`style`), магические значения и глобальные стили -вне `app/styles/` запрещены. - -### Получение данных - -*Раздел в разработке* — SWR, генерация API-клиентов, сокеты. - -### Управление состоянием - -*Раздел в разработке* — когда создавать стор, что хранить локально и глобально. - -### Локализация - -*Раздел в разработке* — переводы и i18next. - - -## Технологии и библиотеки - -Этот раздел описывает базовый стек технологий и библиотек, принятый в проекте. - -### Что используем - -#### Стек -- `React` / `TypeScript` — основной стек для UI и приложения. -- `Next.js` — для продуктовых сайтов. - -#### Архитектура -- `FSD (Feature-Sliced Design)` — структура проекта и границы модулей. Используется кастомизированная версия — подробнее в разделе [Архитектура](/basics/architecture). - -#### UI компоненты -- `Mantine UI` — базовые UI-компоненты. - -#### Работа с данными (API) -- `@gromlab/api-codegen` — генерация API‑клиентов и типов. -- `SWR` — получение, кеширование, ревалидация, дедубликация. -- `SWR (useSWRSubscription)` — сокеты, реалтайм подписки. - -#### Store -- `Zustand` — глобальное состояние. - -#### Локализация -- `i18next (i18n)` — локализация всех пользовательских текстов. - -#### Тестирование -- `Vitest` — тестирование. - -#### Стили -- `PostCSS Modules` — изоляция стилей. -- `Mobile First` — подход к адаптивной верстке. -- `clsx` — конкатенация CSS‑классов. - -#### Генерация -- `@gromlab/create` — шаблонизатор для создания слоёв и других файлов из шаблонов. - - -## Именование - -Этот раздел описывает соглашения об именовании в проекте. Единые правила делают код предсказуемым и упрощают навигацию по проекту. - -### Базовые правила - -| Что | Рекомендуется | -| ---------------- | ---------------------- | -| Папки | `kebab-case` | -| Файлы | `kebab-case` | -| Переменные | `camelCase` | -| Константы | `SCREAMING_SNAKE_CASE` | -| Классы | `PascalCase` | -| React-компоненты | `PascalCase` | -| Хуки | `useSomething` | -| CSS классы | `camelCase` | -| Ключи enum | `SCREAMING_SNAKE_CASE` | - - -### Именование файлов - -Суффикс обозначает роль или тип файла. Пишется в единственном числе. -Формат: `name..ts`. - -**Хуки** -- `use-name.hook.ts` — файл хука, функция именуется `useName` - -**Логика** -- `.store.ts` — стор -- `.service.ts` — сервис - -**Типы и контракты** -- `.type.ts` — типы и интерфейсы -- `.interface.ts` — интерфейсы -- `.enum.ts` — enum -- `.dto.ts` — внешние DTO -- `.schema.ts` — схемы валидации -- `.constant.ts` — константы -- `.config.ts` — конфигурация - -**Утилиты** -- `.util.ts` — утилиты -- `.helper.ts` — вспомогательные функции -- `.lib.ts` — библиотечный код - -**Тесты** -- `.test.ts` — тесты -- `.mock.ts` — моки - -**Хорошо** -```text -features/ -└── auth-by-email/ - ├── ui/ - │ └── login-form.tsx - ├── hooks/ - │ └── use-auth.hook.ts - ├── stores/ - │ └── auth.store.ts - ├── types/ - │ └── auth.interface.ts - ├── auth-by-email.feature.tsx - └── index.ts -``` - -**Плохо** -```text -features/ -└── authByEmail/ - ├── LoginForm.tsx - ├── useAuth.ts - ├── authStore.ts - └── index.ts -``` - -### Булевы значения - -- Использовать префиксы `is`, `has`, `can`, `should`. - -**Хорошо** -```ts -const isReady = true; -const hasAccess = false; -const canSubmit = true; -const shouldRedirect = false; -``` - -**Плохо** -```ts -// Плохо: неясное булево значение без префикса. -const ready = true; -const access = false; -const submit = true; -``` - -### События и обработчики - -- Обработчики начинать с `handle`. -- События и колбэки начинать с `on`. - -**Хорошо** -```ts -const handleSubmit = () => { ... }; -const onSubmit = () => { ... }; -``` - -**Плохо** -```ts -// Плохо: неочевидное назначение имени. -const submitClick = () => { ... }; -``` - -### Коллекции - -- Для массивов использовать имена во множественном числе. -- Для словарей/мап — использовать суффиксы `ById`, `Map`, `Dict`. - -**Хорошо** -```ts -const users = []; -const usersById = {} as Record; -const userIds = ['u1', 'u2']; -const ordersMap = new Map(); -const featureFlagsDict = { beta: true, legacy: false } as Record; -``` - -**Плохо** -```ts -// Плохо: имя не отражает, что это коллекция. -const user = []; -// Плохо: словарь назван как массив. -const usersMap = []; -// Плохо: по имени непонятно, что это словарь. -const users = {} as Record; -``` - - -## Архитектура - -Раздел описывает архитектуру проекта: из каких слоёв состоит приложение, -как организован код внутри слоёв и какие правила управляют зависимостями. - -### Что нужно знать - -SLM Design (Scoped Layered Module Design) — архитектурный подход -к проектированию фронтенд-приложений, предложенный Громовым Сергеем в 2026 г. - -Вырос на основе: - -- [Feature-Sliced Design](https://feature-sliced.design) — слои и направление зависимостей -- Screaming Architecture — структура говорит сама за себя -- Colocation Principle — код рядом с местом использования - -Переосмыслив эти подходы, SLM Design отличается от FSD в трёх аспектах: -где живёт код (колокация), как он организован (модули) -и как масштабируется (подъём при переиспользовании). - -### Терминология - -Архитектура оперирует четырьмя ключевыми понятиями: - -- **Слой** — содержит модули -- **Модуль** — содержит сегменты -- **Компонент** — содержит сегменты -- **Сегмент** — папка внутри модуля или компонента, группирующая код по назначению: UI-элементы (`ui/`), хуки (`hooks/`), типы (`types/`), стили (`styles/`) и другие - -Модуль и компонент устроены одинаково — оба имеют сегменты. Разница в том, где они живут и обязателен ли UI. - -```text -Слой -└── Модуль - ├── Сегменты (hooks/, stores/, types/, styles/, lib/...) - └── ui/ - └── Компонент - ├── Сегменты (hooks/, stores/, types/, styles/, lib/...) - └── ui/ - └── Компонент → ... -``` - -#### Слой - -Архитектурный уровень. Содержит только модули. Определяет назначение кода и правила зависимостей. - -#### Модуль - -Единица первого уровня слоя, объединённая по смыслу. Может содержать компонент, логику, типы, стили — или любую комбинацию. Имеет публичный API (`index.ts`) и внутреннюю структуру из сегментов. - -Модуль — не обязательно UI. Feature `analytics` может быть только стором и сервисом. Entity `session` может быть только типами и хуком. - -Модуль не может содержать вложенных модулей. Вложенные единицы с UI размещаются в сегменте `ui/` как компоненты. - -#### Компонент - -Вложенная единица внутри сегмента `ui/` модуля (или другого компонента). Публичный `.tsx` файл обязателен. Именуется без суффикса слоя. - -Компонент может иметь собственные сегменты (`hooks/`, `styles/`, `types/` и т.д.), `index.ts` и свой `ui/` с ещё более вложенными компонентами. - -Отличия от модуля: - -| | Модуль | Компонент | -|--|--------|-----------| -| Где живёт | В корне слоя | В `ui/` модуля или другого компонента | -| Публичный `.tsx` | С суффиксом слоя, опционален | Без суффикса, обязателен | -| Может не иметь UI | Да | Нет | - -Пример: - -```text -features/auth-by-email/ # модуль -├── auth-by-email.feature.tsx # публичный .tsx модуля (с суффиксом, опционален) -├── ui/ # сегмент: компоненты -│ ├── login-form/ # компонент -│ │ ├── login-form.tsx # публичный .tsx компонента (без суффикса, обязателен) -│ │ ├── ui/ # вложенные компоненты -│ │ │ └── password-field/ -│ │ │ └── password-field.tsx -│ │ ├── hooks/ -│ │ │ └── use-validation.hook.ts -│ │ ├── styles/ -│ │ │ └── login-form.module.css -│ │ └── index.ts -│ └── reset-password/ # компонент -│ ├── reset-password.tsx -│ └── index.ts -├── hooks/ -│ └── use-auth.hook.ts -├── stores/ -│ └── auth.store.ts -└── index.ts -``` - -#### Сегмент - -Техническая папка внутри модуля или компонента, группирующая код по назначению. Набор не фиксирован — включаются только те сегменты, которые нужны. - -| Сегмент | Назначение | -|---------|-----------| -| `ui/` | Вложенные компоненты | -| `hooks/` | React-хуки | -| `stores/` | Сторы состояния | -| `types/` | Интерфейсы, типы, enums, DTO | -| `styles/` | Стили | -| `lib/` | Утилиты | -| `services/` | Внешние источники данных | -| `helpers/` | Вспомогательные функции | -| `config/` | Константы, конфигурация | - -### Ключевой принцип - -> Модуль живёт на самом низком уровне, где он используется. -> Поднимается выше только при переиспользовании в 2+ местах. - -Если модуль используется только в одном месте — он остаётся на текущем уровне. -Как только он начинает использоваться в 2+ местах — выносится на уровень выше. -В крайнем случае — в `shared/`, где он доступен всем. - -### Слои - -Каждый нижний слой не знает о существовании верхних. Импорты идут строго сверху вниз. - -``` -app → layouts → screens → widgets → features → entities → shared -``` - -| Слой | Что лежит | Импортирует | -|------|-----------|-------------| -| **App** | Роутинг, провайдеры, глобальные стили. Композиция layout + screen для маршрута. | Все слои ниже | -| **Layouts** | Каркас страницы, общий для группы маршрутов. | widgets, features, entities, shared | -| **Screens** | Контент конкретной страницы. | widgets, features, entities, shared | -| **Widgets** | Составные блоки с данными/логикой, переиспользуемые в 2+ местах. | features, entities, shared | -| **Features** | Пользовательское действие или интерактивный сценарий. | entities, shared | -| **Entities** | Бизнес-сущность с отображением и типами. | shared | -| **Shared** | Переиспользуемые компоненты, утилиты, стили без бизнес-логики. | ничего | - -Принципы: - -- Импорты строго сверху вниз -- Модули одного слоя не знают друг о друге -- Layout получает контекстно-зависимые блоки через пропсы от app, а не импортирует их сам -- `entities/` и `features/` создаются осознанно — это не результат «вынесения» компонента из screen - -#### App - -Точка входа приложения: роутинг (Next.js App Router), провайдеры, глобальные стили. -Находится на самом высоком уровне абстракции — может импортировать любой слой ниже. -Никакой бизнес-логики — только композиция. - -```text -app/ -├── layout.tsx # RootLayout: провайдеры, глобальные стили -├── page.tsx # Главная: MainLayout + HomeScreen -├── knv-new/ -│ └── page.tsx # КНВ: MainLayout + KnvScreen -└── catalog/ - └── page.tsx # Каталог: MainLayout + CatalogScreen -``` - -```tsx -// app/knv-new/page.tsx -import { MainLayout } from '@/layouts/main' -import { KnvScreen } from '@/screens/knv' - -export default function KnvNewPage() { - return ( - - - - ) -} -``` - -Если layout требует разный контент в зависимости от страницы — app передаёт его через пропсы: - -```tsx -// app/knv-new/page.tsx -import { MainLayout } from '@/layouts/main' -import { KnvScreen } from '@/screens/knv' -import { KnvHeader } from '@/widgets/knv-header' - -export default function KnvNewPage() { - return ( - }> - - - ) -} -``` - -#### Layouts - -Каркас страницы — общие элементы, одинаковые для группы маршрутов (header, footer, sidebar). - -Если компонент внутри layout начинает использоваться в 2+ местах — он выносится в `widgets/` или `shared/ui/`. - -```text -src/layouts/ -└── main/ - ├── main.layout.tsx - ├── ui/ - │ ├── header/ - │ │ └── header.tsx - │ └── footer/ - │ └── footer.tsx - └── index.ts -``` - -#### Screens - -Контент конкретной страницы. Собирает локальные секции и переиспользуемые модули из нижних слоёв. - -Если компонент внутри screen начинает использоваться в 2+ местах — он выносится в `widgets/` или `shared/ui/`. - -```text -src/screens/ -└── knv/ - ├── knv.screen.tsx - ├── ui/ - │ ├── hero-section/ - │ │ └── hero-section.tsx - │ ├── products-section/ - │ │ └── products-section.tsx - │ └── diseases-section/ - │ └── diseases-section.tsx - └── index.ts -``` - -#### Widgets - -Составные блоки с данными и логикой, переиспользуемые в 2+ местах. - -Если блок с логикой нужен только в одном месте — это компонент внутри `screens/{name}/ui/` или `layouts/{name}/ui/`, а не widget. - -```text -src/widgets/ -└── popular-products-slider/ - ├── popular-products-slider.widget.tsx - ├── ui/ - │ └── slider-card/ - │ └── slider-card.tsx - ├── hooks/ - │ └── use-products.hook.ts - └── index.ts -``` - -#### Features - -Пользовательское действие или интерактивный сценарий: авторизация, заказ, добавление в корзину. - -Feature создаётся осознанно, когда есть действие пользователя с бизнес-логикой. Компонент опционален — feature может экспортировать хуки, сторы, компоненты или всё вместе. - -```text -src/features/ -└── auth-by-email/ - ├── auth-by-email.feature.tsx - ├── ui/ - │ ├── login-form/ - │ │ └── login-form.tsx - │ └── reset-password/ - │ └── reset-password.tsx - ├── hooks/ - │ └── use-auth.hook.ts - ├── stores/ - │ └── auth.store.ts - └── index.ts -``` - -#### Entities - -Бизнес-сущность с отображением и типами: препарат, заболевание, врач, пользователь. - -Entity создаётся осознанно, когда появляется бизнес-сущность. Компонент опционален — entity может быть только типами и хуком. - -Отличие от `shared/ui/`: entity-компонент знает о бизнес-домене (принимает `Product`, а не абстрактные пропсы). - -```text -src/entities/ -├── product/ -│ ├── product.entity.tsx -│ ├── ui/ -│ │ └── product-card/ -│ │ └── product-card.tsx -│ ├── types/ -│ │ └── product.type.ts -│ └── index.ts -│ -├── session/ -│ ├── types/ -│ │ └── session.type.ts -│ ├── hooks/ -│ │ └── use-session.hook.ts -│ └── index.ts -``` - -#### Shared - -Переиспользуемые компоненты, утилиты, стили без бизнес-логики. Не знает о бизнес-домене — работает с абстрактными данными. - -Структурирован как набор сегментов: - -```text -src/shared/ -├── ui/ -│ ├── icon/ -│ │ └── icon.tsx -│ ├── carousel/ -│ │ ├── carousel.tsx -│ │ ├── ui/ -│ │ │ ├── carousel-slide/ -│ │ │ │ └── carousel-slide.tsx -│ │ │ └── carousel-dots/ -│ │ │ └── carousel-dots.tsx -│ │ └── index.ts -│ ├── container/ -│ └── button/ -├── lib/ -│ ├── format-date.ts -│ └── cn.ts -├── styles/ -│ ├── variables.css -│ └── media.css -└── sprites/ -``` - -### Модуль - -#### Структура - -```text -{name}/ -├── {name}.{суффикс}.tsx # компонент (опционален) -├── ui/ # вложенные компоненты -├── hooks/ # хуки -├── stores/ # сторы -├── types/ # типы, интерфейсы, enums -├── styles/ # стили -├── lib/ # утилиты -├── services/ # внешние источники данных -├── helpers/ # вспомогательные функции -├── config/ # константы, конфигурация -└── index.ts # публичный API -``` - -#### Именование компонента - -Суффикс слоя получают **только модули первого уровня слоя** — те, что лежат непосредственно в корне слоя. Все компоненты (в `ui/`, любой глубины) именуются без суффикса. Без исключений. - -| Слой | Суффикс | Пример | -|------|---------|--------| -| Layouts | `.layout.tsx` | `main.layout.tsx` | -| Screens | `.screen.tsx` | `knv.screen.tsx` | -| Widgets | `.widget.tsx` | `popular-products-slider.widget.tsx` | -| Features | `.feature.tsx` | `auth-by-email.feature.tsx` | -| Entities | `.entity.tsx` | `product.entity.tsx` | - -Примеры: - -```text -features/auth-by-email/auth-by-email.feature.tsx # модуль первого уровня → суффикс -features/auth-by-email/ui/login-form/login-form.tsx # компонент в ui/ → без суффикса -shared/ui/carousel/carousel.tsx # компонент в shared → без суффикса -``` - -#### Правила импорта - -Три уровня правил: - -**Между слоями** — импорты строго сверху вниз: - -``` -app → layouts → screens → widgets → features → entities → shared -``` - -**Внутри модуля (не shared)** — сегменты доступны друг другу и компонентам. Компоненты внутри одного `ui/` не импортируют друг друга: - -```text -features/auth-by-email/ -├── ui/ -│ ├── login-form/ # НЕ может импортировать reset-password -│ └── reset-password/ # НЕ может импортировать login-form -``` - -Если двум компонентам нужен общий код — он поднимается на уровень выше: - -```text -features/auth/ui/login-form/ui/email-input/ # нужен соседу -→ features/auth/ui/email-input/ # поднимаем на уровень -→ shared/ui/email-input/ # если нужен за пределами фичи -``` - -Компоненты наследуют правила зависимостей **родительского слоя**: - -- Компонент внутри `features/auth/ui/login-form/` может импортировать `entities/` и `shared/` — как и сам feature -- Компонент внутри `widgets/hero/ui/hero-stats/` может импортировать `features/`, `entities/`, `shared/` — как и сам widget - -**Shared** — без ограничений на внутренние импорты. Компоненты в `shared/ui/` могут импортировать друг друга (`button` использует `icon`), `ui/` может использовать `lib/` и другие сегменты. Shared — фундамент, его компоненты строятся друг на друге. - -Правила импорта между слоями enforceable через ESLint — настройка границ слоёв и запрет обратных зависимостей. - -### Жизненный цикл модуля - -Модуль не проектируется «на вырост». Он рождается на самом низком уровне -и поднимается только когда появляется реальная потребность. - -Пример пути компонента `product-card`: - -1. **Начало:** `screens/catalog/ui/product-card/` — нужен только на странице каталога. -2. **Переиспользование:** появился на странице поиска — выносим выше. - Куда именно зависит от природы: - - Составной блок с данными и логикой → `widgets/product-card/` - - Представление бизнес-сущности → `entities/product/ui/product-card/` - - Абстрактный UI без бизнес-логики → `shared/ui/product-card/` - -Основной триггер подъёма — переиспользование в 2+ местах. -Но если очевидно что модуль будет переиспользоваться — разумно разместить его на нужном уровне сразу. - -Как происходит подъём на практике: - -1. Разработчик обнаруживает что компонент нужен в другом месте -2. Определяет целевой слой по природе компонента (widget / entity / shared) -3. Перемещает папку, обновляет импорты, добавляет суффикс если это модуль первого уровня слоя -4. Ревью подтверждает что подъём обоснован - -Подъём — это обычный рефакторинг в рамках задачи, а не отдельная активность. - -### Граничные случаи - -| Ситуация | Решение | Почему | -|----------|---------|--------| -| Фильтр каталога только на одной странице, но с хуками и стором | Модуль в `screens/catalog/` с сегментами `hooks/`, `stores/` | Не feature — feature это действие пользователя с бизнес-логикой (авторизация, заказ), а не UI с состоянием | -| Компонент используется в 2 местах на одной странице | Остаётся в `screens/{name}/ui/` | Переиспользование внутри одного screen — не повод выносить в widget | -| Entity без UI (только типы и хук) | Нормально | Модуль не обязан иметь UI. `entities/session/` с типами и хуком — валидный модуль | -| Компонент нужен и в layout, и в screen | Выносить в `widgets/` или `shared/ui/` | Два разных слоя используют один компонент → переиспользование → подъём | -| Модуль screen содержит бизнес-логику (хуки, стор, сервисы) | Нормально | Это не значит что он должен стать feature. Модуль с логикой внутри screen — обычное дело, пока он не переиспользуется | -| Компонент в `shared/ui/button` хочет использовать `shared/ui/icon` | Разрешено | Shared — исключение: внутренние импорты без ограничений. Это фундамент, его компоненты строятся друг на друге | - -### Запрещено - -- **Не создавать feature без бизнес-логики** — кнопка без состояния и сайд-эффектов это компонент в `ui/`, а не feature -- **Не класть доменные типы в shared** — если тип знает о Product, Disease, User — он живёт в `entities/`, не в `shared/` -- **Не создавать entity или feature как результат «вынесения»** — они создаются осознанно: появилась бизнес-сущность → entity, появилось действие пользователя → feature -- **Не импортировать соседние компоненты в `ui/` (кроме shared)** — если двум компонентам нужен общий код, он поднимается на уровень выше -- **Не хранить в shared «помойку для всего»** — shared содержит переиспользуемые компоненты и утилиты без бизнес-логики, а не код который «непонятно куда положить» - -### Почему так, а не иначе - -#### Почему `ui/` а не `modules/` - -Внутри сегмента `ui/` всегда лежат единицы с обязательным UI (компоненты). Название точно отражает содержимое. `modules/` был нейтральнее, но скрывал природу вложенных единиц и создавал путаницу — модуль внутри модуля размывал понятие «модуль как единица слоя». - -#### Почему модуль и компонент — разные понятия - -Модуль — единица первого уровня слоя, может не иметь UI. Компонент — вложенная единица с обязательным UI. Разделение снимает вопрос «а если нет `.tsx` — это всё ещё компонент?» и делает название сегмента `ui/` честным. - -#### Почему shared без ограничений на внутренние импорты - -Shared — фундамент. Его компоненты строятся друг на друге: `button` использует `icon`, `carousel` использует `button`. Запрещать это — бороться с реальностью. Поднимать некуда — shared уже нижний слой. - -#### Почему нет слоя pages - -Роутинг живёт в `app/` (Next.js App Router). Отдельный слой `pages` конфликтовал бы с файловой структурой Next.js и дублировал ответственность `app/`. - -#### Почему компоненты в одном `ui/` не импортируют друг друга (кроме shared) - -Независимые компоненты легко выносить в другой слой при переиспользовании. Если компонент A зависит от соседа B — при подъёме A придётся тянуть B. Это усложняет рефакторинг и нарушает принцип колокации. - - -## Стиль кода - -Раздел описывает единые правила оформления кода: отступы, переносы, кавычки, порядок импортов и базовую читаемость. - -### Отступы - -- 2 пробела (не табы). - -### Длина строк - -- Ориентироваться на 100 символов, но превышение допустимо, если строка читается легко. -- Переносить выражение на новые строки, когда строка становится плохо читаемой. -- Не переносить строку внутри строковых литералов без необходимости. - -**Хорошо** -```ts -const config = createRequestConfig( - endpoint, - { - headers: { - 'X-Request-Id': requestId, - 'X-User-Id': userId, - }, - params: { - page, - pageSize, - sort: 'createdAt', - }, - }, - timeoutMs, -); -``` - -**Плохо** -```ts -// Плохо: длинная строка с вложенными структурами плохо читается. -const config = createRequestConfig(endpoint, { headers: { 'X-Request-Id': requestId, 'X-User-Id': userId }, params: { page, pageSize, sort: 'createdAt' } }, timeoutMs); -``` - -### Кавычки - -- В JavaScript/TypeScript использовать одинарные кавычки. -- В JSX/TSX для атрибутов использовать двойные кавычки. -- Шаблонные строки использовать только при интерполяции или многострочном тексте. - -**Хорошо** -```ts -const label = 'Сохранить'; -const title = `Привет, ${name}`; -``` - -```tsx - -``` - -**Плохо** -```ts -// Плохо: двойные кавычки в TS и конкатенация вместо шаблонной строки. -const label = "Сохранить"; -const title = 'Привет, ' + name; -``` - -```tsx -// Плохо: одинарные кавычки в JSX-атрибутах. - -``` - -### Точки с запятой и запятые - -- Допускаются упущения точки с запятой, если код остаётся читаемым и однозначным. -- В многострочных массивах, объектах и параметрах функции запятая в конце допускается, но не обязательна. - -### Импорты - -- В именованных импортах использовать пробелы внутри фигурных скобок. -- Типы импортировать через `import type`. -- `default` экспорт избегать, использовать именованные. `default` импорт допустим (например, стили CSS Modules, сторонние библиотеки). -- Избегать импорта всего модуля через `*`. - -**Хорошо** -```ts -import { MyComponent } from 'MyComponent'; -import type { User } from '../model/types'; -import styles from './styles/button.module.css'; -``` - -**Плохо** -```ts -// Плохо: отсутствие пробелов в именованном импорте. -import type {User} from '../model/types'; -// Плохо: default экспорт. -export default MyComponent; -``` - -### Ранние возвраты (early return) - -- Использовать ранние возвраты для упрощения чтения. -- Избегать `else` после `return`. - -**Хорошо** -```ts -const getName = (user?: { name: string }) => { - if (!user) { - return 'Гость'; - } - - return user.name; -}; -``` - -**Плохо** -```ts -// Плохо: лишний else после return усложняет чтение. -const getName = (user?: { name: string }) => { - if (user) { - return user.name; - } else { - return 'Гость'; - } -}; -``` - -### Форматирование объектов и массивов - -- В многострочных объектах каждое свойство на новой строке. -- В многострочных массивах каждый элемент на новой строке. -- Объекты и массивы можно писать в одну строку, если длина строки не превышает 100 символов. -- В однострочных объектах и массивах использовать пробелы после запятых. - -**Хорошо** -```ts -const roles = ['admin', 'editor', 'viewer']; -const options = { id: 1, name: 'User' }; - -const config = { - url: '/api/users', - method: 'GET', - params: { page: 1, pageSize: 20 }, -}; -``` - -**Плохо** -```ts -// Плохо: нет пробелов после запятых и объект слишком длинный для одной строки. -const roles = ['admin','editor','viewer']; -const options = { id: 1,name: 'User' }; -const config = { url: '/api/users', method: 'GET', params: { page: 1, pageSize: 20 } }; -``` - - -## Документирование - -Этот раздел описывает правила документирования кода: когда и как писать -комментарии к компонентам, функциям, типам и интерфейсам. - -### Общие правила - -- Документировать публичные функции, компоненты, типы, интерфейсы и enum. -- Не документировать очевидное — если название говорит само за себя, комментарий не нужен. -- Не документировать параметры, возвращаемые значения и типы пропсов — они видны из сигнатуры. -- Описание через пользу и назначение, а не через внутреннюю реализацию. -- Описание завершается точкой. - -### Функции - -Для документирования функций используется шаблон. Описание механики опционально — -добавляется когда логика нетривиальна. - -**Шаблон** -```ts -/** - * <Что делает функция в 1 строке>. - * - * <Опционально: описание сложной механики или важных нюансов>. - */ -``` - -**Хорошо** -```ts -/** - * Форматирует цену с символом валюты. - */ -export const formatPrice = (value: number): string => { ... } - -/** - * Рекурсивно собирает дерево категорий из плоского списка. - * - * Группирует элементы по parentId, начиная с корневых (parentId = null). - * Категории без родителя попадают в корень дерева. - */ -export const buildCategoryTree = (categories: Category[]): CategoryTree[] => { ... } -``` - -**Плохо** -```ts -// Плохо: дублирует сигнатуру. -/** - * @param value - число - * @returns строка с ценой - */ -``` - -### Компоненты - -Компонент описывает своё **назначение** и **сценарии применения** — это помогает понять, когда и где его использовать, без необходимости читать реализацию. - -**Шаблон** -```ts -/** - * <Назначение компонента в 1 строке>. - * - * Используется для: - * - <сценарий 1> - * - <сценарий 2> - * - <сценарий 3> - */ -``` - -**Хорошо** -```tsx -/** - * Контейнер с адаптивной максимальной шириной. - * - * Используется для: - * - обёртки контента страниц с ограничением ширины - * - центрирования блоков в лейауте - */ -export const Container = (props: ContainerProps) => { ... } -``` - -**Плохо** -```tsx -// Плохо: описывает реализацию, а не назначение. -/** - * Рендерит div с className и htmlAttr. - */ - -// Плохо: нет описания вообще. -export const Container = (props: ContainerProps) => { ... } -``` - -### Типы, интерфейсы, enum - -Документируются назначение сущности и каждое её поле. - -**Хорошо** -```ts -/** - * Фильтры списка задач. - */ -export enum TodoFilter { - /** Все задачи. */ - ALL = 'all', - /** Только активные. */ - ACTIVE = 'active', - /** Только завершённые. */ - COMPLETED = 'completed', -} - -/** - * Задача пользователя. - */ -export interface TodoItem { - /** Уникальный идентификатор задачи. */ - id: string; - /** Текст задачи. */ - text: string; - /** Статус выполнения. */ - completed: boolean; -} -``` - -**Плохо** -```ts -// Плохо: описывает очевидное. -export interface TodoItem { - /** id — это id */ - id: string; -} -``` - - -## Типизация - -Этот раздел описывает правила типизации: как типизировать компоненты, функции и работу с `any`/`unknown`. - -### Общие правила - -- Указывать типы для параметров компонентов, возвращаемых значений и параметров функций. -- Предпочитать `type` для описания сущностей и `interface` для расширяемых контрактов. -- Избегать `any` и `unknown` без необходимости. -- Не использовать `ts-ignore`, кроме крайних случаев с явным комментарием причины. - -### Функции - -- Для публичных функций указывать возвращаемый тип. -- Не полагаться на неявный вывод для важных API. - -**Хорошо** -```ts -export const formatPrice = (value: number): string => { - return `${value} ₽`; -}; -``` - -**Плохо** -```ts -// Плохо: нет явного возвращаемого типа. -export const formatPrice = (value: number) => { - return `${value} ₽`; -}; -``` - -### Работа с any/unknown - -- `any` использовать только для временных заглушек. -- `unknown` сужать через проверки перед использованием. - -**Хорошо** -```ts -const parse = (value: unknown): string => { - if (typeof value === 'string') { - return value; - } - - return ''; -}; -``` - -**Плохо** -```ts -// Плохо: any отключает проверку типов. -const parse = (value: any) => value; -``` - - -## Структура проекта - -Раздел описывает расположение файлов и папок в проекте Next.js (App Router). - -### Корень репозитория - -```text -project-root/ -├── .templates/ # Шаблоны для генерации модулей -├── .vscode/ # Настройки и рекомендуемые расширения VS Code -├── public/ # Статика, доступная по прямому URL -├── src/ # Исходный код приложения -├── .env.example # Переменные окружения проекта (шаблон) -├── .env # Переменные окружения проекта (не коммитить) -├── .gitignore -├── AGENTS.md # Инструкции для AI-агентов -├── biome.json # Линтер и форматтер (вместо ESLint + Prettier) -├── next.config.ts # Конфигурация Next.js -├── package.json # Зависимости и скрипты -├── postcss.config.mjs # Конфигурация PostCSS -└── tsconfig.json # Конфигурация TypeScript -``` - -### Папка `public/` - -Хранит статические файлы, которые отдаются по прямому URL без обработки сборщиком: - -```text -public/ -└── og-image.png -``` - -Компоненты, стили и другой исходный код здесь не размещаются. - -### Папка `src/` - -```text -src/ -├── app/ # Роутинг Next.js, провайдеры, глобальные стили -├── screens/ # Собраные страницы (UI) -├── layouts/ # Шаблоны -├── widgets/ # Крупные самостоятельные блоки интерфейса -├── features/ # Пользовательские сценарии -├── entities/ # Бизнес-сущности -└── shared/ # Переиспользуемый код (UI, утилиты, типы и др.) -``` - -Принципы организации слоёв описаны в разделе [Архитектура](../basics/architecture). - -#### Папка `app/` - -Совмещает два слоя: инициализацию приложения по FSD (провайдеры, глобальные стили) и файловый роутинг Next.js (`layout.tsx`, `page.tsx`, route-сегменты). - -```text -src/app/ -├── providers/ # Провайдеры приложения -├── styles/ # Глобальные стили -├── layout.tsx # Корневой layout -└── page.tsx # Главная страница -``` - -### Папка `.templates/` - -Содержит шаблоны для генерации кода. Каждый подкаталог — шаблон отдельного типа модуля: - -```text -.templates/ -├── component/ # Шаблон компонента -├── screen/ # Шаблон экрана -├── layout/ # Шаблон layout -├── widget/ # Шаблон виджета -├── feature/ # Шаблон фичи -├── entity/ # Шаблон сущности -└── store/ # Шаблон стора -``` - -Подробнее о генерации описано в разделе [Шаблоны и генерация кода](./templates-generation). - -### Конфигурационные файлы - -| Файл | Назначение | -|---|---| -| `next.config.ts` | Настройки Next.js: редиректы, переменные окружения, webpack | -| `tsconfig.json` | Настройки TypeScript: пути, строгость, таргет | -| `biome.json` | Правила линтера и форматтера Biome | -| `postcss.config.mjs` | Подключение PostCSS-плагинов (CSS Modules, custom media) | -| `package.json` | Зависимости, версии, npm-скрипты | -| `AGENTS.md` | Инструкции для AI-агентов, работающих в проекте | - -### Переменные окружения - -- `.env` — переменные окружения проекта, запрещено коммитить -- `.env.example` — шаблон, коммитится в репозиторий - -Переменные с префиксом `NEXT_PUBLIC_` доступны в клиентском коде. Остальные доступны только на сервере. - - -## Компоненты - -Правила написания React-компонентов: файловая структура модуля, типизация пропсов, документирование и реализация. Раздел охватывает компоненты всех слоёв — от `shared/ui` до `screens`. - -Архитектурные слои и их назначение описаны в разделе [Архитектура](/basics/architecture). - - -### Правила организации - -1. Один компонент — один файл. -2. Компонент не содержит бизнес-логики — логика и сайд-эффекты выносятся в хуки или сторы. -3. Дочерние компоненты размещаются в сегменте `ui/` и подчиняются тем же правилам структуры. -4. Публичный API модуля — только `index.ts`. Прямые импорты внутренних файлов запрещены. - -### Базовая структура компонента - -Минимальный набор файлов: компонент, стили, типы и публичный экспорт. - -```text -container/ -├── styles/ -│ └── container.module.css -├── types/ -│ └── container.type.ts -├── container.tsx -└── index.ts -``` - -### Именования - -- Имя корневого css класса всегда `.root` -- Тип пропсов именуется `{ComponentName}Props`. -- Тип пользовательских параметров именуется `{ComponentName}Params`. - -### Типизация - -Структура типов компонента показана в [примере](#пример). Ниже — обоснования ключевых решений. - -- **`type` вместо `interface`** — гибче для пропсов: поддерживает union, intersection, mapped types. Declaration merging пропсам не нужно. -- **Без `FC`** — неявно добавляет `children`, усложняет дженерики, не даёт преимуществ перед аннотацией параметра. -- **Типы в `types/`, а не в `.tsx`** — предотвращает циклические зависимости (компонент импортирует хук, хук импортирует тип из компонента) и разделяет ответственность: `.tsx` для рендера, `.type.ts` для данных. -- **Без возвращаемого типа** — TypeScript выводит из JSX. Осознанное исключение из [базового правила](/basics/typing). - -### Реализация - -- Пропсы деструктурируются в теле компонента, не в параметрах. -- Порядок: пользовательские → системные (`children`, `className`) → `...htmlAttr`. -- `className` объединяется с корневым классом через `cl()`: `cl(styles.root, className)`. -- `...htmlAttr` прокидывается на корневой элемент. - -### Пример - -`container/types/container.type.ts` - -```ts -import type { HTMLAttributes } from 'react' - -/** - * Параметры компонента Container. - */ -export type ContainerParams = {} - -/** HTML-атрибуты корневого элемента. */ -type RootAttrs = HTMLAttributes - -export type ContainerProps = RootAttrs & ContainerParams -``` - -`container/styles/container.module.css` - -```css -.root { - max-width: var(--content-width); - margin: 0 auto; - padding: 0 var(--spacing-4); -} -``` - -`container/container.tsx` - -```tsx -import cl from 'clsx' -import type { ContainerProps } from './types/container.type' -import styles from './styles/container.module.css' - -/** - * Контейнер с адаптивной максимальной шириной. - * - * Используется для: - * - обёртки контента страниц с ограничением ширины - * - центрирования блоков в лейауте - */ -export const Container = (props: ContainerProps) => { - const { children, className, ...htmlAttr } = props - - return ( -
- {children} -
- ) -} -``` - -`container/index.ts` - -```ts -export { Container } from './container' -``` - - -## Файлы роутинга - -Правила для специальных файлов App Router (`page.tsx`, `layout.tsx`, `error.tsx`, `not-found.tsx` и др.) — чем наш подход отличается от дефолтного. - -### Организация - -- `page.tsx` — тонкий файл: только `metadata` и рендер экрана. Логика, стили и зависимости живут в экране, не в `page.tsx`. -- `error.tsx` и `not-found.tsx` делегируют разметку экранам по тому же принципу. -- `layout.tsx` — точка подключения провайдеров и глобальных стилей. Вёрстка layout-обёрток выносится в слой `layouts/`. -- Стили в файлах роутинга не используются — стилизация только внутри вызываемых компонентов. - -### Реализация - -- Каждый `page.tsx` экспортирует `metadata` с `title` — он подставляется в шаблон корневого layout (`%s | App`). -- Корневой `layout.tsx` задаёт `metadata` с `title.template`, `description`, `metadataBase` и OpenGraph-настройками. - -### Примеры - -`src/app/profile/[id]/page.tsx` - -```tsx -import type { Metadata } from 'next' -import { ProfileScreen } from '@/screens/profile' - -export const metadata: Metadata = { - title: 'Профиль', - description: 'Страница профиля пользователя', -} - -type ProfilePageProps = { - params: Promise<{ id: string }> -} - -export default async function ProfilePage({ params }: ProfilePageProps) { - const { id } = await params - - return -} -``` - -`src/app/error.tsx` - -```tsx -'use client' - -import { ErrorScreen } from '@/screens/error' - -type ErrorPageProps = { - error: Error & { digest?: string } - reset: () => void -} - -const ErrorPage = ({ error, reset }: ErrorPageProps) => { - return -} - -export default ErrorPage -``` - - - -::: v-pre - -## Шаблоны и генерация кода - -Как работают шаблоны, как их создавать, синтаксис переменных и как генерировать код с помощью расширения VS Code и CLI. - -### Структура шаблонов - -Все шаблоны лежат в `.templates/` в корне проекта. Каждая папка — отдельный шаблон. - -```text -.templates/ -├── component/ # шаблон компонента -│ └── {{name.kebabCase}}/ -│ ├── styles/ -│ │ └── {{name.kebabCase}}.module.css -│ ├── types/ -│ │ └── {{name.kebabCase}}.type.ts -│ ├── {{name.kebabCase}}.tsx -│ └── index.ts -└── store/ # шаблон Zustand стора - └── {{name.kebabCase}}/ - ├── {{name.kebabCase}}.store.ts - ├── {{name.kebabCase}}.type.ts - └── index.ts -``` - -### Синтаксис шаблонов - -Переменные работают в именах файлов/папок и внутри файлов. Базовая переменная — `name`. - -```text -{{variable}} -``` - -Модификаторы меняют регистр и формат записи: - -```text -{{name.pascalCase}} → MyButton -{{name.camelCase}} → myButton -{{name.kebabCase}} → my-button -{{name.snakeCase}} → my_button -{{name.screamingSnakeCase}} → MY_BUTTON -``` - -### Как создать новый шаблон - -1. Создать папку в `.templates/` с именем шаблона (например `hook`). -2. Внутри разместить файлы и папки, используя `{{name}}` и модификаторы в именах и содержимом. -3. Шаблон сразу доступен и в расширении VS Code, и в CLI. - -Пример — создание шаблона для хука: - -```text -.templates/ -└── hook/ - └── {{name.kebabCase}}/ - ├── {{name.kebabCase}}.hook.ts - └── index.ts -``` - -```ts -// .templates/hook/{{name.kebabCase}}.hook.ts -export const {{name.camelCase}} = () => { - -} -``` - -```ts -// .templates/hook/index.ts -export { {{name.camelCase}} } from './{{name.kebabCase}}.hook' -``` - -### Примеры шаблонов - -#### Шаблон компонента - -```ts -// .templates/component/index.ts -export { {{name.pascalCase}} } from './{{name.kebabCase}}' -``` - -```ts -// .templates/component/types/{{name.kebabCase}}.type.ts -import type { HTMLAttributes } from 'react' - -/** - * Параметры {{name.pascalCase}}. - */ -export type {{name.pascalCase}}Params = {} - -/** HTML-атрибуты корневого элемента. */ -type RootAttrs = HTMLAttributes - -export type {{name.pascalCase}}Props = RootAttrs & {{name.pascalCase}}Params -``` - -```tsx -// .templates/component/{{name.kebabCase}}.tsx -import cl from 'clsx' -import type { {{name.pascalCase}}Props } from './types/{{name.kebabCase}}.type' -import styles from './styles/{{name.kebabCase}}.module.css' - -/** - * {{name.pascalCase}}. - */ -export const {{name.pascalCase}} = (props: {{name.pascalCase}}Props) => { - const { children, className, ...htmlAttr } = props - - return ( -
- {children} -
- ) -} -``` - -```css -/* .templates/component/styles/{{name.kebabCase}}.module.css */ -.root { - -} -``` - -### Генерация через VS Code - -Template File Generator | gromlab ([Marketplace](https://marketplace.visualstudio.com/items?itemName=gromlab.vscode-templateFileGenerator), [Open VSX](https://open-vsx.org/extension/gromlab/vscode-templateFileGenerator)) — расширение для генерации файлов и папок из шаблонов через интерфейс редактора. - -1. ПКМ на целевой папке в проводнике VS Code. -2. **Generate from template** → выбрать шаблон. -3. Ввести имя (например `button`) — расширение подставит его во все переменные `{{name}}`. - -### Генерация через CLI - -[@gromlab/create](https://www.npmjs.com/package/@gromlab/create) — CLI для генерации из тех же шаблонов. Используется через npx, глобальная установка не требуется. - -```bash -npx @gromlab/create <шаблон> <имя> <путь> -``` - -| Команда | Что создаёт | -|---|---| -| `npx @gromlab/create component button src/shared/ui` | Компонент | -| `npx @gromlab/create feature auth src/features` | Фичу | -| `npx @gromlab/create widget header src/widgets` | Виджет | -| `npx @gromlab/create entity user src/entities` | Сущность | -| `npx @gromlab/create layout admin src/layouts` | Layout | -| `npx @gromlab/create store auth src/shared/model` | Стор | - -::: - - -## Стили - -Раздел описывает правила написания CSS: PostCSS Modules, вложенность, медиа-запросы, переменные, форматирование. - -### Общие правила - -- Только **PostCSS** и **CSS Modules** для кастомной стилизации. -- Подход **Mobile First** — стили пишутся от мобильных к десктопу. -- Именование классов — `camelCase` (`.root`, `.buttonNext`, `.itemTitle`). -- Модификаторы — отдельный класс с `_`, применяется через `&._modifier`. - -**Хорошо** -```css -.submitButton { - padding: 8px 16px; - - &._disabled { - opacity: 0.5; - } -} -``` - -**Плохо** -```css -/* Плохо: kebab-case и вложенный элемент вместо отдельного класса. */ -.submit-button { - padding: 8px 16px; - - &__icon { - margin-right: 8px; - } -} -``` - -### Вложенность - -- Вложенность селекторов запрещена. -- Исключения: - - Псевдоклассы: `&:hover`, `&:active`, `&:focus`, `&:disabled` и т.д. - - Псевдоэлементы: `&::before`, `&::after`. - - Медиа-запросы: `@media`. - - Модификаторы: `&._active`, `&._disabled`. -- Каждый вложенный блок отделяется пустой строкой от предыдущих свойств. - -**Хорошо** -```css -.card { - padding: 16px; - background-color: var(--color-bg); - - &:hover { - background-color: var(--color-bg-hover); - } - - &::after { - content: ''; - display: block; - } - - &._highlighted { - border-color: var(--color-primary); - } - - @media (--md) { - padding: 24px; - } -} - -.cardTitle { - font-size: 16px; - - @media (--md) { - font-size: 20px; - } -} -``` - -**Плохо** -```css -/* Плохо: вложенность селекторов, нет пустых строк между блоками. */ -.card { - padding: 16px; - .cardTitle { - font-size: 16px; - } - &:hover { - background-color: var(--color-bg-hover); - } -} -``` - -### Медиа-запросы - -- Только **Custom Media Queries**: `@media (--md) {}`. -- Запрещены произвольные breakpoints: `@media (min-width: 768px)`. -- `@media` пишется только **внутри** селектора. -- Запрещено писать `@media` на верхнем уровне с селекторами внутри. - -**Хорошо** -```css -.sidebar { - display: none; - - @media (--md) { - display: block; - } -} - -.sidebarTitle { - font-size: 14px; - - @media (--md) { - font-size: 18px; - } -} -``` - -**Плохо** -```css -/* Плохо: @media на верхнем уровне с селекторами внутри. */ -@media (--md) { - .sidebar { - display: block; - } - - .sidebarTitle { - font-size: 18px; - } -} - -/* Плохо: произвольный breakpoint вместо custom media. */ -.sidebar { - @media (min-width: 992px) { - display: block; - } -} -``` - -### CSS-переменные - -- Цвета (`--color-*`), отступы (`--space-*`), скругления (`--radius-*`) определяются в `app/styles/variables.css` через `:root`. -- Файл переменных подключается один раз в корневом layout/entry point — после этого переменные доступны глобально через каскад. -- Не дублировать магические значения в компонентах. - -**Хорошо** -```css -/* app/styles/variables.css */ -:root { - --color-primary: #3b82f6; - --color-bg: #ffffff; - --color-bg-hover: #f5f5f5; - --space-1: 4px; - --space-2: 8px; - --space-3: 12px; - --radius-1: 4px; - --radius-2: 8px; -} -``` - -```css -/* компонент */ -.card { - padding: var(--space-3); - border-radius: var(--radius-2); - background-color: var(--color-bg); -} -``` - -**Плохо** -```css -/* Плохо: магические значения вместо переменных. */ -.card { - padding: 12px; - border-radius: 8px; - background-color: #ffffff; -} -``` - -### Custom Media - -- Breakpoints определяются через Custom Media Queries в `app/styles/media.css`. -- Custom media подключаются глобально через конфиг PostCSS (плагин `postcss-custom-media`) — не импортировать в файлы стилей. - -```css -/* app/styles/media.css */ -@custom-media --sm (min-width: 36em); -@custom-media --md (min-width: 62em); -@custom-media --lg (min-width: 82em); -``` - -### Импорт стилей - -- Стили компонента импортируются только внутри своего компонента. -- Запрещено импортировать стили одного компонента в другой. -- Custom media не импортируются в файлы стилей — они подключаются глобально через конфиг PostCSS. - -### Форматирование - -- Пустая строка между селекторами верхнего уровня. -- Пустая строка перед каждым вложенным блоком (медиа, псевдокласс, модификатор). - -**Хорошо** -```css -.userBar { - display: none; - color: var(--color-text); - - @media (--md) { - display: flex; - } -} - -.userBarButton { - background-color: var(--color-bg); - - &:hover { - background-color: var(--color-bg-hover); - } - - &._active { - background-color: var(--color-primary); - } -} -``` - -**Плохо** -```css -/* Плохо: нет пустых строк между селекторами и вложенными блоками. */ -.userBar { - display: none; - color: var(--color-text); - @media (--md) { - display: flex; - } -} -.userBarButton { - background-color: var(--color-bg); - &:hover { - background-color: var(--color-bg-hover); - } - &._active { - background-color: var(--color-primary); - } -} -``` - -### Единицы измерения - -- `px` — основная единица измерения. -- Остальные (`em`, `rem`, `%`, `vh`/`vw`) — допускаются по необходимости дизайна. - -### Порядок CSS-свойств - -В стилях рекомендуется придерживаться логического порядка свойств: - -1. Позиционирование (`position`, `top`, `left`, `z-index`). -2. Блочная модель (`display`, `width`, `height`, `margin`, `padding`). -3. Оформление (`background`, `border`, `box-shadow`, `border-radius`). -4. Текст (`font`, `color`, `text-align`, `line-height`). -5. Прочее (`transition`, `animation`, `opacity`, `cursor`). - -### Комментарии - -- Желательно не писать комментарии в CSS. -- Исключение — нетривиальные хаки и обходные решения, к которым стоит оставить пояснение. - - -## SVG-спрайты - - -## Настройка VS Code - -Каждый проект содержит папку `.vscode/` с конфигурацией редактора. Это гарантирует, что все участники команды работают с одинаковыми настройками форматирования, линтинга и расширениями. - -### Структура `.vscode/` - -```text -.vscode/ -├── extensions.json # Рекомендуемые расширения -└── settings.json # Настройки редактора для проекта -``` - -Оба файла коммитятся в репозиторий. - -### Расширения - -Файл `.vscode/extensions.json` определяет список расширений, которые VS Code предложит установить при открытии проекта. - -```json -// .vscode/extensions.json -{ - "recommendations": [ - "biomejs.biome", - "MyTemplateGenerator.mytemplategenerator", - "csstools.postcss" - ] -} -``` - -| Расширение | Назначение | -|---|---| -| [Biome](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) | Линтинг и форматирование кода. Заменяет ESLint и Prettier | -| Template File Generator \| gromlab ([Marketplace](https://marketplace.visualstudio.com/items?itemName=gromlab.vscode-templateFileGenerator), [Open VSX](https://open-vsx.org/extension/gromlab/vscode-templateFileGenerator)) | Генерация файлов и папок из шаблонов `.templates/` через контекстное меню | -| [PostCSS Language Support](https://marketplace.visualstudio.com/items?itemName=csstools.postcss) | Подсветка синтаксиса и автодополнение для PostCSS (`@custom-media`, `@nest` и др.) | - -#### Зачем это нужно - -- Новый участник команды получает все нужные расширения одним кликом. -- Нет разночтений: все используют одинаковый форматтер и линтер. -- Расширения привязаны к проекту, а не к конкретному разработчику. - -### Настройки редактора - -Файл `.vscode/settings.json` переопределяет пользовательские настройки VS Code на уровне проекта. - -```json -// .vscode/settings.json -{ - "editor.defaultFormatter": "biomejs.biome", - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.fixAll.biome": "explicit", - "source.organizeImports.biome": "explicit" - }, - "files.associations": { - "*.css": "postcss" - } -} -``` - -#### Разбор настроек - -| Настройка | Значение | Что делает | -|---|---|---| -| `editor.defaultFormatter` | `biomejs.biome` | Biome используется как единственный форматтер для всех файлов | -| `editor.formatOnSave` | `true` | Код автоматически форматируется при каждом сохранении | -| `codeActionsOnSave.source.fixAll.biome` | `explicit` | Biome автоматически применяет безопасные исправления при сохранении | -| `codeActionsOnSave.source.organizeImports.biome` | `explicit` | Импорты сортируются и группируются автоматически при сохранении | -| `files.associations` | `"*.css": "postcss"` | Все CSS-файлы открываются с подсветкой PostCSS вместо стандартного CSS | - -#### Зачем это нужно - -- **Единый стиль кода** -- форматирование происходит автоматически, невозможно закоммитить неформатированный код. -- **Автофикс при сохранении** -- распространённые ошибки линтинга исправляются без ручного вмешательства. -- **Сортировка импортов** -- импорты всегда в одном порядке, без конфликтов при мерже. -- **PostCSS-подсветка** -- кастомные at-правила (`@custom-media`, `@define-mixin`) подсвечиваются корректно, а не как ошибки. - -### Что не должно быть в `.vscode/` - -Не коммитятся файлы, специфичные для конкретного разработчика: - -- **Не коммитить**: отладочные конфигурации с локальными путями, персональные сниппеты, настройки тем оформления. -- **Коммитить**: только `extensions.json` и `settings.json` с общими для команды настройками. \ No newline at end of file diff --git a/package.json b/package.json index 5e00454..0a16148 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "type": "module", "version": "0.0.0", "scripts": { - "docs": "node ./concat-md.js", + "build:ai": "node ./scripts/build-ai.js", "dev": "vitepress dev .", "build": "vitepress build .", "serve": "vitepress serve ." diff --git a/scripts/build-ai.js b/scripts/build-ai.js new file mode 100644 index 0000000..95f5aea --- /dev/null +++ b/scripts/build-ai.js @@ -0,0 +1,88 @@ +import fs from "fs"; +import path from "path"; +import { pathToFileURL } from "url"; + +const SRC_DIR = "./src"; +const DIST_DIR = "./dist/ai"; +const SCRIPTS_DIR = "./scripts"; + +// --------------------------------------------------------------------------- +// Сборка по манифесту +// --------------------------------------------------------------------------- + +async function buildForFramework(framework) { + const manifestPath = path.join(SCRIPTS_DIR, `${framework}.build.js`); + + if (!fs.existsSync(manifestPath)) { + console.error(`Манифест не найден: ${manifestPath}`); + process.exit(1); + } + + const manifest = (await import(pathToFileURL(path.resolve(manifestPath)).href)).default; + const outDir = path.join(DIST_DIR, framework); + + // Очищаем выходную директорию + if (fs.existsSync(outDir)) { + fs.rmSync(outDir, { recursive: true, force: true }); + } + + console.log(`\nСборка: ${manifest.name} (${framework})`); + console.log(`Выход: ${outDir}\n`); + + const errors = []; + let count = 0; + + for (const [destRelative, srcRelative] of Object.entries(manifest.files)) { + const srcPath = path.join(SRC_DIR, srcRelative); + const destPath = path.join(outDir, destRelative); + + if (!fs.existsSync(srcPath)) { + errors.push(` [!] Не найден: ${srcRelative}`); + continue; + } + + fs.mkdirSync(path.dirname(destPath), { recursive: true }); + fs.copyFileSync(srcPath, destPath); + console.log(` ${destRelative}`); + count++; + } + + if (errors.length > 0) { + console.log(`\nОшибки:`); + errors.forEach((e) => console.log(e)); + } + + console.log(`\nГотово: ${outDir} (${count} файлов)`); +} + +// --------------------------------------------------------------------------- +// Определяем что собирать +// --------------------------------------------------------------------------- + +let frameworks = fs + .readdirSync(SCRIPTS_DIR) + .filter((f) => f.endsWith(".build.js")) + .map((f) => f.replace(".build.js", "")); + +if (frameworks.length === 0) { + console.error("Не найдено ни одного манифеста *.build.js в scripts/"); + process.exit(1); +} + +// --framework=nextjs +const fwArg = process.argv.find((a) => a.startsWith("--framework=")); +if (fwArg) { + const fw = fwArg.split("=")[1]; + if (frameworks.includes(fw)) { + frameworks = [fw]; + } else { + console.error(`Фреймворк "${fw}" не найден. Доступные: ${frameworks.join(", ")}`); + process.exit(1); + } +} + +for (const fw of frameworks) { + await buildForFramework(fw); +} + +console.log("\nВсе сборки завершены."); diff --git a/scripts/nextjs.build.js b/scripts/nextjs.build.js new file mode 100644 index 0000000..847c5d2 --- /dev/null +++ b/scripts/nextjs.build.js @@ -0,0 +1,70 @@ +/** + * Манифест сборки стайлгайда для Next.js. + * + * Ключ — путь файла в dist/ai/nextjs/. + * Значение — путь исходника относительно src/. + * + * Скрипт только копирует. Никакой генерации. + */ +export default { + name: "Next.js", + + files: { + // ── Точки входа ───────────────────────────────────────────── + "DEVELOP.md": "nextjs/DEVELOP.md", + + // ── Базовые правила ───────────────────────────────────────── + "basics/architecture.md": "base/basics/architecture.md", + "basics/code-style.md": "base/basics/code-style.md", + "basics/documentation.md": "base/basics/documentation.md", + "basics/getting-started.md": "base/basics/getting-started.md", + "basics/naming.md": "base/basics/naming.md", + "basics/tech-stack.md": "base/basics/tech-stack.md", + "basics/typing.md": "base/basics/typing.md", + + // ── Прикладные разделы ────────────────────────────────────── + "applied/components.md": "base/applied/components.md", + "applied/styles.md": "base/applied/styles.md", + "applied/templates-generation.md": "base/applied/templates-generation.md", + "applied/hooks.md": "base/applied/hooks.md", + "applied/stores.md": "base/applied/stores.md", + "applied/api.md": "base/applied/api.md", + "applied/fonts.md": "base/applied/fonts.md", + "applied/localization.md": "base/applied/localization.md", + "applied/images-sprites.md": "base/applied/images-sprites.md", + "applied/svg-sprites.md": "base/applied/svg-sprites.md", + "applied/video.md": "base/applied/video.md", + "applied/vscode.md": "base/applied/vscode.md", + "applied/page-level.md": "nextjs/applied/page-level.md", + "applied/project-structure.md": "nextjs/applied/project-structure.md", + + // ── Триггеры: разработка / создание ───────────────────────── + "triggers/develop/create-component.md": "base/triggers/develop/create-component.md", + "triggers/develop/create-feature.md": "base/triggers/develop/create-feature.md", + "triggers/develop/create-widget.md": "base/triggers/develop/create-widget.md", + "triggers/develop/create-entity.md": "base/triggers/develop/create-entity.md", + "triggers/develop/create-hook.md": "base/triggers/develop/create-hook.md", + "triggers/develop/create-store.md": "base/triggers/develop/create-store.md", + "triggers/develop/create-page.md": "nextjs/triggers/develop/create-page.md", + "triggers/develop/create-layout.md": "nextjs/triggers/develop/create-layout.md", + "triggers/develop/create-project.md": "nextjs/triggers/develop/create-project.md", + "triggers/develop/generate-module.md": "base/triggers/develop/generate-module.md", + + // ── Триггеры: разработка / стилизация и ресурсы ───────────── + "triggers/develop/style-component.md": "base/triggers/develop/style-component.md", + "triggers/develop/add-icon.md": "base/triggers/develop/add-icon.md", + "triggers/develop/add-image.md": "base/triggers/develop/add-image.md", + "triggers/develop/add-video.md": "base/triggers/develop/add-video.md", + "triggers/develop/add-font.md": "base/triggers/develop/add-font.md", + + // ── Триггеры: разработка / данные и состояние ─────────────── + "triggers/develop/add-api-request.md": "base/triggers/develop/add-api-request.md", + "triggers/develop/connect-store.md": "base/triggers/develop/connect-store.md", + "triggers/develop/add-server-data.md": "nextjs/triggers/develop/add-server-data.md", + + // ── Триггеры: разработка / инфраструктура ─────────────────── + "triggers/develop/add-localization.md": "base/triggers/develop/add-localization.md", + "triggers/develop/add-dependency.md": "base/triggers/develop/add-dependency.md", + "triggers/develop/setup-vscode.md": "base/triggers/develop/setup-vscode.md", + }, +}; diff --git a/src/base/applied/api.md b/src/base/applied/api.md new file mode 100644 index 0000000..aa89beb --- /dev/null +++ b/src/base/applied/api.md @@ -0,0 +1,5 @@ +--- +scope: applied +keywords: [api, запрос, fetch, SWR, эндпоинт, REST, клиент] +when: "Работа с API: запросы, клиенты, обработка ответов" +--- diff --git a/docs/ru/applied/components.md b/src/base/applied/components.md similarity index 88% rename from docs/ru/applied/components.md rename to src/base/applied/components.md index 5ea67fd..64b4372 100644 --- a/docs/ru/applied/components.md +++ b/src/base/applied/components.md @@ -1,7 +1,9 @@ --- title: Компоненты +scope: applied +keywords: [компонент, props, jsx, ui, clsx, cl, React, FC] +when: "Создание или редактирование React-компонентов: структура, пропсы, стили" --- - # Компоненты Правила написания React-компонентов: файловая структура модуля, типизация пропсов, документирование и реализация. Раздел охватывает компоненты всех слоёв — от `shared/ui` до `screens`. @@ -110,3 +112,7 @@ export const Container = (props: ContainerProps) => { ```ts export { Container } from './container' ``` + +## Дочерние компоненты + +Если модулю нужны внутренние подкомпоненты — генерировать их из шаблона `component` в папку `ui/` внутри родительского модуля. Дочерние компоненты не экспортируются через `index.ts` родителя. diff --git a/src/base/applied/fonts.md b/src/base/applied/fonts.md new file mode 100644 index 0000000..aa9baae --- /dev/null +++ b/src/base/applied/fonts.md @@ -0,0 +1,5 @@ +--- +scope: applied +keywords: [шрифт, font, next/font, подключение шрифта, woff] +when: "Подключение и настройка шрифтов" +--- diff --git a/src/base/applied/hooks.md b/src/base/applied/hooks.md new file mode 100644 index 0000000..52f342e --- /dev/null +++ b/src/base/applied/hooks.md @@ -0,0 +1,5 @@ +--- +scope: applied +keywords: [хук, hook, use, кастомный хук, useState, useEffect] +when: "Создание или использование кастомных хуков" +--- diff --git a/src/base/applied/images-sprites.md b/src/base/applied/images-sprites.md new file mode 100644 index 0000000..a5ffc0b --- /dev/null +++ b/src/base/applied/images-sprites.md @@ -0,0 +1,5 @@ +--- +scope: applied +keywords: [изображение, картинка, image, next/image, public, оптимизация] +when: "Работа с изображениями: подключение, оптимизация" +--- diff --git a/src/base/applied/localization.md b/src/base/applied/localization.md new file mode 100644 index 0000000..b03e5f0 --- /dev/null +++ b/src/base/applied/localization.md @@ -0,0 +1,5 @@ +--- +scope: applied +keywords: [i18n, локализация, перевод, язык, i18next, namespace] +when: "Локализация: добавление переводов, работа с i18next" +--- diff --git a/src/base/applied/stores.md b/src/base/applied/stores.md new file mode 100644 index 0000000..a3f3a92 --- /dev/null +++ b/src/base/applied/stores.md @@ -0,0 +1,5 @@ +--- +scope: applied +keywords: [стор, store, zustand, состояние, глобальное состояние] +when: "Работа с глобальным состоянием: создание стора, подписка" +--- diff --git a/docs/ru/applied/styles.md b/src/base/applied/styles.md similarity index 83% rename from docs/ru/applied/styles.md rename to src/base/applied/styles.md index 5ce5cdd..065397d 100644 --- a/docs/ru/applied/styles.md +++ b/src/base/applied/styles.md @@ -1,7 +1,9 @@ --- title: Стили +scope: applied +keywords: [css, postcss, модули, css modules, токены, медиа-запросы, вложенность, класс] +when: "Стилизация: CSS Modules, PostCSS, переменные, медиа-запросы" --- - # Стили Раздел описывает правила написания CSS: PostCSS Modules, вложенность, медиа-запросы, переменные, форматирование. @@ -267,3 +269,17 @@ title: Стили - Желательно не писать комментарии в CSS. - Исключение — нетривиальные хаки и обходные решения, к которым стоит оставить пояснение. + +## Приоритет стилизации + +Основной UI-фреймворк проекта — **Mantine**. При стилизации компонентов придерживаться следующего приоритета: + +1. **Mantine-компоненты и их пропсы** — в первую очередь использовать встроенные возможности Mantine (пропсы, `classNames`, `styles`). +2. **Глобальные CSS-токены** (`--color-*`, `--space-*`, `--radius-*`) — для значений, которые не покрываются Mantine. +3. **PostCSS Modules** — когда Mantine не покрывает задачу и нужна кастомная стилизация. + +## Что запрещено + +- **Инлайн-стили** — использование атрибута `style` в компонентах строго запрещено. +- **Магические значения** — произвольные цвета, отступы и скругления запрещены, использовать токены. +- **Глобальные стили** вне `app/styles/` запрещены. diff --git a/src/base/applied/svg-sprites.md b/src/base/applied/svg-sprites.md new file mode 100644 index 0000000..1d59ecd --- /dev/null +++ b/src/base/applied/svg-sprites.md @@ -0,0 +1,7 @@ +--- +title: SVG-спрайты +scope: applied +keywords: [svg, спрайт, иконка, icon, sprite] +when: "Работа с SVG-иконками и спрайтами" +--- +# SVG-спрайты diff --git a/docs/ru/applied/templates-generation.md b/src/base/applied/templates-generation.md similarity index 85% rename from docs/ru/applied/templates-generation.md rename to src/base/applied/templates-generation.md index 60f4108..fb65619 100644 --- a/docs/ru/applied/templates-generation.md +++ b/src/base/applied/templates-generation.md @@ -1,7 +1,9 @@ --- title: Шаблоны и генерация кода +scope: applied +keywords: [шаблон, генерация, template, scaffold, plop, hygen, .templates] +when: "Генерация кода из шаблонов, создание новых шаблонов" --- - ::: v-pre @@ -154,3 +156,20 @@ npx @gromlab/create <шаблон> <имя> <путь> ::: +## Какие модули генерируются из шаблонов + +| Модуль | Слой | Шаблон | +|---|---|---| +| Компонент | `shared/ui/` | `component` | +| Фича | `features/` | `feature` | +| Виджет | `widgets/` | `widget` | +| Сущность | `entities/` | `entity` | +| Layout | `layouts/` | `layout` | +| Экран | `screens/` | `screen` | +| Стор | `model/` | `store` | + +## Когда создавать новый шаблон + +- Повторяющаяся структура появляется больше одного раза. +- Существующий шаблон не покрывает нужный тип модуля. + diff --git a/src/base/applied/video.md b/src/base/applied/video.md new file mode 100644 index 0000000..b8bd490 --- /dev/null +++ b/src/base/applied/video.md @@ -0,0 +1,5 @@ +--- +scope: applied +keywords: [видео, video, плеер, mp4] +when: "Встраивание и работа с видео" +--- diff --git a/docs/ru/applied/vscode.md b/src/base/applied/vscode.md similarity index 96% rename from docs/ru/applied/vscode.md rename to src/base/applied/vscode.md index f9d7607..5d313fe 100644 --- a/docs/ru/applied/vscode.md +++ b/src/base/applied/vscode.md @@ -1,7 +1,9 @@ --- title: Настройка VS Code +scope: applied +keywords: [vscode, редактор, расширение, настройка, extension, .vscode] +when: "Настройка VS Code: расширения, settings.json, сниппеты" --- - # Настройка VS Code Каждый проект содержит папку `.vscode/` с конфигурацией редактора. Это гарантирует, что все участники команды работают с одинаковыми настройками форматирования, линтинга и расширениями. diff --git a/src/base/basics/architecture.md b/src/base/basics/architecture.md new file mode 100644 index 0000000..64b94f5 --- /dev/null +++ b/src/base/basics/architecture.md @@ -0,0 +1,658 @@ + +# SLM Design +Scoped Layered Module Design — модульная архитектура фронтенд-приложений. Код организован по слоям ответственности, а модуль содержит всё, что ему нужно: компоненты, хуки, сторы, типы, стили. + +## Преимущества + +### Вертикальная организация домена + +Бизнес-домен не разбивается по техническим слоям — сценарии, сущности, типы и UI живут в одном модуле. Это сокращает время навигации и упрощает сопровождение: все изменения домена локализованы. + +### Dependency Injection без фреймворков + +Cross-domain зависимости в бизнес-слое реализуются через фабрики — модуль декларирует что ему нужно, а точка использования предоставляет зависимости. Домены изолированы без DI-контейнеров, провайдеров и шин событий. + +### Разделение ответственности без перегрузки слоёв + +Сервисы приложения (`infrastructure/`), UI-кит (`ui/`) и общие ресурсы (`shared/`) — три разных слоя с разной природой. Ни один слой не превращается в свалку разнородного кода. + +### Горизонтальная инкапсуляция + +Вложенные модули (`parts/`) и направление зависимостей позволяют нескольким разработчикам работать над одной областью приложения параллельно, не затрагивая код друг друга. + +### Колокация по умолчанию + +Код начинает жизнь рядом с местом использования и поднимается в общие слои только при реальной потребности. Глобальные слои не засоряются преждевременными абстракциями. + +### Явное разделение каркаса и контента + +Каркас группы маршрутов (`layouts/`) и контент конкретной страницы (`screens/`) — независимые слои с собственной ответственностью. + +### Масштабирование через группировку + +При росте проекта слои не теряют структуру — модули группируются по естественным признакам: бизнес-домены по субдоменам, страницы по разделам, UI-компоненты по уровню абстракции (примитивы и композиции). + +## Происхождение + +SLM Design вырос на основе: + +- **Feature-Sliced Design** — слоистая структура, публичный API модуля, направление зависимостей +- **Vertical Slice Architecture** — модуль как вертикальный срез, содержащий всё необходимое +- **Screaming Architecture** — структура проекта «кричит» о назначении: открыл `business/auth` — видишь авторизацию +- **Colocation Principle** — код живёт рядом с местом использования + +## Пример структуры проекта + +```text +src/ +├── app/ +│ +├── layouts/ +│ ├── main/ +│ └── dashboard/ +│ +├── screens/ +│ ├── home/ +│ ├── products/ +│ ├── product-detail/ +│ └── about/ +│ +├── widgets/ +│ ├── page-heading/ +│ ├── hero-section/ +│ └── promo-banner/ +│ +├── business/ +│ ├── auth/ +│ ├── catalog/ +│ ├── orders/ +│ └── chat/ +│ +├── infrastructure/ +│ ├── theme/ +│ ├── i18n/ +│ ├── backend-api/ +│ └── logger/ +│ +├── ui/ +│ ├── button/ +│ ├── input/ +│ ├── modal/ +│ ├── toast/ +│ └── dropdown/ +│ +└── shared/ + ├── lib/ + ├── types/ + └── styles/ +``` + +## Принципы + +- **Домен — единое целое.** Всё, что относится к домену, живёт в одном модуле. +- **Колокация.** Код рождается рядом с местом использования и поднимается только при необходимости. +- **Зависимости однонаправлены.** Импорты только сверху вниз, только через публичный API. +- **Архитектура — каркас, не клетка.** Правила фиксируют направление зависимостей и структуру модуля, остальное определяет команда. + + +## Слои + +Раздел описывает слои SLM: что такое слой, какие бывают, как между ними направлены зависимости и какие правила действуют на каждом. + +### Определение + +**Слой — уровень организации кода внутри `src/`. Каждый слой отвечает за свою область (каркас страницы, бизнес-логика, UI-кит) и задаёт правила для кода внутри: направление импортов, именование, допустимые связи между модулями.** + +### Группы слоёв + +Слои делятся на три группы: + +| Группа | Слои | Описание | +|--------|------|----------| +| Композиция | `app`, `layouts`, `screens`, `widgets` | Собирают интерфейс из готовых блоков: маршруты, каркасы, страницы | +| Ядро | `business`, `infrastructure`, `ui` | Реализация продукта: бизнес-домены, техсервисы, UI-кит | +| Фундамент | `shared` | Общие ресурсы: утилиты, хелперы, стили, конфиги | + +### Направление зависимостей + +Любой импорт между модулями — только через публичный API. + +``` +app → [ layouts | screens ] → widgets → business → infrastructure → ui → shared +``` + +- `layouts` и `screens` — параллельные слои, не импортируют друг друга +- Модули одного слоя в группе «Композиция» изолированы друг от друга +- Модули одного слоя `infrastructure` и `ui` могут импортировать друг друга через публичный API +- Модули `business` — cross-domain зависимости по коду через фабрику, `import type` напрямую +- Импорт типов (`import type`) в «Ядре» разрешён в обоих направлениях + + +### Слой App + +Точка входа приложения. Отвечает за запуск, роутинг и композицию маршрутов из layout и screen. + +В отличие от остальных слоёв, `app/` не содержит модулей SLM. Здесь живут только инфраструктурные файлы, которые не могут быть никаким другим слоем: файлы фреймворка роутинга, точка запуска и код инициализации. + +#### Требования + +- Не содержит модулей SLM — только файлы фреймворка, роутинг, инициализация +- Содержит: файлы маршрутов, bootstrap, обработку ошибок верхнего уровня (404, error boundary), подключение глобальных стилей и ассетов +- Провайдеры и гарды — только подключает готовые из нижних слоёв, не реализует +- Не содержит бизнес-логику, UI-компоненты, хуки, сторы, сервисы +- Никем не импортируется + +### Слой Layouts + +Каркас страницы: общие элементы, одинаковые для группы маршрутов (header, footer, sidebar). + +```text +src/layouts/ +├── main/ +├── dashboard/ +└── auth/ +``` + +#### Требования + +- Содержит только модули +- Не содержит бизнес-логику +- Контекстно-зависимые блоки принимает через пропсы от `app`, не импортирует напрямую + +### Слой Screens + +Контент конкретной страницы: собирает её из модулей нижних слоёв. + +```text +src/screens/ +├── home/ +├── products/ +├── product-detail/ +├── about/ +└── contacts/ +``` + +Когда количество страниц затрудняет навигацию — вводится группировка по разделам. Группа — папка для организации, не модуль (без `index.ts`). + +```text +src/screens/ +├── shop/ +│ ├── home/ +│ ├── products/ +│ ├── product-detail/ +│ └── cart/ +├── account/ +│ ├── profile/ +│ ├── settings/ +│ └── order-history/ +└── info/ + ├── about/ + ├── contacts/ + └── faq/ +``` + +#### Требования + +- Содержит только модули +- Не содержит бизнес-логику +- Локальные одноразовые секции живут внутри screen-модуля, не выносятся в `widgets`/`business` + +### Слой Widgets + +Составной блок интерфейса, который компонует модули ядра, но не принадлежит конкретному бизнес-домену. Widget появляется когда блок используется в нескольких screens или layouts. + +Если блок принадлежит домену — он живёт в `business/{area}/`, даже если переиспользуется. Если блок нужен только в одном месте — это `screens/{name}/parts/` или `layouts/{name}/parts/`, а не widget. + +```text +src/widgets/ +├── page-heading/ +├── hero-section/ +├── onboarding-checklist/ +├── promo-banner/ +└── error-boundary/ +``` + +#### Требования + +- Не принадлежит конкретному бизнес-домену. Если блок доменный — он живёт в `business/` +- Используется в нескольких screens или layouts + +### Слой Business + +Бизнес-домены приложения: auth, catalog, orders, checkout, chat. Каждый домен — отдельный модуль со своими типами, логикой, UI и сервисами. + +Слой входит в группу «Ядро». Импортирует `infrastructure/`, `ui/`, `shared/`. Cross-domain зависимости по коду реализуются через фабрику. `import type` между доменами разрешён напрямую. + +Business объединяет то, что в FSD разделено на `features` и `entities`: пользовательские сценарии и бизнес-сущности живут вместе, внутри одного домена. Внутри домена сегменты разделяют ответственность: `types/` — доменная модель, `hooks/` и `services/` — сценарии и логика, `mappers/` — трансформация данных, `parts/` — составные блоки. + +```text +src/business/ +├── auth/ +├── catalog/ +├── orders/ +├── checkout/ +└── chat/ +``` + +Когда количество доменов затрудняет навигацию — вводится группировка по субдоменам. Группа — папка для организации, не модуль (без `index.ts`). + +```text +src/business/ +├── commerce/ +│ ├── catalog/ +│ ├── cart/ +│ ├── orders/ +│ └── checkout/ +└── communication/ + ├── chat/ + └── notifications/ +``` + +#### Требования + +- Один модуль = один бизнес-домен +- Циклические зависимости между доменами запрещены +- Импорт кода между доменами — через фабрику. `import type` — напрямую +- Доменные типы (`User`, `Product`) живут здесь, не в `shared/` + +### Слой Infrastructure + +Техсервисы приложения: theme, i18n, API-адаптеры, logger, realtime. Каждый сервис — отдельный модуль. + +Слой входит в группу «Ядро». Импортирует `infrastructure/`, `ui/`, `shared/`. + +Отличие от `shared/`: infrastructure — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги). + +```text +src/infrastructure/ +├── theme/ +├── i18n/ +├── backend-api/ +├── maps-api/ +├── logger/ +├── feature-flags/ +└── realtime/ +``` + +#### Требования + +- Один модуль = один техсервис +- Импортирует `infrastructure/`, `ui/`, `shared/` + +### Слой UI + +UI-кит без бизнес-логики: button, carousel, toast, modal. + +Слой входит в группу «Ядро». Импортирует `ui/` и `shared/`. + +Компоненты строятся друг на друге: `button` использует `icon`, `carousel` использует `button`. + +```text +src/ui/ +├── button/ +├── input/ +├── icon/ +├── carousel/ +├── modal/ +├── toast/ +├── dropdown/ +├── tabs/ +└── tooltip/ +``` + +Когда количество компонентов затрудняет навигацию — вводится группировка на примитивы и композиции. Примитивы (`button`, `icon`, `input`) не импортируют композиции. Композиции (`carousel`, `modal`, `dropdown`) строятся на примитивах. + +```text +src/ui/ +├── primitives/ +│ ├── button/ +│ ├── input/ +│ ├── icon/ +│ └── badge/ +└── composites/ + ├── carousel/ + ├── modal/ + ├── dropdown/ + ├── tabs/ + └── tooltip/ +``` + +#### Требования + +- Не содержит бизнес-логику +- Импортирует только `ui/` и `shared/` + +### Слой Shared + +Общие ресурсы: утилиты, хелперы, стили, конфиги. Не знает о бизнес-домене. + +Слой входит в группу «Фундамент» — ни о ком не знает, никого не импортирует. + +Отличие от `infrastructure/`: infrastructure — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги). + +Отличие от `ui/`: UI-компоненты (button, carousel, modal) живут в слое `ui/`, а не здесь. + +```text +src/shared/ +├── lib/ +├── types/ +├── styles/ +└── sprites/ +``` + +#### Требования + +- Не имеет runtime-состояния + + +## Модули + +Раздел описывает модули SLM: что такое модуль, из чего он состоит и как взаимодействует с остальным кодом. + +### Определение + +**Модуль — универсальный строительный блок архитектуры. Живёт на слое и содержит всё необходимое для своей работы: компоненты, хуки, сторы, сервисы, типы, стили. Набор содержимого не фиксирован — включаются только нужные части.** + +### Модуль vs компонент + +**Компонент** — один `.tsx` файл. Не имеет своих сегментов, использует сегменты родительского модуля. Живёт в корне или `ui/` сегменте модуля. + +**Модуль** — папка, которая может содержать корневой компонент, сегменты (`hooks/`, `types/`, `styles/`, `ui/`, `parts/` и т.д.) и публичный API (`index.ts`). + +```text +auth/ +├── ui/ +│ ├── auth-guard.tsx +│ └── logout-button.tsx +├── parts/ +│ ├── login-form/ +│ ├── registration-form/ +│ └── restore-form/ +├── hooks/ +├── stores/ +├── types/ +├── auth.tsx # корневой компонент (опционален) +└── index.ts +``` + +### Структура + +Модуль состоит из сегментов. Ни один сегмент не обязателен — модуль может состоять даже из одного `index.ts` с реэкспортом типов. + +```text +{module-name}/ +├── {module-name}.tsx # корневой компонент (опционален) +├── ui/ # компоненты модуля (только .tsx) +├── parts/ # вложенные модули (со своими сегментами) +├── hooks/ # хуки +├── stores/ # сторы состояния +├── services/ # внешние источники данных +├── mappers/ # трансформация данных между форматами +├── types/ # типы +├── styles/ # стили +├── lib/ # утилиты модуля +├── config/ # константы +└── index.ts # публичный API +``` + +Подробное описание каждого сегмента — в разделе [Сегменты](/reference/segments). + +### Публичный API + +Модуль экспортирует наружу только то, что нужно другим. Всё остальное — внутреннее. + +```ts +// business/auth/index.ts +export type { User, Session } from './types/user.types' +export { useAuth } from './hooks/use-auth.hook' +export { AuthGuard } from './ui/auth-guard' +``` + +Импорт в обход `index.ts` запрещён: + +```ts +// Плохо +import { validateToken } from '@/business/auth/lib/tokens' + +// Хорошо +import { useAuth } from '@/business/auth' +``` + +### Фабрика + +Если модуль зависит от кода другого бизнес-домена — он экспортирует фабрику. Фабрика декларирует необходимые зависимости и возвращает API модуля. Точка использования (screen, widget, layout) предоставляет зависимости при вызове. + +Модуль без cross-domain зависимостей экспортирует API напрямую. Типы всегда экспортируются напрямую — `import type` не является runtime-зависимостью. + +#### Модуль без зависимостей — прямой экспорт: + +```ts +// business/auth/index.ts +export { useAuth } from './hooks/use-auth' +export { useCurrentUser } from './hooks/use-current-user' +export type { User, Session } from './types' +``` + +#### Модуль с зависимостями — фабрика: + +```ts +// business/chat/types/deps.ts +import type { User } from '@/business/auth' + +export interface ChatDeps { + useCurrentUser: () => User | null +} +``` + +```ts +// business/chat/index.ts +import type { ChatDeps } from './types/deps' + +export function chatFactory(deps: ChatDeps) { + return { + useMessages: (roomId: string) => { + const user = deps.useCurrentUser() + // ... + }, + useSendMessage: (roomId: string) => { + const user = deps.useCurrentUser() + return (text: string) => { /* ... */ } + }, + useChatRooms: () => { + const user = deps.useCurrentUser() + // ... + }, + ChatBadge: ({ count }: { count: number }) => { /* ... */ }, + } +} + +export type { Message, ChatRoom } from './types' +export type { ChatDeps } from './types/deps' +``` + +#### Использование на странице: + +```tsx +// screens/support/support.tsx +import { useCurrentUser } from '@/business/auth' +import { chatFactory } from '@/business/chat' + +const chat = chatFactory({ useCurrentUser }) + +export function SupportScreen() { + const { useMessages, useSendMessage, ChatBadge } = chat + const messages = useMessages('support') + const sendMessage = useSendMessage('support') + + return ( +
+ + {messages.map(m => )} + +
+ ) +} +``` + +### Жизненный цикл + +Модуль рождается на самом низком уровне использования и поднимается выше только при реальной потребности. + +- Нужен на одной странице → `screens/{name}/parts/` +- Появился в 2+ местах → поднимается по природе: + - абстрактный UI → `ui/` + - блок с данными/логикой → `widgets/` + - представление бизнес-домена → `business/{area}/parts/` + +Подъём — обычный рефакторинг в рамках задачи, а не отдельная активность. + + +## Сегменты + +Раздел описывает сегменты SLM: что такое сегмент, какие бывают и что в каждом из них лежит. + +### Определение + +**Сегмент — папка внутри модуля, которая группирует файлы по назначению. Набор сегментов не фиксирован — модуль включает только те, которые ему нужны. Команда сама определяет какие сегменты используются в проекте — архитектура даёт рекомендацию.** + +### Обзор + +| Сегмент | Содержимое | +|---------|------------| +| `ui/` | Компоненты модуля — только `.tsx` файлы | +| `parts/` | Вложенные модули со своими сегментами | +| `hooks/` | React-хуки | +| `stores/` | Сторы состояния | +| `services/` | Работа с внешними источниками данных | +| `mappers/` | Трансформация данных между форматами | +| `types/` | TypeScript-типы и интерфейсы | +| `styles/` | Стили | +| `lib/` | Утилиты и хелперы модуля | +| `config/` | Константы и конфигурация | + +### Сегмент ui/ + +Компоненты, принадлежащие модулю. Содержит только `.tsx` файлы — без своих сегментов, стилей, типов, хуков. Использует сегменты родительского модуля. + +```text +auth/ +├── ui/ +│ ├── auth-provider.tsx +│ ├── auth-guard.tsx +│ └── logout-button.tsx +├── types/ +├── hooks/ +└── index.ts +``` + +Если компоненту нужны собственные сегменты — это уже не `ui/`, а `parts/`. + +### Сегмент parts/ + +Вложенные модули со своими сегментами. Каждый элемент `parts/` — полноценный модуль: папка с компонентом, хуками, стилями, типами и т.д. + +```text +home/ +├── parts/ +│ ├── hero-section/ +│ │ ├── hero-section.tsx +│ │ ├── styles/ +│ │ └── parts/ +│ │ └── top-banner/ +│ │ └── top-banner.tsx +│ └── features-section/ +│ ├── features-section.tsx +│ └── hooks/ +├── home.screen.tsx +└── index.ts +``` + +Отличие от `ui/`: элемент `parts/` — модуль со своими сегментами. Элемент `ui/` — компонент, один `.tsx` файл. + +Вложенность `parts/` инкапсулирует область разработки горизонтально: каждый разработчик работает в своём `parts/`-модуле, не затрагивая чужие. Это снижает конфликты при параллельной разработке. + +Если вложенный модуль обрастает своими `parts/` — это сигнал, что он достаточно самостоятельный для подъёма на уровень выше. + +### Сегмент hooks/ + +React-хуки модуля. Инкапсулируют логику, состояние, подписки, побочные эффекты. + +```text +hooks/ +├── use-auth.hook.ts +├── use-session.hook.ts +└── use-permissions.hook.ts +``` + +### Сегмент stores/ + +Сторы состояния модуля. Конкретная реализация зависит от выбранного стейт-менеджера (Zustand, MobX, Redux и т.д.). + +```text +stores/ +├── auth.store.ts +└── session.store.ts +``` + +### Сегмент services/ + +Работа с внешними источниками данных: API-вызовы, запросы, подписки. + +```text +services/ +├── auth.service.ts +└── token.service.ts +``` + +### Сегмент mappers/ + +Функции трансформации данных из одного формата в другой: DTO в доменный тип, доменный тип в DTO, доменный тип в ViewModel. + +```text +mappers/ +├── map-user.ts +├── map-product.ts +└── map-order-to-dto.ts +``` + +### Сегмент types/ + +TypeScript-типы и интерфейсы модуля. Доменные типы, DTO, пропсы компонентов. + +```text +types/ +├── user.type.ts +└── session.type.ts +``` + +### Сегмент styles/ + +Стили модуля. Формат зависит от выбранного подхода (CSS Modules, SCSS, CSS-in-JS и т.д.). + +```text +styles/ +├── auth.module.css +└── login-form.module.css +``` + +### Сегмент lib/ + +Утилиты и хелперы, специфичные для модуля. Чистые функции без побочных эффектов. + +```text +lib/ +├── validate-email.ts +└── format-phone.ts +``` + +Отличие от `shared/lib/`: здесь лежат утилиты, нужные только этому модулю. Общие утилиты — в `shared/lib/`. + +### Сегмент config/ + +Константы и конфигурация модуля: маршруты, лимиты, дефолтные значения. + +```text +config/ +├── routes.ts +└── constants.ts +``` diff --git a/docs/ru/basics/code-style.md b/src/base/basics/code-style.md similarity index 94% rename from docs/ru/basics/code-style.md rename to src/base/basics/code-style.md index ed6b06b..f933e18 100644 --- a/docs/ru/basics/code-style.md +++ b/src/base/basics/code-style.md @@ -1,7 +1,9 @@ --- title: Стиль кода +scope: basics +keywords: [форматирование, импорт, отступ, кавычки, early return, точка с запятой, линтер] +when: "Написание или ревью любого кода: форматирование, импорты, структура файла" --- - # Стиль кода Раздел описывает единые правила оформления кода: отступы, переносы, кавычки, порядок импортов и базовую читаемость. diff --git a/docs/ru/basics/documentation.md b/src/base/basics/documentation.md similarity index 93% rename from docs/ru/basics/documentation.md rename to src/base/basics/documentation.md index a70c209..96ac8a5 100644 --- a/docs/ru/basics/documentation.md +++ b/src/base/basics/documentation.md @@ -1,7 +1,9 @@ --- title: Документирование +scope: basics +keywords: [JSDoc, комментарий, документирование, описание функции, описание компонента] +when: "Документирование кода: JSDoc для функций, компонентов, типов" --- - # Документирование Этот раздел описывает правила документирования кода: когда и как писать diff --git a/docs/ru/workflow/getting-started.md b/src/base/basics/getting-started.md similarity index 86% rename from docs/ru/workflow/getting-started.md rename to src/base/basics/getting-started.md index 8e616f8..a50241c 100644 --- a/docs/ru/workflow/getting-started.md +++ b/src/base/basics/getting-started.md @@ -1,7 +1,9 @@ --- title: Начало работы +scope: workflow +keywords: [начало, onboarding, настройка, установка, первый запуск] +when: "Первый запуск проекта, знакомство со стеком" --- - # Начало работы Что нужно знать перед началом разработки в проекте. diff --git a/docs/ru/basics/naming.md b/src/base/basics/naming.md similarity index 93% rename from docs/ru/basics/naming.md rename to src/base/basics/naming.md index e2d7867..ffce5ce 100644 --- a/docs/ru/basics/naming.md +++ b/src/base/basics/naming.md @@ -1,7 +1,9 @@ --- title: Именование +scope: basics +keywords: [camelCase, kebab-case, PascalCase, имя файла, имя переменной, имя компонента, имя хука] +when: "Создание файлов, переменных, компонентов, хуков — выбор имени" --- - # Именование Этот раздел описывает соглашения об именовании в проекте. Единые правила делают код предсказуемым и упрощают навигацию по проекту. diff --git a/docs/ru/basics/tech-stack.md b/src/base/basics/tech-stack.md similarity index 87% rename from docs/ru/basics/tech-stack.md rename to src/base/basics/tech-stack.md index 0092c07..2c9e480 100644 --- a/docs/ru/basics/tech-stack.md +++ b/src/base/basics/tech-stack.md @@ -1,7 +1,9 @@ --- title: Технологии и библиотеки +scope: basics +keywords: [стек, React, TypeScript, Next.js, Mantine, библиотека, зависимость] +when: "Выбор библиотеки или технологии, проверка допустимости зависимости" --- - # Технологии и библиотеки Этот раздел описывает базовый стек технологий и библиотек, принятый в проекте. diff --git a/docs/ru/basics/typing.md b/src/base/basics/typing.md similarity index 89% rename from docs/ru/basics/typing.md rename to src/base/basics/typing.md index 3da8967..297c8e3 100644 --- a/docs/ru/basics/typing.md +++ b/src/base/basics/typing.md @@ -1,7 +1,9 @@ --- title: Типизация +scope: basics +keywords: [type, interface, generic, any, unknown, enum, типизация, пропсы] +when: "Типизация кода: выбор type vs interface, работа с generic, запрет any" --- - # Типизация Этот раздел описывает правила типизации: как типизировать компоненты, функции и работу с `any`/`unknown`. diff --git a/src/base/triggers/develop/add-api-request.md b/src/base/triggers/develop/add-api-request.md new file mode 100644 index 0000000..ab91dbd --- /dev/null +++ b/src/base/triggers/develop/add-api-request.md @@ -0,0 +1,35 @@ +--- +title: Добавить API-запрос +--- + +# Добавить API-запрос + +Инструкция по добавлению запроса к серверу: создание клиента, хука, обработка ответа. + +## Прочитай перед началом + +- applied/api.md — правила API-слоя: клиенты, эндпоинты, обработка ошибок +- basics/typing.md — типизация запросов и ответов + +## Шаги + +1. Определи подход: + - Клиентские данные → SWR / хук + - Серверные данные → серверный компонент (RSC) + +2. Опиши типы запроса и ответа. + +3. Создай или расширь API-клиент (→ applied/api.md). + +4. Создай хук для использования в компоненте (→ triggers/develop/create-hook.md). + +## Смежные триггеры + +- triggers/develop/create-hook.md — хук для запроса +- triggers/develop/create-component.md — компонент, использующий данные + +## Проверь себя + +- [ ] Типы запроса и ответа описаны +- [ ] Хук для использования в компоненте создан +- [ ] Обработка ошибок реализована diff --git a/src/base/triggers/develop/add-dependency.md b/src/base/triggers/develop/add-dependency.md new file mode 100644 index 0000000..ed7a7a1 --- /dev/null +++ b/src/base/triggers/develop/add-dependency.md @@ -0,0 +1,24 @@ +--- +title: Добавить зависимость +--- + +# Добавить зависимость + +Инструкция по добавлению новой npm-зависимости в проект. Проверь допустимость перед установкой. + +## Прочитай перед началом + +- basics/tech-stack.md — разрешённый стек, допустимые библиотеки + +## Шаги + +1. Проверь, что библиотека не дублирует уже используемую (→ basics/tech-stack.md). + +2. Проверь, что библиотека входит в разрешённый список или обоснуй необходимость. + +3. Установи как `dependency` или `devDependency` в зависимости от назначения. + +## Проверь себя + +- [ ] Библиотека не дублирует уже используемую +- [ ] Библиотека входит в разрешённый список (→ basics/tech-stack.md) diff --git a/src/base/triggers/develop/add-font.md b/src/base/triggers/develop/add-font.md new file mode 100644 index 0000000..abe29e6 --- /dev/null +++ b/src/base/triggers/develop/add-font.md @@ -0,0 +1,28 @@ +--- +title: Подключить шрифт +--- + +# Подключить шрифт + +Инструкция по подключению и настройке шрифта в проекте. + +## Прочитай перед началом + +- applied/fonts.md — правила подключения шрифтов: форматы, загрузка, CSS-переменные + +## Шаги + +1. Подготовь файлы шрифта (woff2). + +2. Подключи шрифт по правилам (→ applied/fonts.md). + +3. Зарегистрируй CSS-переменную для шрифта. + +## Смежные триггеры + +- triggers/develop/style-component.md — использование шрифта в стилях + +## Проверь себя + +- [ ] Файл шрифта в формате woff2 +- [ ] CSS-переменная для шрифта зарегистрирована diff --git a/src/base/triggers/develop/add-icon.md b/src/base/triggers/develop/add-icon.md new file mode 100644 index 0000000..f5dab10 --- /dev/null +++ b/src/base/triggers/develop/add-icon.md @@ -0,0 +1,29 @@ +--- +title: Добавить иконку +--- + +# Добавить иконку + +Инструкция по добавлению SVG-иконки в проект через спрайт-систему. + +## Прочитай перед началом + +- applied/svg-sprites.md — правила SVG-спрайтов: структура, именование, использование + +## Шаги + +1. Подготовь SVG-файл: убери лишние атрибуты, оптимизируй. + +2. Добавь SVG в спрайт по правилам (→ applied/svg-sprites.md). + +3. Используй иконку в компоненте через компонент-обёртку. + +## Смежные триггеры + +- triggers/develop/create-component.md — если нужен компонент-обёртка для иконки +- triggers/develop/style-component.md — стилизация иконки (размер, цвет) + +## Проверь себя + +- [ ] SVG оптимизирован — убраны лишние атрибуты +- [ ] Иконка добавлена в спрайт по правилам (→ applied/svg-sprites.md) diff --git a/src/base/triggers/develop/add-image.md b/src/base/triggers/develop/add-image.md new file mode 100644 index 0000000..cdefdc3 --- /dev/null +++ b/src/base/triggers/develop/add-image.md @@ -0,0 +1,30 @@ +--- +title: Добавить изображение +--- + +# Добавить изображение + +Инструкция по добавлению и использованию растровых изображений в проекте. + +## Прочитай перед началом + +- applied/images-sprites.md — правила работы с изображениями: оптимизация, форматы, подключение + +## Шаги + +1. Определи тип изображения: + - Статическое (логотип, декор) → `public/` + - Динамическое (контентное) → URL из API + +2. Оптимизируй изображение (формат, размер, сжатие). + +3. Подключи в компоненте по правилам (→ applied/images-sprites.md). + +## Смежные триггеры + +- triggers/develop/create-component.md — если нужен компонент-обёртка для изображения + +## Проверь себя + +- [ ] Изображение оптимизировано (формат, размер, сжатие) +- [ ] Подключено по правилам (→ applied/images-sprites.md) diff --git a/src/base/triggers/develop/add-localization.md b/src/base/triggers/develop/add-localization.md new file mode 100644 index 0000000..330641f --- /dev/null +++ b/src/base/triggers/develop/add-localization.md @@ -0,0 +1,28 @@ +--- +title: Добавить перевод +--- + +# Добавить перевод + +Инструкция по добавлению локализации: создание ключей перевода и подключение в компоненте. + +## Прочитай перед началом + +- applied/localization.md — правила локализации: namespace, ключи, форматирование + +## Шаги + +1. Определи namespace для переводов (→ applied/localization.md). + +2. Добавь ключи перевода в файлы локализации. + +3. Подключи переводы в компоненте (→ applied/localization.md). + +## Смежные триггеры + +- triggers/develop/create-component.md — если компонент ещё не создан + +## Проверь себя + +- [ ] Ключи перевода добавлены в файлы локализации +- [ ] Namespace определён (→ applied/localization.md) diff --git a/src/base/triggers/develop/add-video.md b/src/base/triggers/develop/add-video.md new file mode 100644 index 0000000..a319276 --- /dev/null +++ b/src/base/triggers/develop/add-video.md @@ -0,0 +1,27 @@ +--- +title: Добавить видео +--- + +# Добавить видео + +Инструкция по встраиванию видео в проект. + +## Прочитай перед началом + +- applied/video.md — правила работы с видео: форматы, плеер, оптимизация + +## Шаги + +1. Определи тип видео: + - Локальное → `public/` + - Внешнее (YouTube, Vimeo) → embed + +2. Подключи видео по правилам (→ applied/video.md). + +## Смежные триггеры + +- triggers/develop/create-component.md — если нужен компонент-обёртка для видео + +## Проверь себя + +- [ ] Видео подключено по правилам (→ applied/video.md) diff --git a/src/base/triggers/develop/connect-store.md b/src/base/triggers/develop/connect-store.md new file mode 100644 index 0000000..0457ef0 --- /dev/null +++ b/src/base/triggers/develop/connect-store.md @@ -0,0 +1,31 @@ +--- +title: Подключить стор к компоненту +--- + +# Подключить стор к компоненту + +Инструкция по подключению стора к React-компоненту. + +## Прочитай перед началом + +- applied/stores.md — правила сторов: подписка, селекторы + +## Шаги + +1. Определи нужен ли стор: + - Локальное состояние → `useState` / `useReducer` + - Глобальное состояние → стор + +2. Если стор не существует — создай его (→ triggers/develop/create-store.md). + +3. Подключи стор в компоненте через селектор (→ applied/stores.md). + +## Смежные триггеры + +- triggers/develop/create-store.md — создание нового стора +- triggers/develop/create-hook.md — хук-обёртка над стором + +## Проверь себя + +- [ ] Используется селектор, а не подписка на весь стор +- [ ] Выбор локальное/глобальное состояние обоснован diff --git a/src/base/triggers/develop/create-component.md b/src/base/triggers/develop/create-component.md new file mode 100644 index 0000000..ac5c4a5 --- /dev/null +++ b/src/base/triggers/develop/create-component.md @@ -0,0 +1,38 @@ +--- +title: Создать компонент +--- + +# Создать компонент + +Инструкция по созданию React-компонента в проекте. Определи слой, сгенерируй из шаблона, реализуй по правилам. + +## Прочитай перед началом + +- applied/components.md — правила компонентов: структура файлов, пропсы, документирование +- basics/naming.md — именование файла и экспортов + +## Шаги + +1. Определи слой компонента по его назначению (→ basics/architecture.md): + - `shared/ui/` — переиспользуемый UI без бизнес-логики + - `features/` — фича с бизнес-логикой + - `widgets/` — композиция фичей и сущностей + - `entities/` — бизнес-сущность с UI + +2. Сгенерируй модуль из шаблона (→ triggers/develop/generate-module.md). + +3. Реализуй компонент по правилам (→ applied/components.md). + +4. Если нужны стили — см. triggers/develop/style-component.md. + +## Смежные триггеры + +- triggers/develop/style-component.md — стилизация компонента +- triggers/develop/add-icon.md — добавление иконки в компонент +- triggers/develop/generate-module.md — генерация из шаблона + +## Проверь себя + +- [ ] Компонент создан из шаблона, не вручную +- [ ] Файл и экспорт именованы по конвенции (→ basics/naming.md) +- [ ] Пропсы типизированы (→ basics/typing.md) diff --git a/src/base/triggers/develop/create-entity.md b/src/base/triggers/develop/create-entity.md new file mode 100644 index 0000000..ceba8d0 --- /dev/null +++ b/src/base/triggers/develop/create-entity.md @@ -0,0 +1,34 @@ +--- +title: Создать сущность +--- + +# Создать сущность + +Инструкция по созданию модуля на слое `entities/`. Сущность — бизнес-объект с UI-представлением и моделью данных. + +## Прочитай перед началом + +- basics/architecture.md — слои и зависимости +- applied/components.md — правила компонентов + +## Шаги + +1. Сгенерируй модуль из шаблона `entity` (→ triggers/develop/generate-module.md). + +2. Определи модель данных — типы в `model/`. + +3. Реализуй UI-компонент сущности. + +4. Настрой публичный API — экспорт через `index.ts`. + +## Смежные триггеры + +- triggers/develop/create-component.md — UI-компонент сущности +- triggers/develop/create-store.md — стор для сущности +- triggers/develop/generate-module.md — генерация из шаблона + +## Проверь себя + +- [ ] Сущность создана из шаблона `entity` +- [ ] Модель данных определена — типы в `model/` +- [ ] Публичный API настроен — экспорт через `index.ts` diff --git a/src/base/triggers/develop/create-feature.md b/src/base/triggers/develop/create-feature.md new file mode 100644 index 0000000..d28aeab --- /dev/null +++ b/src/base/triggers/develop/create-feature.md @@ -0,0 +1,37 @@ +--- +title: Создать фичу +--- + +# Создать фичу + +Инструкция по созданию модуля на слое `features/`. Фича — самодостаточный блок с бизнес-логикой и UI. + +## Прочитай перед началом + +- basics/architecture.md — слои и зависимости +- applied/components.md — правила компонентов + +## Шаги + +1. Сгенерируй модуль из шаблона `feature` (→ triggers/develop/generate-module.md). + +2. Реализуй компонент фичи (→ applied/components.md). + +3. Если нужен стор — создай в `model/` (→ triggers/develop/create-store.md). + +4. Если нужны хуки — создай в `model/` (→ triggers/develop/create-hook.md). + +5. Настрой публичный API — экспорт через `index.ts`. + +## Смежные триггеры + +- triggers/develop/create-component.md — компонент внутри фичи +- triggers/develop/create-store.md — стор для фичи +- triggers/develop/create-hook.md — хук для фичи +- triggers/develop/generate-module.md — генерация из шаблона + +## Проверь себя + +- [ ] Фича создана из шаблона `feature` +- [ ] Публичный API настроен — экспорт через `index.ts` +- [ ] Нет зависимостей от других фичей (→ basics/architecture.md) diff --git a/src/base/triggers/develop/create-hook.md b/src/base/triggers/develop/create-hook.md new file mode 100644 index 0000000..37e0ec2 --- /dev/null +++ b/src/base/triggers/develop/create-hook.md @@ -0,0 +1,36 @@ +--- +title: Создать хук +--- + +# Создать хук + +Инструкция по созданию кастомного React-хука. Определи где он живёт, реализуй по правилам. + +## Прочитай перед началом + +- applied/hooks.md — правила хуков +- basics/naming.md — именование (префикс `use`) +- basics/typing.md — типизация параметров и возврата + +## Шаги + +1. Определи область хука: + - Утилитарный (не привязан к бизнес-логике) → `shared/hooks/` + - Привязан к фиче/сущности → `model/` внутри модуля + +2. Создай файл с именем `use-{name}.ts`. + +3. Реализуй хук по правилам (→ applied/hooks.md). + +4. Экспортируй через публичный API модуля. + +## Смежные триггеры + +- triggers/develop/create-component.md — если хук используется в новом компоненте +- triggers/develop/connect-store.md — если хук подключает стор + +## Проверь себя + +- [ ] Имя начинается с `use` (→ basics/naming.md) +- [ ] Параметры и возвращаемое значение типизированы +- [ ] Хук экспортирован через публичный API модуля diff --git a/src/base/triggers/develop/create-store.md b/src/base/triggers/develop/create-store.md new file mode 100644 index 0000000..8ca9d13 --- /dev/null +++ b/src/base/triggers/develop/create-store.md @@ -0,0 +1,36 @@ +--- +title: Создать стор +--- + +# Создать стор + +Инструкция по созданию стора для управления состоянием. Определи область, сгенерируй из шаблона. + +## Прочитай перед началом + +- applied/stores.md — правила сторов +- basics/naming.md — именование +- basics/typing.md — типизация состояния и экшенов + +## Шаги + +1. Определи область стора: + - Глобальный → `shared/model/` + - Привязан к фиче/сущности → `model/` внутри модуля + +2. Сгенерируй из шаблона `store` (→ triggers/develop/generate-module.md). + +3. Реализуй стор по правилам (→ applied/stores.md). + +4. Экспортируй через публичный API модуля. + +## Смежные триггеры + +- triggers/develop/connect-store.md — подключение стора к компоненту +- triggers/develop/generate-module.md — генерация из шаблона + +## Проверь себя + +- [ ] Стор создан из шаблона `store` +- [ ] Состояние и экшены типизированы +- [ ] Стор экспортирован через публичный API модуля diff --git a/src/base/triggers/develop/create-widget.md b/src/base/triggers/develop/create-widget.md new file mode 100644 index 0000000..f717580 --- /dev/null +++ b/src/base/triggers/develop/create-widget.md @@ -0,0 +1,32 @@ +--- +title: Создать виджет +--- + +# Создать виджет + +Инструкция по созданию модуля на слое `widgets/`. Виджет — композиция фичей и сущностей. + +## Прочитай перед началом + +- basics/architecture.md — слои и зависимости +- applied/components.md — правила компонентов + +## Шаги + +1. Сгенерируй модуль из шаблона `widget` (→ triggers/develop/generate-module.md). + +2. Скомпонуй виджет из существующих фичей и сущностей. + +3. Настрой публичный API — экспорт через `index.ts`. + +## Смежные триггеры + +- triggers/develop/create-feature.md — если нужна новая фича для виджета +- triggers/develop/create-component.md — UI-компоненты внутри виджета +- triggers/develop/generate-module.md — генерация из шаблона + +## Проверь себя + +- [ ] Виджет создан из шаблона `widget` +- [ ] Композиция из существующих фичей/сущностей, не дублирует логику +- [ ] Публичный API настроен — экспорт через `index.ts` diff --git a/src/base/triggers/develop/generate-module.md b/src/base/triggers/develop/generate-module.md new file mode 100644 index 0000000..1113c20 --- /dev/null +++ b/src/base/triggers/develop/generate-module.md @@ -0,0 +1,37 @@ +--- +title: Сгенерировать модуль из шаблона +--- + +# Сгенерировать модуль из шаблона + +Инструкция по генерации модуля из шаблонов `.templates/`. Ручное создание файловой структуры запрещено. + +## Прочитай перед началом + +- applied/templates-generation.md — шаблоны, синтаксис, инструменты генерации + +## Шаги + +1. Определи тип модуля и шаблон (→ applied/templates-generation.md): + - Компонент → `component` + - Фича → `feature` + - Виджет → `widget` + - Сущность → `entity` + - Layout → `layout` + - Экран → `screen` + - Стор → `store` + +2. Запусти генерацию (→ applied/templates-generation.md). + +3. Если подходящего шаблона нет — сначала создай шаблон, затем генерируй. + +## Смежные триггеры + +- triggers/develop/create-component.md — после генерации компонента +- triggers/develop/create-feature.md — после генерации фичи +- triggers/develop/create-store.md — после генерации стора + +## Проверь себя + +- [ ] Модуль создан из шаблона, не вручную +- [ ] Выбран правильный шаблон для типа модуля (→ applied/templates-generation.md) diff --git a/src/base/triggers/develop/setup-vscode.md b/src/base/triggers/develop/setup-vscode.md new file mode 100644 index 0000000..953a78e --- /dev/null +++ b/src/base/triggers/develop/setup-vscode.md @@ -0,0 +1,24 @@ +--- +title: Настроить VS Code +--- + +# Настроить VS Code + +Инструкция по настройке VS Code для работы с проектом. + +## Прочитай перед началом + +- applied/vscode.md — настройки, расширения, сниппеты + +## Шаги + +1. Установи рекомендованные расширения (→ applied/vscode.md). + +2. Проверь настройки `.vscode/settings.json`. + +3. Настрой сниппеты при необходимости. + +## Проверь себя + +- [ ] Рекомендованные расширения установлены +- [ ] Настройки `.vscode/settings.json` проверены diff --git a/src/base/triggers/develop/style-component.md b/src/base/triggers/develop/style-component.md new file mode 100644 index 0000000..175144f --- /dev/null +++ b/src/base/triggers/develop/style-component.md @@ -0,0 +1,35 @@ +--- +title: Стилизовать компонент +--- + +# Стилизовать компонент + +Инструкция по выбору подхода к стилизации и написанию стилей для компонента. + +## Прочитай перед началом + +- applied/styles.md — правила CSS: PostCSS Modules, токены, медиа-запросы + +## Шаги + +1. Определи подход (→ applied/styles.md): + - Mantine-компонент → используй пропсы Mantine, не пиши CSS + - CSS-токены достаточно → используй токены + - Нужна кастомная стилизация → PostCSS Modules + +2. Создай файл стилей `{component-name}.module.css` рядом с компонентом. + +3. Напиши стили по правилам (→ applied/styles.md). + +4. Подключи стили в компоненте через `cl()`. + +## Смежные триггеры + +- triggers/develop/create-component.md — если компонент ещё не создан +- triggers/develop/add-icon.md — если нужна иконка в компоненте + +## Проверь себя + +- [ ] Приоритет стилизации соблюдён: Mantine → токены → PostCSS Modules +- [ ] Нет инлайн-стилей и магических значений +- [ ] Файл стилей именован `{component-name}.module.css` diff --git a/src/nextjs/DEVELOP.md b/src/nextjs/DEVELOP.md new file mode 100644 index 0000000..394e60d --- /dev/null +++ b/src/nextjs/DEVELOP.md @@ -0,0 +1,51 @@ +# Стайлгайд — Разработка + +Правила и стандарты разработки на Next.js и TypeScript. + +## Как работать + +1. Найди задачу в таблицах ниже → открой триггер. +2. Триггер укажет какие разделы прочитать и какие шаги выполнить. +3. Перед каждой подзадачей возвращайся к этой таблице — проверяй, нет ли готового триггера. +4. Если задачи нет в таблицах — ищи в `applied/` (по области) или `basics/` (общие правила). + +## Создание + +| Задача | Триггер | Когда / Когда НЕ | +|--------|---------|-------------------| +| Создать компонент | triggers/develop/create-component.md | Переиспользуемый UI без бизнес-логики. НЕ для: фичи, виджета, сущности | +| Создать фичу | triggers/develop/create-feature.md | Самодостаточный блок с бизнес-логикой и UI. НЕ для: утилитарного UI (→ компонент) | +| Создать виджет | triggers/develop/create-widget.md | Композиция фичей и сущностей. НЕ для: одиночного UI (→ компонент) | +| Создать сущность | triggers/develop/create-entity.md | Бизнес-объект с UI и моделью данных. НЕ для: UI без модели (→ компонент) | +| Создать хук | triggers/develop/create-hook.md | Кастомный React-хук. НЕ для: хука внутри стора | +| Создать стор | triggers/develop/create-store.md | Глобальное или модульное состояние. НЕ для: локального useState | +| Создать страницу | triggers/develop/create-page.md | Новый route в Next.js. Всегда экран + page.tsx | +| Создать layout | triggers/develop/create-layout.md | layout.tsx для группы страниц | +| Создать проект | triggers/develop/create-project.md | Новый проект из шаблона | +| Сгенерировать модуль | triggers/develop/generate-module.md | Любой модуль из `.templates/`. Ручное создание файлов запрещено | + +## Стилизация и ресурсы + +| Задача | Триггер | Когда / Когда НЕ | +|--------|---------|-------------------| +| Стилизовать компонент | triggers/develop/style-component.md | Выбор подхода + написание CSS. НЕ для: Mantine-пропсов (они не требуют CSS) | +| Добавить иконку | triggers/develop/add-icon.md | SVG-иконка через спрайт-систему | +| Добавить изображение | triggers/develop/add-image.md | Растровое изображение (png, jpg, webp) | +| Добавить видео | triggers/develop/add-video.md | Встраивание видео | +| Подключить шрифт | triggers/develop/add-font.md | Новый шрифт в проект | + +## Данные и состояние + +| Задача | Триггер | Когда / Когда НЕ | +|--------|---------|-------------------| +| Добавить API-запрос | triggers/develop/add-api-request.md | Клиентский запрос (SWR). НЕ для: серверных данных (→ add-server-data) | +| Подключить стор | triggers/develop/connect-store.md | Подключение стора к компоненту. НЕ для: создания стора (→ create-store) | +| Серверные данные (RSC) | triggers/develop/add-server-data.md | Данные в серверных компонентах. НЕ для: клиентских запросов (→ add-api-request) | + +## Инфраструктура + +| Задача | Триггер | Когда / Когда НЕ | +|--------|---------|-------------------| +| Добавить перевод | triggers/develop/add-localization.md | Ключи перевода и подключение i18next | +| Добавить зависимость | triggers/develop/add-dependency.md | Новая npm-библиотека. Проверь допустимость | +| Настроить VS Code | triggers/develop/setup-vscode.md | Расширения, настройки, сниппеты | diff --git a/src/nextjs/REVIEW.md b/src/nextjs/REVIEW.md new file mode 100644 index 0000000..45cf1a0 --- /dev/null +++ b/src/nextjs/REVIEW.md @@ -0,0 +1,43 @@ +# Стайлгайд — Ревью + +Правила проверки кода на Next.js и TypeScript. Читай перед ревью PR. + +## Как пользоваться + +1. Определи какие области затронуты в PR. +2. Открой соответствующие разделы из таблиц ниже. +3. Проверь код на соответствие правилам. + +## Что проверять всегда + +Базовые правила — применимы к любому коду в PR. + +| Что проверить | Раздел | +|---------------|--------| +| Форматирование, импорты, early return | basics/code-style.md | +| Имена файлов, переменных, компонентов | basics/naming.md | +| Нет any, правильный type/interface | basics/typing.md | +| JSDoc на публичных функциях | basics/documentation.md | +| Правильный слой, нет запрещённых зависимостей | basics/architecture.md | +| Нет неразрешённых библиотек | basics/tech-stack.md | + +## Что проверять по области + +Открой раздел, если PR затрагивает соответствующую область. + +| Область | Раздел | +|---------|--------| +| React-компоненты | applied/components.md | +| CSS / стили | applied/styles.md | +| Шаблоны генерации | applied/templates-generation.md | +| Хуки | applied/hooks.md | +| Сторы | applied/stores.md | +| API-слой | applied/api.md | +| Шрифты | applied/fonts.md | +| Переводы | applied/localization.md | +| Изображения | applied/images-sprites.md | +| SVG-иконки | applied/svg-sprites.md | +| Видео | applied/video.md | +| Настройки VS Code | applied/vscode.md | +| page.tsx, layout.tsx | applied/page-level.md | +| Структура папок | applied/project-structure.md | diff --git a/docs/ru/applied/page-level.md b/src/nextjs/applied/page-level.md similarity index 78% rename from docs/ru/applied/page-level.md rename to src/nextjs/applied/page-level.md index e9a8585..6b29e35 100644 --- a/docs/ru/applied/page-level.md +++ b/src/nextjs/applied/page-level.md @@ -1,11 +1,17 @@ --- title: Файлы роутинга +scope: applied +keywords: [page.tsx, layout.tsx, error.tsx, not-found.tsx, loading.tsx, App Router, metadata] +when: "Работа с файлами роутинга Next.js App Router: page, layout, error, not-found" --- - # Файлы роутинга Правила для специальных файлов App Router (`page.tsx`, `layout.tsx`, `error.tsx`, `not-found.tsx` и др.) — чем наш подход отличается от дефолтного. +## Что нужно знать + +Страница в проекте — это два файла: экран в `src/screens/` (вся логика, стили, зависимости) и `page.tsx` в `src/app/` (точка входа для роутинга Next.js). Экран генерируется из шаблона, `page.tsx` создаётся вручную. + ## Организация - `page.tsx` — тонкий файл: только `metadata` и рендер экрана. Логика, стили и зависимости живут в экране, не в `page.tsx`. diff --git a/docs/ru/applied/project-structure.md b/src/nextjs/applied/project-structure.md similarity index 95% rename from docs/ru/applied/project-structure.md rename to src/nextjs/applied/project-structure.md index fbd63ca..b8d8b04 100644 --- a/docs/ru/applied/project-structure.md +++ b/src/nextjs/applied/project-structure.md @@ -1,7 +1,9 @@ --- title: Структура проекта +scope: applied +keywords: [структура проекта, папки, src/app, src/shared, FSD, Next.js структура] +when: "Организация папок и файлов в Next.js проекте" --- - # Структура проекта Раздел описывает расположение файлов и папок в проекте Next.js (App Router). diff --git a/src/nextjs/triggers/develop/add-server-data.md b/src/nextjs/triggers/develop/add-server-data.md new file mode 100644 index 0000000..0857e39 --- /dev/null +++ b/src/nextjs/triggers/develop/add-server-data.md @@ -0,0 +1,33 @@ +--- +title: Добавить серверные данные +--- + +# Добавить серверные данные + +Инструкция по получению данных в серверных компонентах (RSC) Next.js. + +## Прочитай перед началом + +- applied/page-level.md — серверные компоненты в App Router +- applied/api.md — API-клиенты + +## Шаги + +1. Определи где получать данные: + - В `page.tsx` / `layout.tsx` → серверный fetch + - В клиентском компоненте → SWR (→ triggers/develop/add-api-request.md) + +2. Создай или расширь серверный API-клиент. + +3. Получи данные в серверном компоненте и передай через пропсы. + +## Смежные триггеры + +- triggers/develop/add-api-request.md — клиентские запросы (SWR) +- triggers/develop/create-page.md — серверный fetch в page.tsx + +## Проверь себя + +- [ ] Определён тип: серверный fetch или клиентский SWR +- [ ] Типы запроса и ответа описаны +- [ ] Данные передаются через пропсы, не через глобальное состояние diff --git a/src/nextjs/triggers/develop/create-layout.md b/src/nextjs/triggers/develop/create-layout.md new file mode 100644 index 0000000..660be9f --- /dev/null +++ b/src/nextjs/triggers/develop/create-layout.md @@ -0,0 +1,34 @@ +--- +title: Создать layout +--- + +# Создать layout + +Инструкция по созданию layout.tsx в Next.js App Router. + +## Прочитай перед началом + +- applied/page-level.md — правила layout.tsx: провайдеры, metadata, вёрстка +- applied/project-structure.md — структура `src/app/` + +## Шаги + +1. Определи уровень layout: + - Корневой (`src/app/layout.tsx`) — провайдеры, глобальные стили, metadata + - Вложенный (`src/app/{route}/layout.tsx`) — layout для группы страниц + +2. Создай `layout.tsx` в нужном маршруте. + +3. Вёрстку layout-обёрток вынеси в слой `layouts/` (→ applied/page-level.md). + +4. Layout содержит только провайдеры и вызов layout-компонента — не вёрстку. + +## Смежные триггеры + +- triggers/develop/create-page.md — страницы внутри layout +- triggers/develop/create-component.md — layout-компонент в `layouts/` + +## Проверь себя + +- [ ] Вёрстка вынесена в layout-компонент в `layouts/` +- [ ] layout.tsx содержит только провайдеры и вызов layout-компонента diff --git a/src/nextjs/triggers/develop/create-page.md b/src/nextjs/triggers/develop/create-page.md new file mode 100644 index 0000000..a23eb94 --- /dev/null +++ b/src/nextjs/triggers/develop/create-page.md @@ -0,0 +1,36 @@ +--- +title: Создать страницу +--- + +# Создать страницу + +Инструкция по добавлению нового route в Next.js проект. Страница — это экран + page.tsx. + +## Прочитай перед началом + +- applied/page-level.md — правила файлов роутинга: page.tsx, layout.tsx, metadata +- applied/project-structure.md — где располагаются файлы + +## Шаги + +1. Сгенерируй экран из шаблона `screen` в `src/screens/` (→ triggers/develop/generate-module.md). + +2. Заполни экран логикой и стилями. + +3. Создай `page.tsx` в нужном маршруте `src/app/`. + - page.tsx тонкий: только `metadata` и рендер экрана + - Никакой логики, стилей и хуков в page.tsx + +4. Добавь `metadata` с `title` (→ applied/page-level.md). + +## Смежные триггеры + +- triggers/develop/generate-module.md — генерация экрана из шаблона +- triggers/develop/create-layout.md — если нужен новый layout для маршрута +- triggers/develop/create-component.md — компоненты внутри экрана + +## Проверь себя + +- [ ] Экран создан из шаблона `screen` в `src/screens/` +- [ ] page.tsx тонкий — только metadata и рендер экрана +- [ ] metadata содержит title и description diff --git a/src/nextjs/triggers/develop/create-project.md b/src/nextjs/triggers/develop/create-project.md new file mode 100644 index 0000000..bc27db9 --- /dev/null +++ b/src/nextjs/triggers/develop/create-project.md @@ -0,0 +1,52 @@ +--- +title: Создать проект +scope: applied +keywords: [создать проект, новый проект, tiged, шаблон проекта, init] +when: "Создание нового Next.js проекта из шаблона" +--- + +# Создать проект + +Инструкция по созданию нового Next.js проекта из готового шаблона. Проект готов к разработке сразу после установки зависимостей. + +## Прочитай перед началом + +- basics/getting-started.md — знакомство со стеком и особенностями проекта +- applied/project-structure.md — структура папок и файлов + +## Шаги + +1. Создай проект из шаблона: + + ```bash + npx tiged git@gromlab.ru:templates/nextjs.git my-app + cd my-app + npm install + ``` + +2. Ознакомься со структурой проекта (→ applied/project-structure.md). + +3. Настрой VS Code (→ triggers/develop/setup-vscode.md). + +## Что входит в шаблон + +- Next.js + TypeScript (App Router) +- Mantine UI + PostCSS Modules +- Biome (линтинг и форматирование) +- Zustand, SWR +- Структура FSD (`screens/`, `widgets/`, `features/`, `entities/`, `shared/`) +- Шаблоны генерации (`.templates/`) +- Конфигурация VS Code (`.vscode/`) +- CSS-токены (цвета, отступы, радиусы, медиа) +- Open Graph метаданные + +## Смежные триггеры + +- triggers/develop/setup-vscode.md — настройка редактора +- triggers/develop/create-page.md — добавление первой страницы + +## Проверь себя + +- [ ] Проект создан из шаблона через `npx tiged` +- [ ] Зависимости установлены +- [ ] VS Code настроен (→ triggers/develop/setup-vscode.md)