Compare commits

..

23 Commits

Author SHA1 Message Date
47658cdbb9 sync 2026-04-20 09:43:43 +03:00
4aeb1dd6b2 feat: Progressive Disclosure документация 2026-04-20 06:40:34 +03:00
436c87a986 docs: обновить RULES.md после переработки раздела архитектуры
All checks were successful
CI/CD Pipeline / docker (push) Successful in 40s
CI/CD Pipeline / deploy (push) Successful in 5s
2026-04-04 08:10:41 +03:00
be3d86f198 docs: переработать раздел архитектуры (SLM Design)
All checks were successful
CI/CD Pipeline / docker (push) Successful in 40s
CI/CD Pipeline / deploy (push) Successful in 8s
- описание FSD как базы заменено на SLM Design (Scoped Layered Module Design)
- добавлена терминология: слой, модуль, компонент, сегмент
- добавлено детальное описание каждого слоя с примерами структуры
- описан ключевой принцип колокации и подъёма модулей
- добавлены правила именования суффиксов по слоям
- добавлены правила импортов (между слоями, внутри модуля, shared)
- добавлен жизненный цикл модуля и граничные случаи
- добавлены обоснования архитектурных решений
2026-04-04 08:07:45 +03:00
073fc6507f Обновить notes
All checks were successful
CI/CD Pipeline / docker (push) Successful in 40s
CI/CD Pipeline / deploy (push) Successful in 6s
2026-04-03 20:02:01 +03:00
cba311d78e Обновить notes
All checks were successful
CI/CD Pipeline / docker (push) Successful in 39s
CI/CD Pipeline / deploy (push) Successful in 6s
2026-04-03 19:54:46 +03:00
11f9b702e0 Обновить notes
All checks were successful
CI/CD Pipeline / docker (push) Successful in 40s
CI/CD Pipeline / deploy (push) Successful in 6s
2026-04-03 19:40:15 +03:00
f7d3506a91 Добавить notes
All checks were successful
CI/CD Pipeline / docker (push) Successful in 39s
CI/CD Pipeline / deploy (push) Successful in 7s
2026-04-03 12:37:08 +03:00
be8e89fccd docs: обновить название и ссылки расширения для генерации шаблонов
All checks were successful
CI/CD Pipeline / docker (push) Successful in 41s
CI/CD Pipeline / deploy (push) Successful in 6s
- заменён MyTemplateGenerator на Template File Generator | gromlab
- добавлены ссылки на VS Code Marketplace и Open VSX
- пересобран RULES.md
2026-04-02 22:33:30 +03:00
fbac3e1a55 docs: отказаться от FC и interface в пропсах компонентов
All checks were successful
CI/CD Pipeline / docker (push) Successful in 1m41s
CI/CD Pipeline / deploy (push) Successful in 8s
- переписана типизация: type вместо interface, убран FC
- введена система типов: Params + RootAttrs + Props
- добавлены обоснования: почему type, почему не FC, почему types/
- обновлены примеры в components, page-level, templates, documentation
- убраны упоминания FC из таблиц index.md и README
- перегенерированы RULES.md
2026-04-02 16:01:29 +03:00
6ccc4a0d06 docs(pages): Переписать весь раздел.
All checks were successful
CI/CD Pipeline / docker (push) Successful in 44s
CI/CD Pipeline / deploy (push) Successful in 8s
2026-04-01 11:02:18 +03:00
4ae6ac893d docs: убрать устаревшее правило о кэше VitePress из AGENTS.md
All checks were successful
CI/CD Pipeline / docker (push) Successful in 39s
CI/CD Pipeline / deploy (push) Successful in 7s
- удалена строка «Не коммитить .vitepress/cache/» (кэш уже исключён из отслеживания git)
2026-04-01 10:45:50 +03:00
965235e390 docs: убрать Workflow и Чеклист из структуры прикладного раздела
- удалены секции «Workflow» и «Чеклист» из шаблона
- обновлено описание раздела: о чём раздел и какие аспекты он охватывает
- обновлён порядок секций: убраны «процесс» и «проверка»
- удалён принцип «Workflow vs правила», нумерация сдвинута
2026-04-01 10:45:22 +03:00
e608017dce chore: удалить кэш VitePress из отслеживания git
- удалены файлы .vitepress/cache из индекса (правило в .gitignore уже существовало, но файлы были закоммичены ранее)
2026-04-01 10:38:16 +03:00
29bcf23dde docs: переработать компоненты, структуру проекта и документирование
- переработан раздел «Компоненты»: добавлены правила организации, типизации, реализации
- переработан раздел «Структура проекта»: упрощён, добавлены корень репозитория и конфиг-файлы
- переработан раздел «Документирование»: добавлены шаблоны для функций, компонентов, типов
- обновлён CONTRIBUTING.md: добавлены секции Workflow и Чеклист, правила разделены на Реализацию и Организацию
- перенесены типы компонентов из «Типизации» в «Компоненты»
- обновлён шаблон генерации: деструктуризация пропсов в теле, children вместо текста
- добавлен SCREAMING_SNAKE_CASE для ключей enum в «Именование»
- перемещён «Настройка VS Code» в конец сайдбара
- обновлён порядок файлов в concat-md.js и перегенерирован RULES.md
2026-04-01 10:35:07 +03:00
c46b843670 chore: переместить 'Именование' после 'Технологии' в сайдбаре и конкатенации
All checks were successful
CI/CD Pipeline / docker (push) Successful in 45s
CI/CD Pipeline / deploy (push) Successful in 8s
2026-03-31 15:18:08 +03:00
2d1f3b9df9 docs: добавить вводные описания разделов документирования и типизации 2026-03-31 15:18:04 +03:00
2bf34e6f79 docs(tech-stack): обновить раздел технологий
- заменил жирное выделение на форматирование кодом
- добавил ссылку на раздел архитектуры для FSD
- обновил вводное описание раздела
- переименовал 'Fetch (API)' в 'Работа с данными (API)'
2026-03-31 15:18:00 +03:00
909ce71931 docs(naming): переработать раздел именования
- переименовал 'Архитектурный неймспейс' в 'Именование файлов'
- убрал суффиксы master component'ов (перенесены в архитектуру)
- добавил правило именования хуков: use-name.hook.ts / useName
- обновил примеры хорошо/плохо
- обновил вводное описание раздела
2026-03-31 15:17:54 +03:00
e337ec78fa docs(architecture): переработать раздел архитектуры
- заменил описание слоёв и модулей FSD на новую модель с компонентами
- добавил раздел 'Что важно знать' с пояснением что архитектура надстройка над FSD
- добавил описание master component и его правил
- добавил раздел сегментов с таблицей
- убрал дублирующиеся правила зависимостей и публичного API
2026-03-31 15:17:47 +03:00
3993909b98 docs: добавлен AGENTS.md с правилами для агентов
All checks were successful
CI/CD Pipeline / docker (push) Successful in 41s
CI/CD Pipeline / deploy (push) Successful in 7s
- ссылка на CONTRIBUTING.md как основной источник правил
- операционные напоминания: язык, npm run docs, обновление конфигов, кеш
2026-03-30 09:23:27 +03:00
43f2d92201 docs: добавлен CONTRIBUTING.md, удалён AGENTS.md
- создан CONTRIBUTING.md с мета-правилами работы над документацией
- описаны три типа документации (workflow, базовые, прикладные) и границы между ними
- добавлен шаблон структуры прикладного раздела
- зафиксированы конвенции оформления (frontmatter, заголовки, примеры, таблицы)
- удалён устаревший AGENTS.md
2026-03-30 09:10:21 +03:00
bc01cb930a docs: переименованы разделы прикладных секций, удалён «Начало работы»
- Компоненты → UI и компоненты
- Page-level компоненты → Страницы (App Router)
- Удалён раздел «Начало работы» из workflow
- Обновлены sidebar, заголовки md-файлов и RULES.md
2026-03-29 18:55:12 +03:00
134 changed files with 2501 additions and 31792 deletions

View File

@@ -73,7 +73,7 @@ jobs:
ssh -i ~/.ssh/deploy_key root@188.225.47.78 bash -s <<'SCRIPT' ssh -i ~/.ssh/deploy_key root@188.225.47.78 bash -s <<'SCRIPT'
set -e set -e
IMAGE="${{ env.REGISTRY_IMAGE }}:latest" IMAGE="${{ env.REGISTRY_IMAGE }}:latest"
CONTAINER="nextjs-style-guide" CONTAINER="frontend-style-guide"
# Логин в реестр # Логин в реестр
echo '${{ secrets.CR_TOKEN }}' | docker login ${{ env.DOCKER_REGISTRY }} -u '${{ secrets.CR_USER }}' --password-stdin echo '${{ secrets.CR_TOKEN }}' | docker login ${{ env.DOCKER_REGISTRY }} -u '${{ secrets.CR_USER }}' --password-stdin

View File

@@ -1,31 +0,0 @@
{
"hash": "e66d10e4",
"configHash": "bca2cdcc",
"lockfileHash": "5778a81f",
"browserHash": "5fea5472",
"optimized": {
"vue": {
"src": "../../../node_modules/vue/dist/vue.runtime.esm-bundler.js",
"file": "vue.js",
"fileHash": "cabb4131",
"needsInterop": false
},
"vitepress > @vue/devtools-api": {
"src": "../../../node_modules/@vue/devtools-api/dist/index.js",
"file": "vitepress___@vue_devtools-api.js",
"fileHash": "66e76a7b",
"needsInterop": false
},
"vitepress > @vueuse/core": {
"src": "../../../node_modules/@vueuse/core/index.mjs",
"file": "vitepress___@vueuse_core.js",
"fileHash": "6d04ab1e",
"needsInterop": false
}
},
"chunks": {
"chunk-EAEFJUV4": {
"file": "chunk-EAEFJUV4.js"
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +0,0 @@
{
"type": "module"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,343 +0,0 @@
import {
BaseTransition,
BaseTransitionPropsValidators,
Comment,
DeprecationTypes,
EffectScope,
ErrorCodes,
ErrorTypeStrings,
Fragment,
KeepAlive,
ReactiveEffect,
Static,
Suspense,
Teleport,
Text,
TrackOpTypes,
Transition,
TransitionGroup,
TriggerOpTypes,
VueElement,
assertNumber,
callWithAsyncErrorHandling,
callWithErrorHandling,
camelize,
capitalize,
cloneVNode,
compatUtils,
compile,
computed,
createApp,
createBaseVNode,
createBlock,
createCommentVNode,
createElementBlock,
createHydrationRenderer,
createPropsRestProxy,
createRenderer,
createSSRApp,
createSlots,
createStaticVNode,
createTextVNode,
createVNode,
customRef,
defineAsyncComponent,
defineComponent,
defineCustomElement,
defineEmits,
defineExpose,
defineModel,
defineOptions,
defineProps,
defineSSRCustomElement,
defineSlots,
devtools,
effect,
effectScope,
getCurrentInstance,
getCurrentScope,
getCurrentWatcher,
getTransitionRawChildren,
guardReactiveProps,
h,
handleError,
hasInjectionContext,
hydrate,
hydrateOnIdle,
hydrateOnInteraction,
hydrateOnMediaQuery,
hydrateOnVisible,
initCustomFormatter,
initDirectivesForSSR,
inject,
isMemoSame,
isProxy,
isReactive,
isReadonly,
isRef,
isRuntimeOnly,
isShallow,
isVNode,
markRaw,
mergeDefaults,
mergeModels,
mergeProps,
nextTick,
normalizeClass,
normalizeProps,
normalizeStyle,
onActivated,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onScopeDispose,
onServerPrefetch,
onUnmounted,
onUpdated,
onWatcherCleanup,
openBlock,
popScopeId,
provide,
proxyRefs,
pushScopeId,
queuePostFlushCb,
reactive,
readonly,
ref,
registerRuntimeCompiler,
render,
renderList,
renderSlot,
resolveComponent,
resolveDirective,
resolveDynamicComponent,
resolveFilter,
resolveTransitionHooks,
setBlockTracking,
setDevtoolsHook,
setTransitionHooks,
shallowReactive,
shallowReadonly,
shallowRef,
ssrContextKey,
ssrUtils,
stop,
toDisplayString,
toHandlerKey,
toHandlers,
toRaw,
toRef,
toRefs,
toValue,
transformVNodeArgs,
triggerRef,
unref,
useAttrs,
useCssModule,
useCssVars,
useHost,
useId,
useModel,
useSSRContext,
useShadowRoot,
useSlots,
useTemplateRef,
useTransitionState,
vModelCheckbox,
vModelDynamic,
vModelRadio,
vModelSelect,
vModelText,
vShow,
version,
warn,
watch,
watchEffect,
watchPostEffect,
watchSyncEffect,
withAsyncContext,
withCtx,
withDefaults,
withDirectives,
withKeys,
withMemo,
withModifiers,
withScopeId
} from "./chunk-EAEFJUV4.js";
export {
BaseTransition,
BaseTransitionPropsValidators,
Comment,
DeprecationTypes,
EffectScope,
ErrorCodes,
ErrorTypeStrings,
Fragment,
KeepAlive,
ReactiveEffect,
Static,
Suspense,
Teleport,
Text,
TrackOpTypes,
Transition,
TransitionGroup,
TriggerOpTypes,
VueElement,
assertNumber,
callWithAsyncErrorHandling,
callWithErrorHandling,
camelize,
capitalize,
cloneVNode,
compatUtils,
compile,
computed,
createApp,
createBlock,
createCommentVNode,
createElementBlock,
createBaseVNode as createElementVNode,
createHydrationRenderer,
createPropsRestProxy,
createRenderer,
createSSRApp,
createSlots,
createStaticVNode,
createTextVNode,
createVNode,
customRef,
defineAsyncComponent,
defineComponent,
defineCustomElement,
defineEmits,
defineExpose,
defineModel,
defineOptions,
defineProps,
defineSSRCustomElement,
defineSlots,
devtools,
effect,
effectScope,
getCurrentInstance,
getCurrentScope,
getCurrentWatcher,
getTransitionRawChildren,
guardReactiveProps,
h,
handleError,
hasInjectionContext,
hydrate,
hydrateOnIdle,
hydrateOnInteraction,
hydrateOnMediaQuery,
hydrateOnVisible,
initCustomFormatter,
initDirectivesForSSR,
inject,
isMemoSame,
isProxy,
isReactive,
isReadonly,
isRef,
isRuntimeOnly,
isShallow,
isVNode,
markRaw,
mergeDefaults,
mergeModels,
mergeProps,
nextTick,
normalizeClass,
normalizeProps,
normalizeStyle,
onActivated,
onBeforeMount,
onBeforeUnmount,
onBeforeUpdate,
onDeactivated,
onErrorCaptured,
onMounted,
onRenderTracked,
onRenderTriggered,
onScopeDispose,
onServerPrefetch,
onUnmounted,
onUpdated,
onWatcherCleanup,
openBlock,
popScopeId,
provide,
proxyRefs,
pushScopeId,
queuePostFlushCb,
reactive,
readonly,
ref,
registerRuntimeCompiler,
render,
renderList,
renderSlot,
resolveComponent,
resolveDirective,
resolveDynamicComponent,
resolveFilter,
resolveTransitionHooks,
setBlockTracking,
setDevtoolsHook,
setTransitionHooks,
shallowReactive,
shallowReadonly,
shallowRef,
ssrContextKey,
ssrUtils,
stop,
toDisplayString,
toHandlerKey,
toHandlers,
toRaw,
toRef,
toRefs,
toValue,
transformVNodeArgs,
triggerRef,
unref,
useAttrs,
useCssModule,
useCssVars,
useHost,
useId,
useModel,
useSSRContext,
useShadowRoot,
useSlots,
useTemplateRef,
useTransitionState,
vModelCheckbox,
vModelDynamic,
vModelRadio,
vModelSelect,
vModelText,
vShow,
version,
warn,
watch,
watchEffect,
watchPostEffect,
watchSyncEffect,
withAsyncContext,
withCtx,
withDefaults,
withDirectives,
withKeys,
withMemo,
withModifiers,
withScopeId
};
//# sourceMappingURL=vue.js.map

View File

@@ -1,7 +0,0 @@
{
"version": 3,
"sources": [],
"sourcesContent": [],
"mappings": "",
"names": []
}

View File

@@ -9,9 +9,9 @@ const ruSidebar = [
text: 'Базовые правила', text: 'Базовые правила',
items: [ items: [
{ text: 'Технологии и библиотеки', link: '/basics/tech-stack' }, { text: 'Технологии и библиотеки', link: '/basics/tech-stack' },
{ text: 'Именование', link: '/basics/naming' },
{ text: 'Архитектура', link: '/basics/architecture' }, { text: 'Архитектура', link: '/basics/architecture' },
{ text: 'Стиль кода', link: '/basics/code-style' }, { text: 'Стиль кода', link: '/basics/code-style' },
{ text: 'Именование', link: '/basics/naming' },
{ text: 'Документирование', link: '/basics/documentation' }, { text: 'Документирование', link: '/basics/documentation' },
{ text: 'Типизация', link: '/basics/typing' }, { text: 'Типизация', link: '/basics/typing' },
], ],
@@ -19,10 +19,9 @@ const ruSidebar = [
{ {
text: 'Прикладные разделы', text: 'Прикладные разделы',
items: [ items: [
{ text: 'Настройка VS Code', link: '/applied/vscode' },
{ text: 'Структура проекта', link: '/applied/project-structure' }, { text: 'Структура проекта', link: '/applied/project-structure' },
{ text: 'Компоненты', link: '/applied/components' }, { text: 'Компоненты', link: '/applied/components' },
{ text: 'Page-level компоненты', link: '/applied/page-level' }, { text: 'Страницы (App Router)', link: '/applied/page-level' },
{ text: 'Шаблоны и генерация кода', link: '/applied/templates-generation' }, { text: 'Шаблоны и генерация кода', link: '/applied/templates-generation' },
{ text: 'Стили', link: '/applied/styles' }, { text: 'Стили', link: '/applied/styles' },
{ text: 'Изображения', link: '/applied/images-sprites' }, { text: 'Изображения', link: '/applied/images-sprites' },
@@ -33,6 +32,7 @@ const ruSidebar = [
{ text: 'Хуки', link: '/applied/hooks' }, { text: 'Хуки', link: '/applied/hooks' },
{ text: 'Шрифты', link: '/applied/fonts' }, { text: 'Шрифты', link: '/applied/fonts' },
{ text: 'Локализация', link: '/applied/localization' }, { text: 'Локализация', link: '/applied/localization' },
{ text: 'Настройка VS Code', link: '/applied/vscode' },
], ],
}, },
]; ];

View File

@@ -1,32 +1,13 @@
# NextJS Style Guide — правила для агентов # Правила для агентов
Это проект документации (VitePress). Агент является основным писателем контента в этом проекте — записывает, оформляет и редактирует материал по указаниям пользователя. При работе с документацией следовать правилам из CONTRIBUTING.md.
## Документация - Язык документации и коммитов — русский.
- Исходники документации — в `src/`, только `.md` файлы.
### Tip-блоки со ссылками - Скрипты и манифесты сборки — в `scripts/`.
При создании или редактировании документации добавлять tip-блоки (`::: tip`) - Общие правила — в `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`.
::: tip Заголовок блока
Описание — [Название раздела](/путь).
:::
```
Заголовок обязателен — он должен кратко описывать о чём блок.
Описание должно объяснять что найдёт читатель по ссылке.
### Структура разделов
- **Workflow** — порядок действий ("что делать и в каком порядке")
- **Базовые правила** — стандарты и конвенции ("каким должен быть код")
- **Прикладные разделы** — конфигурация и устройство конкретной области ("как это настроить и использовать")
Не дублировать информацию между разделами — использовать ссылки.
### Единообразие
- Заголовок страницы (h1) совпадает с названием в sidebar.
- Описание раздела (текст после h1) раскрывает смысл через "Как...".
- Не описывать инструменты генерации в каждом разделе — ссылаться на прикладной раздел "Шаблоны и генерация кода".

155
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,155 @@
# Правила написания документации
Как писать и редактировать разделы стайлгайда.
## Типы разделов
### Базовые правила (`basics/`)
**Отвечает на вопрос:** «Каким должен быть любой код?»
Универсальные стандарты, не привязанные к конкретной области.
Правило базовое, если оно применимо ко всему коду одинаково.
**Граница:** если правило касается только одной области — оно прикладное.
### Прикладные разделы (`applied/`)
**Отвечает на вопрос:** «Как работать с X?»
Полное описание конкретной области: структура файлов, правила, именование, типизация, примеры.
**Граница:** не дублирует базовые правила. Если правило уже описано в базовых — ссылается, но не повторяет.
### Триггеры (`triggers/`)
**Отвечает на вопрос:** «Как выполнить задачу X?»
Конкретная инструкция: какие разделы прочитать, какие шаги выполнить. Триггер ссылается на basics/ и applied/, но не дублирует их. Группируются по роли: `triggers/develop/`, `triggers/review/`, `triggers/architect/`.
Структура триггера:
- **Заголовок** — глагол + объект ("Создать компонент", "Добавить иконку")
- **Описание** — одно предложение: что делает триггер
- **Прочитай перед началом** — ссылки на basics/ и applied/
- **Шаги** — нумерованный список действий со ссылками
- **Смежные триггеры** — ссылки на связанные задачи
- **Проверь себя** — чеклист из 2-5 пунктов для самопроверки
### Фреймворк-специфичные (`{framework}/`)
Разделы и триггеры, которые применимы только к конкретному фреймворку. Те же категории — `applied/` и `triggers/`.
**Граница:** если правило одинаково для всех фреймворков — оно в `base/`.
## Frontmatter
Каждый `.md`-файл начинается с YAML frontmatter:
```yaml
---
title: Название раздела
scope: basics | applied | triggers
keywords: [ключевое слово 1, ключевое слово 2]
when: "Когда агенту читать этот раздел"
---
```
| Поле | Описание |
|------|----------|
| `title` | Название раздела. Совпадает с `h1` в файле |
| `scope` | Тип: `basics`, `applied` или `triggers` |
| `keywords` | Ключевые слова для поиска агентом |
| `when` | Описание ситуации, когда раздел релевантен |
## Структура прикладного раздела
Раздел включает только релевантные секции — пустые не создаются.
```markdown
# {Название}
Краткое описание: о чём раздел.
## Что нужно знать
Неочевидная вводная информация (если есть).
## Структура
Файловая организация. Обязательно — дерево файлов.
## Правила
### Реализация
Как писать код: синтаксис, паттерны, API.
### Организация
Где что лежит: файловые границы, зоны ответственности, экспорт.
## Именование
Специфичные для области соглашения (не покрытые в basics/naming).
## Типизация
Специфичные для области правила (не покрытые в basics/typing).
## Документирование
Специфичные для области правила (не покрытые в basics/documentation).
## Примеры
Полноценные примеры кода с путями к файлам.
```
Порядок фиксированный: контекст -> структура -> правила -> специализации базовых -> примеры.
## Конвенции оформления
### Заголовки
- Один `h1` на файл — совпадает с `title` из frontmatter.
- Сразу после `h1` — вводный абзац.
- Основные секции — `h2`. Подсекции — `h3`. `h4` не используется.
### Примеры кода
- Блоки кода с указанием языка: ` ```tsx `, ` ```css `, ` ```bash `, ` ```text `.
- Путь к файлу — перед блоком кода или комментарием внутри.
- Дерево файлов — ` ```text ` с символами `├──`, `└──`, `│`.
### Блоки «Хорошо / Плохо»
```markdown
**Хорошо:**
\`\`\`tsx
// правильный код
\`\`\`
**Плохо:**
\`\`\`tsx
// неправильный код
\`\`\`
```
### Таблицы
Формат — стандартный Markdown: `| Ключ | Описание |`.
### Ссылки между разделами
Ссылаться можно, дублировать содержимое — нет.
## Принципы
1. **Не дублировать.** Одна мысль — одно место. Остальные ссылаются.
2. **Базовое vs прикладное.** Применимо ко всему коду — базовое. К одной области — прикладное.
3. **Общее vs специфичное.** Одинаково для всех фреймворков — в `base/`. Для одного — в `{framework}/`.
4. **Пустые секции не создавать.**
5. **Примеры обязательны.** Прикладной раздел без примеров — незавершён.

View File

@@ -1,19 +0,0 @@
# Ассистент
## Для ассистента
- Всегда используй Русский язык для общения и генерации документации/комментариев/коммитов.
- Всегда следуй этим правилам при генерации кода и ответах.
- Всегда пиши план действий перед генерацией кода.
- Всегда спрашивай разрешения у пользователя перед генерацией кода.
- Всегда проверяй, что код соответствует линтингу и форматированию.
- Всегда сверяйся с чек-листом при генерации кода.
- Не предлагай решения, которые противоречат этим правилам этого файла.
- Если не уверен — уточни у пользователя, не гадай, не придумывай.
## Обязательность чек-листов
- Все чек-листы, приведённые в правилах, обязательны к исполнению.
- Ассистент обязан сверяться с чек-листом при выполнении любой задачи, связанной с кодом.
- Нельзя сокращать, игнорировать или опускать пункты чек-листа — каждый пункт должен быть выполнен или явно отмечен как невыполнимый с объяснением причины.
- В каждом ответе, связанном с генерацией или изменением кода, ассистент обязан ссылаться на соответствующий чек-лист и подтверждать его выполнение.

View File

@@ -1,84 +0,0 @@
---
title: Stores
---
# Stores
## Сторы (Stores)
> В этом разделе собраны основные правила и рекомендации по созданию и оформлению сторов. Следуйте этим принципам, чтобы обеспечить чистую архитектуру, удобство поддержки и единый стиль работы с состоянием в проекте.
> В проекте для организации состояния используется только библиотека Zustand.
### Структура
- Store размещается в файле `<store-name>.store.ts` в папке `stores/` на своём уровне абстракции согласно архитектуре проекта.
- Интерфейс состояния описывается в этом же файле с суффиксом `State` (PascalCase).
- Для каждого store создаётся отдельный хук доступа (например, `useTodoStore`).
- Для глобальных сторов используйте только `shared/store`.
### Именование
- Соблюдайте [правила именования файлов и папок](#правила-именования-файлов-и-папок):
- Файл store — `<store-name>.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<TodoStoreState>((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-name>.store.ts` на своём уровне абстракции согласно архитектуре проекта.
- [ ] Именование файлов и сущностей соответствует [правилам именования файлов и папок](#правила-именования-файлов-и-папок).
- [ ] Все поля и методы строго типизированы (см. [общие правила типизации](#общие-правила-типизации)).
- [ ] В store только состояние и методы управления им, без бизнес-логики и side-effects.
- [ ] Для методов, изменяющих состояние через set, используется функция с return с новой строки.
- [ ] Документировано только назначение store и смысл полей (см. [правила документирования кода](#правило-для-документирования-кода)).
- [ ] Нет неиспользуемого или невалидного кода.
- [ ] Экспорт через индексный файл.

View File

@@ -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 или используются переменные.

View File

@@ -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.

View File

@@ -1,68 +0,0 @@
# Хуки (React Hooks)
> В проекте для создания пользовательских хуков используется только React (функциональные компоненты и хуки).
> В этом разделе собраны основные правила и рекомендации по созданию и оформлению хуков. Следуйте этим принципам, чтобы обеспечить чистую архитектуру, переиспользуемость и единый стиль работы с хуками в проекте.
## Рекомендации по использованию сторонних хуков
- Если есть возможность, используйте хуки Mantine в компонентах и кастомных хуках для работы с состоянием, темизацией, медиа-запросами и другими возможностями библиотеки.
- Не дублируйте функциональность, уже реализованную в Mantine.
## Структура
- Каждый хук размещается в отдельном файле с именем `use-<hook-name>.hook.ts` в папке `hooks/` на своём уровне абстракции согласно архитектуре проекта.
- Имя хука — в стиле camelCase с префиксом `use` (например, `useTodoFilter`).
- Для сложных возвращаемых структур использовать отдельные типы или интерфейсы, размещая их в папке `types/` на своём уровне абстракции.
## Именование
- Соблюдайте [правила именования файлов и папок](#правила-именования-файлов-и-папок):
- Файл хука — `use-<hook-name>.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-name>.hook.ts` в папке `hooks/` на своём уровне абстракции согласно архитектуре проекта.
- [ ] Именование файлов и сущностей соответствует [правилам именования файлов и папок](#правила-именования-файлов-и-папок).
- [ ] Все параметры, возвращаемые значения и внутренние переменные строго типизированы.
- [ ] Вся бизнес-логика изолирована в рамках слоя/feature.
- [ ] Нет дублирования логики между хуками.
- [ ] Для мемоизации используется useMemo/useCallback.
- [ ] Не используются side-effects вне useEffect/useLayoutEffect.
- [ ] Документировано только назначение хука (см. [правила документирования кода](#правило-для-документирования-кода)).
- [ ] Нет неиспользуемого или невалидного кода.
- [ ] Экспорт только именованный через индексный файл.

View File

@@ -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/<client-name>/` и имеет собственную структуру согласно архитектуре проекта.
## Структура
- Каждый API-хук размещается в отдельном файле с именем `use-<method-name>.hook-api.ts` в папке `hooks/api/<client-name>/` на своём уровне абстракции согласно архитектуре проекта.
- Имя хука — в стиле camelCase с префиксом `use` (например, `useGetUser`).
- Для сложных возвращаемых структур используйте отдельные типы или интерфейсы, размещая их в папке `types/` на своём уровне абстракции.
## Именование
- Соблюдайте [правила именования файлов и папок](#правила-именования-файлов-и-папок):
- Файл хука — `use-<method-name>.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<UserDto>('/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 <div>Загрузка...</div>;
}
if (error) {
return <div>Ошибка загрузки данных</div>;
}
if (!data) {
return <div>Нет данных о пользователе</div>;
}
return (
<div>
<div>Имя: {data.name}</div>
<div>Email: {data.email}</div>
</div>
);
};
```
## Чек-лист для создания API-хука
- [ ] Для каждого GET-запроса создан отдельный хук.
- [ ] Хук размещён в `hooks/api/<client-name>/use-<method-name>.hook-api.ts` на своём уровне абстракции согласно архитектуре проекта.
- [ ] Именование файлов и сущностей соответствует [правилам именования файлов и папок](#правила-именования-файлов-и-папок).
- [ ] Используется SWR для получения данных.
- [ ] Все параметры, возвращаемые значения и внутренние переменные строго типизированы.
- [ ] Нет дублирования логики между хуками.
- [ ] Не используются side-effects вне useEffect/useLayoutEffect.
- [ ] Документировано только назначение хука (см. [правила документирования кода](#правило-для-документирования-кода)).
- [ ] Нет неиспользуемого или невалидного кода.
- [ ] Экспорт только именованный через индексный файл.
---
## Чек-лист для использования API-хука
- [ ] Импортируется только нужный хук через публичные экспорты (`index.ts`).
- [ ] Использование хука строго по назначению (только для получения данных).
- [ ] Если требуется получить данные через GET-запрос в компоненте — обязательно используется соответствующий API-хук.
**Запрещено вызывать GET-методы API напрямую в компонентах, только через хуки.**
- [ ] Обработка состояний загрузки, ошибки и данных реализована корректно.
- [ ] Не происходит дублирования логики, связанной с получением данных.
- [ ] Нет неиспользуемого или невалидного кода.

View File

@@ -1,242 +0,0 @@
# API
> В этом разделе собраны основные правила и рекомендации по созданию, оформлению и использованию API-клиентов и функций для работы с сервером. Следуйте этим принципам, чтобы обеспечить единый стиль, безопасность и удобство поддержки API-слоя в проекте.
## Описание и назначение API-клиента
API-клиент — это модуль (папка), отвечающий за взаимодействие с конкретным внешним или внутренним API.
В проекте для HTTP-запросов используется только Axios.
API-клиент инкапсулирует:
- инициализацию экземпляра Axios,
- настройку базового URL, интерцепторов, обработчиков ошибок,
- организацию всех сущностей и методов для работы с этим API (например, users, auth, orders и т.д.),
- экспорт всех функций, типов и fetcher через индексные файлы.
Каждый API-клиент размещается в папке `src/shared/api/<client-name>/` и имеет собственную структуру согласно архитектуре проекта.
## Использование методов 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 и т.д.).
- **`<entity>/`**
Папка для отдельной сущности. Имя — в kebab-case, отражает бизнес-область (например, users, auth).
- **`<operation>.api.ts`**
Файл для каждой операции (CRUD, спец. действия).
Внутри:
- DTO (интерфейсы запроса/ответа)
- Функция, реализующая запрос через client
- **index.ts (внутри `<entity>`/)**
Экспортирует все методы и типы этой сущности.
- **index.ts (внутри entities/)**
Экспортирует все сущности (users, auth и т.д.).
## Именование
- Соблюдайте [правила именования файлов и папок](#правила-именования-файлов-и-папок):
- Файл клиента — `client.ts`.
- Файл функции — `<operation>-<entity>.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 (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={e => setEmail(e.target.value)}
placeholder="Email"
required
/>
<input
type="password"
value={password}
onChange={e => setPassword(e.target.value)}
placeholder="Пароль"
required
/>
<button type="submit">Создать пользователя</button>
</form>
);
};
```
## Чек-лист для создания клиента
- [ ] Новый клиент размещён в `src/shared/api/<client-name>/`.
- [ ] В корне клиента есть client.ts (экземпляр Axios) и index.ts (главный экспорт).
- [ ] Все бизнес-сущности размещены в entities/, каждая — в отдельной папке.
- [ ] Для каждой операции создан отдельный файл `<operation>`.api.ts с DTO и функцией.
- [ ] DTO объявлен непосредственно перед функцией.
- [ ] В каждой папке сущности есть свой index.ts для экспорта методов и типов.
- [ ] В папке entities/ есть общий index.ts для экспорта всех сущностей.
- [ ] Все экспорты организованы через индексные файлы.
- [ ] Для каждого GET-метода создан отдельный SWR-хук (см. правила API-хуков).
- [ ] Нет дублирования кода и неиспользуемых файлов.
## Чек-лист для использования API
- [ ] Импортируется только нужный метод через публичные экспорты (index.ts).
- [ ] Все вызовы API обёрнуты в try...catch.
- [ ] Используются только строго типизированные методы.
- [ ] Не происходит обращения к Axios напрямую — только через client.
- [ ] Нет дублирования логики и неиспользуемого кода.

View File

@@ -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) для локализации всех пользовательских текстов.

View File

@@ -1,22 +0,0 @@
---
title: Архитектура
---
# Архитектура
## Архитектура проекта
В проекте используется FSD (Feature-Sliced Design) архитектура.
- **FSD-границы**
- Не нарушать границы слоёв (например, feature не может импортировать из widgets).
- Бизнес-логика должна быть вынесена в хуки или сервисы.
- **Импорты**
- Внутри слоя — относительные импорты.
- Между слоями — абсолютные импорты.
- **Требования**
- Не смешивать логику разных слоёв.
- Не хранить бизнес-логику в UI-компонентах.
- **Именование**
- Файлы и папки kebab-case.
---

View File

@@ -1,74 +0,0 @@
---
title: Стиль кода
---
# Стиль кода
## Отступы
Используем 2 пробела для отступов во всём проекте. Не используем табы.
## Кавычки
Используем **одинарные кавычки** для строк в JavaScript/TypeScript, и **двойные кавычки** для атрибутов в JSX/TSX.
**Пример:**
```ts
// JavaScript/TypeScript
const message = 'Привет, мир!';
const name = 'ProjectName';
```
```tsx
// JSX/TSX
<input type="text" placeholder="Введите имя" />
<button title="Сохранить">Сохранить</button>
```
## Строгая типизация
всегда указывать типы для пропсов, возвращаемых значений, параметров функций.
## Ранние возвраты
(early return) для повышения читаемости.
## Мемоизация
Старайся оптимизировать код если это возможно.
## Документирование
Документируем ТОЛЬКО ОПИСАНИЕ (функций, компонентов, типов и их полей).
## any, unknown
запрещено использовать без крайней необходимости.
## Классы в TSX
Для стилизации компонентов используем CSS-модули и методологию BEM. Классы подключаются через объект стилей, импортированный из соответствующего `.module.css` файла.
> Объект стилей всегда импортируется с именем `s` (сокращённо от style), а не `styles`.
**Пример:**
```tsx
import s from './my-component.module.css';
export const MyComponent = () => (
<div className={s['my-component']}>
<button className={s['my-component__button']}>Кнопка</button>
<span className={s['my-component__text']}>Текст</span>
<button className={s['my-component__button'] + ' ' + s._active}>
Активная кнопка
</button>
</div>
);
```
- Имя класса всегда берётся из объекта `s`.
- Для модификаторов используется отдельный класс с нижним подчёркиванием (например, `s._active`).
- Не используйте строковые литералы с классами напрямую — только через объект `s`.

View File

@@ -1,18 +0,0 @@
---
title: Именование
---
# Именование
## Именование файлов и папок
- Папка компонента: kebab-case, совпадает с названием компонента, пример: `component-name`.
- React-компонент: kebab-case, совпадает с названием компонента, пример: `component-name.tsx`.
- Стили: kebab-case, шаблон: `<style-name>.module.css`, пример: `style-name.module.css`.
- Интерфейсы: kebab-case, шаблон: `<interface-name>.interface.ts`, пример: `interface-name.interface.ts`.
- Типы: kebab-case, шаблон: `<type-name>.type.ts`, пример: `type-name.type.ts`.
- Enum: kebab-case, шаблон: `<enum-name>.enum.ts`, пример: `enum-name.enum.ts`.
- Схемы: kebab-case, шаблон: `<schema-name>.schema.ts`, пример: `schema-name.schema.ts`.
- Локализация: kebab-case, пример: `ru.json`, `en.json`.
- Утилиты: kebab-case, шаблон: `<util-name>.util.ts`, пример: `util-name.util.ts`
- React Hooks: kebab-case, шаблон: `use-<hook-name>.hook.ts`, пример: `use-hook-name.hook.ts`
- Хранилища состояния компонента: kebab-case, шаблон: `<store-name>.store.ts`, пример: `store-name.store.ts`

View File

@@ -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 — статус выполнения
*/
```

View File

@@ -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<TodoListProps> = memo(({ items }) => (
<ul>
{items.map((item) => (
<li key={item.id}>{item.text}</li>
))}
</ul>
));
```
#### Типизация функций и коллбеков (инлайн)
```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<TodoItem[]> => {
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<AxiosResponse<TodoItem[]>> => {
// ...
};
```
### Чек-лист проверки типизации
- [ ] Все пропсы компонентов явно типизированы через интерфейс или тип в папке `types/`.
- [ ] Все параметры и возвращаемые значения функций и методов явно типизированы.
- [ ] Все переменные состояния (в том числе в store) имеют явные типы.
- [ ] Все интерфейсы, типы и enum размещены в папке `types/` на своём уровне абстракции.
- [ ] Ключи всех enum написаны ЗАГЛАВНЫМИ_БУКВАМИ (SCREAMING_SNAKE_CASE).
- [ ] Все DTO размещены в папке `dto/` на своём уровне абстракции.
- [ ] Не используется `any` и `unknown` без крайней необходимости и поясняющего комментария.
- [ ] Для сложных структур используются отдельные интерфейсы или типы.
- [ ] Для массивов и объектов указан тип элементов/ключей.
- [ ] Для асинхронных функций указан тип Promise с конкретным типом результата.
- [ ] Типы коллбеков и функций, передаваемых в пропсы, указаны инлайн.
- [ ] Не используются устаревшие типы (`Function`, `Object`, `{}`).
- [ ] Для внешних библиотек используются официальные типы или собственные декларации.
- [ ] Нет неявного приведения типов, все типы читаемы и прозрачны.

View File

@@ -1,12 +0,0 @@
---
title: Локализация
---
# Локализация
## Правила использования локализации
- Все пользовательские тексты должны быть вынесены в локализационные файлы.
- Для каждого компонента создавать папку `locales/` с файлами `ru.json`, `en.json` и т.д.
- Новые namespace обязательно регистрировать в экземпляре i18n (см. `app/i18n.ts`).
- В коде использовать только функцию перевода из i18n, не использовать "жёстко" прописанные строки.

View File

@@ -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 | dist/ # Собранные версии (gitignore)
|---------|---------------------| ├── ai/{framework}/ # Для AI-агентов
| Getting Started | What tools to install before starting development? | └── vitepress/{framework}/ # Для людей (планируется)
| 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. ```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, FC? |
### 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, FC? |
| 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`.

View File

@@ -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, FC? |
### Прикладные разделы
**Как это настроить и использовать** — конфигурация, структура и примеры кода для конкретных областей.
| Раздел | Отвечает на вопрос |
|--------|-------------------|
| Настройка VS Code | Как настроить редактор для проекта? |
| Структура проекта | Как организованы папки и файлы по FSD? |
| Компоненты | Как устроен компонент: файлы, пропсы, clsx, FC? |
| Page-level компоненты | Как описывать layout, page, loading, error, not-found? |
| Шаблоны и генерация кода | Как работают шаблоны, синтаксис и инструменты генерации? |
| Стили | Как писать CSS: PostCSS Modules, вложенность, медиа, токены? |
| Изображения | _(не заполнен)_ |
| SVG-спрайты | _(не заполнен)_ |
| Видео | _(не заполнен)_ |
| API | _(не заполнен)_ |
| Stores | _(не заполнен)_ |
| Хуки | _(не заполнен)_ |
| Шрифты | _(не заполнен)_ |
| Локализация | _(не заполнен)_ |

View File

@@ -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/architecture.md",
"basics/code-style.md",
"basics/naming.md",
"basics/documentation.md",
"basics/typing.md",
// applied
"applied/vscode.md",
"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",
];
// Удалить 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(`<!-- ${route} -->\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");

View File

@@ -1,5 +0,0 @@
---
title: API
---
# API

View File

@@ -1,7 +0,0 @@
---
title: Components
---
# Components
Rules for creating UI components across all FSD layers.

View File

@@ -1,5 +0,0 @@
---
title: Fonts
---
# Fonts

View File

@@ -1,5 +0,0 @@
---
title: Hooks
---
# Hooks

View File

@@ -1,5 +0,0 @@
---
title: Images
---
# Images

View File

@@ -1,5 +0,0 @@
---
title: Localization
---
# Localization

View File

@@ -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`.

View File

@@ -1,7 +0,0 @@
---
title: Project Structure
---
# Project Structure
Base project structure and principles of module organization at folder and file level.

View File

@@ -1,5 +0,0 @@
---
title: Stores
---
# Stores

View File

@@ -1,7 +0,0 @@
---
title: Styles
---
# Styles
CSS writing rules: PostCSS Modules, nesting, media queries, variables, formatting.

View File

@@ -1,5 +0,0 @@
---
title: SVG Sprites
---
# SVG Sprites

View File

@@ -1,7 +0,0 @@
---
title: Templates & Code Generation
---
# Templates & Code Generation
Template tools, syntax, and examples for code generation.

View File

@@ -1,5 +0,0 @@
---
title: Video
---
# Video

View File

@@ -1,7 +0,0 @@
---
title: Architecture
---
# Architecture
Architecture based on FSD (Feature-Sliced Design) and strict module boundaries.

View File

@@ -1,7 +0,0 @@
---
title: Code Style
---
# Code Style
Unified code formatting rules: indentation, line breaks, quotes, import order, and readability.

View File

@@ -1,7 +0,0 @@
---
title: Documentation
---
# Documentation
Documentation should help understand the purpose of an entity, not duplicate its types or obvious details.

View File

@@ -1,7 +0,0 @@
---
title: Naming
---
# Naming
Naming should be predictable, concise, and reflect the meaning of the entity.

View File

@@ -1,7 +0,0 @@
---
title: Tech Stack
---
# Tech Stack
Base technology stack and libraries used in projects.

View File

@@ -1,7 +0,0 @@
---
title: Typing
---
# Typing
Typing is required for all public interfaces, functions, and components.

View File

@@ -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, FC? |
### 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, FC? |
| 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

View File

@@ -1,7 +0,0 @@
---
title: Creating an App
---
# Creating an App
How to create a new application: choosing a project template and initialization.

View File

@@ -1,7 +0,0 @@
---
title: Creating Components
---
# Creating Components
Generating components using templates, working with child components.

View File

@@ -1,7 +0,0 @@
---
title: Creating Pages
---
# Creating Pages
Page creation pattern: routing (page.tsx) and screen.

View File

@@ -1,7 +0,0 @@
---
title: Data Fetching
---
# Data Fetching
How to fetch data: SWR, API client codegen, sockets.

View File

@@ -1,7 +0,0 @@
---
title: Getting Started
---
# Getting Started
Setting up the environment and installing tools before starting development.

View File

@@ -1,7 +0,0 @@
---
title: Localization
---
# Localization
How to add translations and work with i18next.

View File

@@ -1,7 +0,0 @@
---
title: State Management
---
# State Management
When and how to create a store (Zustand), what to store locally vs globally.

View File

@@ -1,7 +0,0 @@
---
title: Styling
---
# Styling
Styling tools priority and rules for their application.

View File

View File

@@ -1,89 +0,0 @@
---
title: Компоненты
---
# Компоненты
Раздел описывает правила создания UIкомпонентов. Эти правила обязательны для всех слоёв FSD: `app`, `screens`, `layouts`, `widgets`, `features`, `entities`, `shared`.
## Базовая структура компонента
Минимальный набор файлов: компонент, стили, типы и публичный экспорт.
```text
container/
├── styles/
│ └── container.module.css
├── types/
│ └── container.interface.ts
├── container.tsx
└── index.ts
```
## Пример базового компонента
`styles/container.module.css`
```scss
.root {}
```
В CSS Modules использование имени класса **.root** — это общепринятое соглашение (best practice)
`types/container.interface.ts`
```ts
import type { HTMLAttributes } from 'react'
/**
* Параметры контейнера.
*/
export interface ContainerProps extends HTMLAttributes<HTMLDivElement> {}
```
Интерфес параметров компонента всегда наследует свойства своего тега: div, button, итд..
`container.tsx`
```tsx
import type { FC } from 'react'
import cl from 'clsx'
import type { ContainerProps } from './types/container.interface'
import styles from './styles/container.module.css'
/**
* Контейнер с адаптивной максимальной шириной.
*
* Используется для:
* - ограничения ширины контента
* - центрирования содержимого
* - построения адаптивной сетки страницы
*/
export const Container: FC<ContainerProps> = ({ className, ...htmlAttr }) => {
return (
<div {...htmlAttr} className={cl(styles.root, className)}>
Container...
</div>
)
}
```
- Компонент объявляется через `const` и экспортируется именованно.
- Пропсы деструктурируются в сигнатуре; если их больше двух — деструктуризацию переносим в тело компонента.
- Из пропсов отдельно извлекаются `className` и `...htmlAttr`, чтобы корректно объединять классы и прокидывать остальные атрибуты.
- `cl` — короткое имя функции для конкатенации CSSклассов.
- `FC<>` используется для декларации `children`.
`index.ts`
```ts
export { Container } from './container'
```
## Шаблоны и генерация кода
Создание компонентов — **только через шаблоны**. Ручное создание файловой структуры компонента запрещено. Это обеспечивает единообразие каркаса, одинаковые папки и имена файлов, уменьшает ручные ошибки и ускоряет старт работы.
После генерации через **@gromlab/create** — проверить название компонента/файлов и заполнить описание назначения. Подробный порядок действий и перечень обязательных шаблонов — в разделе «Workflow».
## Вложенные (дочерние) компоненты
Если для реализации функционала нужны компоненты, которые используются только внутри текущего компонента, создавайте их как вложенные в папке `ui/`. Такие компоненты не экспортируются наружу и используются только локально.
Вложенные компоненты подчиняются тем же правилам по структуре, именованию и стилю (включая папку `styles/` для их стилей).

View File

@@ -1,182 +0,0 @@
---
title: Page-level компоненты
---
# Page-level компоненты
Специальные файлы Next.js App Router, которые фреймворк использует по соглашению: `layout.tsx`, `page.tsx`, `loading.tsx`, `error.tsx`, `not-found.tsx`, `template.tsx`.
## Общие правила
- Экспорт через `export default function` — конвенция Next.js.
- Типизация через `PropsWithChildren` или явный интерфейс.
- Каждая страница (`page.tsx`) должна содержать `metadata` с `title` и `description`.
- Минимум логики — page-level компоненты делегируют работу экранам, виджетам и фичам.
- Стили в page-level компонентах не используются — стилизация внутри вызываемых компонентов.
## layout.tsx
Корневой layout — точка подключения провайдеров, глобальных стилей и метаданных.
```tsx
import type { PropsWithChildren } from 'react'
import type { Metadata } from 'next'
import { Providers } from './providers'
import './styles/index.css'
export const metadata: Metadata = {
title: {
default: 'App',
template: '%s | App',
},
description: 'Описание приложения',
metadataBase: new URL('https://example.com'),
openGraph: {
type: 'website',
locale: 'ru_RU',
siteName: 'App',
images: [
{
url: '/og-image.png',
width: 1200,
height: 630,
alt: 'App',
},
],
},
twitter: {
card: 'summary_large_image',
},
}
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="ru" suppressHydrationWarning>
<body>
<Providers>
{children}
</Providers>
</body>
</html>
)
}
```
Вложенный layout — для секции с общей обёрткой (sidebar, header):
```tsx
import type { PropsWithChildren } from 'react'
import { DashboardLayout } from '@/shared/ui/dashboard-layout'
export default function Layout({ children }: PropsWithChildren) {
return (
<DashboardLayout>
{children}
</DashboardLayout>
)
}
```
## page.tsx
Тонкий файл — только импорт и рендер экрана. Логика, стили и зависимости размещаются в экране, не в `page.tsx`.
```tsx
import type { Metadata } from 'next'
import { HomeScreen } from '@/screens/home'
export const metadata: Metadata = {
title: 'Главная',
description: 'Главная страница приложения',
}
export default function HomePage() {
return <HomeScreen />
}
```
С параметрами маршрута:
```tsx
import type { Metadata } from 'next'
import { ProfileScreen } from '@/screens/profile'
export const metadata: Metadata = {
title: 'Профиль',
description: 'Страница профиля пользователя',
}
interface ProfilePageProps {
params: Promise<{ id: string }>
}
export default async function ProfilePage({ params }: ProfilePageProps) {
const { id } = await params
return <ProfileScreen id={id} />
}
```
Каждая страница должна содержать `metadata` с `title` — он подставится в шаблон из корневого layout: `Профиль | App`.
## loading.tsx
Состояние загрузки. Показывается пока загружается контент страницы.
```tsx
export default function Loading() {
return <div>Загрузка...</div>
}
```
## error.tsx
Обработка ошибок. Обязательно `'use client'` — error boundary работает только на клиенте. Разметку выносим в экран.
```tsx
'use client'
import type { FC } from 'react'
import { ErrorScreen } from '@/screens/error'
interface ErrorPageProps {
error: Error & { digest?: string }
reset: () => void
}
const ErrorPage: FC<ErrorPageProps> = ({ error, reset }) => {
return <ErrorScreen error={error} reset={reset} />
}
export default ErrorPage
```
## not-found.tsx
Страница 404. Показывается когда маршрут не найден. Разметку выносим в экран.
```tsx
import type { Metadata } from 'next'
import { NotFoundScreen } from '@/screens/not-found'
export const metadata: Metadata = {
title: 'Страница не найдена',
description: 'Запрашиваемая страница не существует',
}
export default function NotFound() {
return <NotFoundScreen />
}
```
## template.tsx
Аналог layout, но пересоздаётся при каждой навигации (не сохраняет состояние). Используется редко — для анимаций переходов между страницами.
```tsx
import type { PropsWithChildren } from 'react'
export default function Template({ children }: PropsWithChildren) {
return <div>{children}</div>
}
```

View File

@@ -1,149 +0,0 @@
---
title: Структура проекта
---
# Структура проекта
Раздел описывает базовую структуру проекта Next.js (App Router) и принципы организации модулей на уровне папок и файлов.
## Базовая структура проекта
```text
src/
├── app/ # Слой app: роутинг, провайдеры, глобальные стили
│ ├── providers/ # Провайдеры и обёртки приложения
│ ├── styles/ # Глобальные стили, CSS-переменные, custom media
│ ├── layout.tsx # Корневой layout (провайдеры, стили, метаданные)
│ ├── page.tsx # Главная страница → HomeScreen
│ └── profile/
│ ├── page.tsx # → ProfileScreen
│ └── [id]/
│ └── page.tsx # → ProfileDetailScreen
├── screens/ # UI-компоненты страниц
│ ├── home/
│ │ ├── home.screen.tsx
│ │ └── index.ts
│ └── profile/
│ ├── profile.screen.tsx
│ └── index.ts
├── layouts/ # Общие шаблоны и каркасы страниц
│ └── main-layout/
│ ├── main-layout.layout.tsx
│ └── index.ts
├── widgets/ # Крупные блоки интерфейса
│ └── header/
│ ├── header.widget.tsx
│ └── index.ts
├── features/ # Пользовательские сценарии
│ └── auth-by-email/
│ ├── ui/
│ │ └── login-form.tsx
│ ├── model/
│ │ └── auth-by-email.store.ts
│ ├── auth-by-email.feature.tsx
│ └── index.ts
├── entities/ # Бизнес-сущности
│ └── user/
│ ├── model/
│ │ └── user.store.ts
│ ├── user.entity.tsx
│ └── index.ts
└── shared/ # Общие ресурсы проекта
├── ui/ # Повторно используемые UI-элементы
│ └── icon/
│ ├── styles/
│ │ └── icon.module.css
│ ├── types/
│ │ └── icon.interface.ts
│ ├── icon.tsx
│ └── index.ts
├── lib/ # Утилиты и хелперы
├── services/ # Общие сервисы и клиенты
├── config/ # Общие конфигурации и константы
└── assets/ # Ресурсы
├── images/
├── icons/
├── fonts/
└── video/
```
## Слой `app/`
Папка `app/` совмещает две роли: инициализация приложения (провайдеры, глобальные стили) и файловый роутинг Next.js (route-сегменты, `layout.tsx`, `page.tsx`).
- `providers/` и `styles/` -- это инфраструктура приложения, они не являются частью роутинга.
- Route-сегменты (вложенные папки с `page.tsx`) -- это роутинг Next.js. Они не содержат логики, только импортируют экраны из `screens/`.
Компоненты, хуки, стили и утилиты не размещаются внутри route-сегментов -- всё это живёт в соответствующих слоях FSD.
## Правила организации
- В слоях FSD (`features`, `entities`, `widgets`, `screens` и т.д.) `ui/` используется только для дочерних элементов, которые относятся к модулю и не экспортируются отдельно. Главные компоненты, которые составляют сам слой, держат собственные `*.feature.tsx`, `*.widget.tsx` и т. п., а `ui/` служит для вспомогательных мелких компонентов.
- В `shared/ui/` хранятся базовые UI-элементы/компоненты, которыми пользуются сразу несколько модулей; в этом случае они экспортируются наружу и не считаются «дочерними» для слоя.
- Если модуль строится вокруг «главного» компонента (`*.feature.tsx`, `*.screen.tsx`, `*.widget.tsx`), помещайте его в корень модуля и экспортируйте через `index.ts`. Проверяйте, что `ui/` не используется просто как «контейнер» слоя.
- Каждый слой и модуль хранится в собственной папке.
- Внутренние реализации разделяются на `ui/`, `model/`, `styles/`, `helpers/`, `lib/`, `api/`.
- Публичный API модуля объявляется в `index.ts`.
- Внутренние файлы не импортируются напрямую извне.
- Не смешивать ответственность разных слоёв в одном модуле.
## Пример организации структуры
**Плохо** -- плоская структура без архитектуры:
```text
src/
├── components/
│ ├── Header.tsx
│ ├── LoginForm.tsx
│ ├── UserCard.tsx
│ └── Button.tsx
├── hooks/
│ ├── useAuth.ts
│ └── useUser.ts
├── api/
│ ├── auth.ts
│ └── user.ts
├── styles/
│ ├── header.module.css
│ └── login.module.css
├── types/
│ └── user.ts
└── utils/
└── format.ts
```
Нет слоёв, нет границ ответственности -- Header и Button лежат рядом, хотя это разные уровни абстракции. LoginForm знает про API напрямую. При росте проекта `components/` превращается в свалку.
**Хорошо** -- та же функциональность в FSD:
```text
src/
├── widgets/
│ └── header/
│ ├── header.widget.tsx
│ └── index.ts
├── features/
│ └── auth-by-email/
│ ├── ui/
│ │ └── login-form.tsx
│ ├── model/
│ │ └── auth.store.ts
│ ├── auth-by-email.feature.tsx
│ └── index.ts
├── entities/
│ └── user/
│ ├── ui/
│ │ └── user-card.tsx
│ ├── model/
│ │ └── user.store.ts
│ ├── user.entity.tsx
│ └── index.ts
└── shared/
├── ui/
│ └── button/
│ ├── button.tsx
│ └── index.ts
└── lib/
└── format.ts
```
Каждый элемент на своём слое, с публичным API и чёткими границами ответственности.

View File

@@ -1,5 +0,0 @@
---
title: SVG-спрайты
---
# SVG-спрайты

View File

@@ -1,60 +0,0 @@
---
title: Архитектура
---
# Архитектура
Архитектура построена на FSD (`FeatureSliced Design`) и строгих границах модулей.
Цель — разделить ответственность, упростить сопровождение и контроль зависимостей.
## Принципы
- Разделять UI, бизнес-логику и инфраструктуру.
- Держать зависимости однонаправленными.
- Открывать наружу только публичный API модулей.
- Не допускать циклических зависимостей.
## Слои (FSD)
- **app** — инициализация приложения: провайдеры, глобальные стили. В Next.js эта же папка `app/` дополнительно содержит системные файлы роутинга (`layout.tsx`, `page.tsx`).
- **screens** — UI-компоненты страниц. Каждый экран — отдельный компонент, который собирает виджеты и фичи конкретной страницы. Роутинг только использует эти компоненты — он не является частью слоя `screens`. В Next.js файлы `page.tsx` остаются тонкими: импортируют экран и рендерят его.
- **layouts** — каркас и шаблоны страниц.
- **widgets** — крупные блоки интерфейса, собирающие несколько сценариев.
- **features** — отдельные пользовательские действия и сценарии.
- **entities** — бизнес-сущности и их модель.
- **shared** — переиспользуемая инфраструктура, утилиты и базовые UIкомпоненты.
## Модули (FSD)
- Модуль — это отдельная папка в слоях `screens`, `layouts`, `widgets`, `features`, `entities`, которая реализует один сценарий/блок. В корне модуля лежит главный файл (`*.screen.tsx`, `*.layout.tsx`, `*.widget.tsx`, `*.feature.tsx`, `*.entity.tsx`) и публичный API (`index.ts`).
- Внутри модуля используются подпапки (по необходимости):
- `ui/` — дочерние UIкомпоненты модуля.
- `model/` — состояние и бизнес‑логика модуля.
- `styles/` — локальные стили модуля.
- `helpers/` — локальные хелперы.
- `lib/` — утилиты модуля.
- `api/` — APIвызовы модуля.
## Правила зависимостей
- Допустимые импорты идут сверху вниз: `app → screens → layouts → widgets → features → entities → shared`.
- Импорты между слоями — через публичный API.
- Внутри одного слоя — относительные импорты.
## Публичный API модулей
- Каждый модуль экспортирует наружу только то, что нужно другим слоям.
- Внешние импорты идут только через `index`‑файл модуля.
- Внутренние файлы не импортируются напрямую извне.
## Границы ответственности
- Бизнес‑логика не размещается в UIкомпонентах.
- UIкомпоненты должны быть максимально простыми и предсказуемыми.
- Связь между независимыми сценариями поднимается на уровень выше.
## Типовые ошибки
- Импорт из более высокого слоя в более низкий.
- Смешивание логики нескольких слоёв в одном модуле.
- Прямые импорты внутренних файлов, минуя публичный API.

View File

@@ -1,64 +0,0 @@
---
title: Документирование
---
# Документирование
Документирование должно помогать понять назначение сущности, а не дублировать её типы или очевидные детали.
## Правила
- Документировать только назначение функций, компонентов, типов, интерфейсов и enum.
- Не документировать параметры, возвращаемые значения, типы пропсов и очевидные детали.
- В интерфейсах, типах и enum описывать только смысл поля или значения.
- Описание должно быть кратким, информативным и завершаться точкой.
## Примеры
**Хорошо**
```ts
/**
* Список задач пользователя.
*/
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 объект задачи
*/
// Плохо: описание очевидных деталей.
/**
* id — идентификатор задачи
* text — текст задачи
* completed — статус выполнения
*/
```

View File

@@ -1,41 +0,0 @@
---
title: Технологии и библиотеки
---
# Технологии и библиотеки
Базовый стек технологий и библиотек, на который опираются проекты и примеры в документации.
## Что используем
### Стек
- **React/TypeScript** — основной стек для UI и приложения.
- **Next.js** — для продуктовых сайтов.
### Архитектура
- **FSD (Feature-Sliced Design)** — структура проекта и границы модулей.
### UI компоненты
- **Mantine UI** — базовые UI-компоненты.
### Fetch (API)
- **@gromlab/api-codegen** — генерация APIклиентов и типов.
- **SWR** — получение, кеширование, ревалидация, дедубликация.
- **SWR (useSWRSubscription)** - сокеты, реалтайм подписки.
### Store
- **Zustand** — глобальное состояние.
### Локализация
- **i18next (i18n)** — локализация всех пользовательских текстов.
### Тестирование
- **Vitest** — тестирование.
### Стили
- **PostCSS Modules** — изоляция стилей.
- **Mobile First** — подход к адаптивной верстке.
- **clsx** — конкатенация CSSклассов.
### Генерация
- **@gromlab/create** — шаблонизатор для создания слоёв и других файлов из шаблонов.

View File

@@ -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, FC? |
### Прикладные разделы
**Как это настроить и использовать** — конфигурация, структура и примеры кода для конкретных областей.
| Раздел | Отвечает на вопрос |
|--------|-------------------|
| Настройка VS Code | Как настроить редактор для проекта? |
| Структура проекта | Как организованы папки и файлы по FSD? |
| Компоненты | Как устроен компонент: файлы, пропсы, clsx, FC? |
| Page-level компоненты | Как описывать layout, page, loading, error, not-found? |
| Шаблоны и генерация кода | Как работают шаблоны, синтаксис и инструменты генерации? |
| Стили | Как писать CSS: PostCSS Modules, вложенность, медиа, токены? |
| Изображения | _(не заполнен)_ |
| SVG-спрайты | _(не заполнен)_ |
| Видео | _(не заполнен)_ |
| API | _(не заполнен)_ |
| Stores | _(не заполнен)_ |
| Хуки | _(не заполнен)_ |
| Шрифты | _(не заполнен)_ |
| Локализация | _(не заполнен)_ |

View File

@@ -1,95 +0,0 @@
---
title: Workflow
---
# Workflow
Порядок действий при разработке — от создания проекта до реализации фич.
## Начало работы
Подготовка окружения перед началом разработки.
1. Открыть проект в VS Code.
2. Установить рекомендуемые расширения (редактор предложит автоматически).
3. Ознакомиться со стеком: Next.js (App Router), Mantine, Zustand, FSD.
## Создание проекта
Инициализация нового проекта из готового шаблона.
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.

View File

@@ -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).

View File

@@ -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 метаданные

View File

@@ -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).

View File

@@ -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).

View File

@@ -1,7 +0,0 @@
---
title: Получение данных
---
# Получение данных
Как получать данные с сервера — SWR, генерация API-клиентов, сокеты.

View File

@@ -1,7 +0,0 @@
---
title: Локализация
---
# Локализация
Как добавлять переводы и подключать локализацию через i18next.

View File

@@ -1,7 +0,0 @@
---
title: Управление состоянием
---
# Управление состоянием
Как работать с состоянием — когда создавать стор, что хранить локально и глобально.

View File

@@ -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).

View File

@@ -1,137 +0,0 @@
<!-- /index -->
# 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, FC? |
### 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, FC? |
| 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
<!-- /basics/tech-stack -->
## Tech Stack
Base technology stack and libraries used in projects.
<!-- /basics/architecture -->
## Architecture
Architecture based on FSD (Feature-Sliced Design) and strict module boundaries.
<!-- /basics/code-style -->
## Code Style
Unified code formatting rules: indentation, line breaks, quotes, import order, and readability.
<!-- /basics/naming -->
## Naming
Naming should be predictable, concise, and reflect the meaning of the entity.
<!-- /basics/documentation -->
## Documentation
Documentation should help understand the purpose of an entity, not duplicate its types or obvious details.
<!-- /basics/typing -->
## Typing
Typing is required for all public interfaces, functions, and components.
<!-- /applied/project-structure -->
## Project Structure
Base project structure and principles of module organization at folder and file level.
<!-- /applied/components -->
## Components
Rules for creating UI components across all FSD layers.
<!-- /applied/page-level -->
## 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`.
<!-- /applied/templates-generation -->
## Templates & Code Generation
Template tools, syntax, and examples for code generation.
<!-- /applied/styles -->
## Styles
CSS writing rules: PostCSS Modules, nesting, media queries, variables, formatting.
<!-- /applied/images-sprites -->
## Images
<!-- /applied/svg-sprites -->
## SVG Sprites
<!-- /applied/video -->
## Video
<!-- /applied/api -->
## API
<!-- /applied/stores -->
## Stores
<!-- /applied/hooks -->
## Hooks
<!-- /applied/fonts -->
## Fonts
<!-- /applied/localization -->
## Localization

File diff suppressed because it is too large Load Diff

23
notes Normal file
View File

@@ -0,0 +1,23 @@
# TODO
## Триггеры: классификация и расширение
Текущий список триггеров слабо проработан. Нужно:
1. Классифицировать триггеры по группам:
- Создание — новые модули, компоненты, страницы
- Ресурсы — ассеты (иконки, шрифты, изображения, видео)
- Данные — API, сторы, серверные данные, формы
- Навигация — роутинг, middleware, редиректы
- Модификация — рефакторинг, перенос, удаление
- Инфраструктура — зависимости, переводы, настройка окружения
2. Добавить недостающие триггеры. Примеры пробелов:
- Создание: утилита/хелпер, тип/интерфейс, контекст
- Данные: создать форму, добавить валидацию
- Навигация: динамический роут, middleware, редирект
- Модификация: рефакторинг компонента, перенос модуля, удаление модуля
- Обработка ошибок: error boundary, fallback UI, error.tsx, not-found.tsx, loading.tsx
- Авторизация: защита страницы, проверка прав
3. Обновить секцию "Триггеры" в DEVELOP.md — перейти на новые группы.

4
package-lock.json generated
View File

@@ -1,11 +1,11 @@
{ {
"name": "nextjs-style-guide", "name": "frontend-style-guide",
"version": "0.0.0", "version": "0.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "nextjs-style-guide", "name": "frontend-style-guide",
"version": "0.0.0", "version": "0.0.0",
"devDependencies": { "devDependencies": {
"vitepress": "^1.6.3" "vitepress": "^1.6.3"

View File

@@ -1,10 +1,10 @@
{ {
"name": "nextjs-style-guide", "name": "frontend-style-guide",
"private": true, "private": true,
"type": "module", "type": "module",
"version": "0.0.0", "version": "0.0.0",
"scripts": { "scripts": {
"docs": "node ./concat-md.js", "build:ai": "node ./scripts/build-ai.js",
"dev": "vitepress dev .", "dev": "vitepress dev .",
"build": "vitepress build .", "build": "vitepress build .",
"serve": "vitepress serve ." "serve": "vitepress serve ."

88
scripts/build-ai.js Normal file
View File

@@ -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Все сборки завершены.");

69
scripts/nextjs.build.js Normal file
View File

@@ -0,0 +1,69 @@
/**
* Манифест сборки стайлгайда для 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/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",
},
};

5
src/base/applied/api.md Normal file
View File

@@ -0,0 +1,5 @@
---
scope: applied
keywords: [api, запрос, fetch, SWR, эндпоинт, REST, клиент]
when: "Работа с API: запросы, клиенты, обработка ответов"
---

View File

@@ -0,0 +1,118 @@
---
title: Компоненты
scope: applied
keywords: [компонент, props, jsx, ui, clsx, cl, React, FC]
when: "Создание или редактирование React-компонентов: структура, пропсы, стили"
---
# Компоненты
Правила написания 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<HTMLDivElement>
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 (
<div {...htmlAttr} className={cl(styles.root, className)}>
{children}
</div>
)
}
```
`container/index.ts`
```ts
export { Container } from './container'
```
## Дочерние компоненты
Если модулю нужны внутренние подкомпоненты — генерировать их из шаблона `component` в папку `ui/` внутри родительского модуля. Дочерние компоненты не экспортируются через `index.ts` родителя.

View File

@@ -0,0 +1,5 @@
---
scope: applied
keywords: [шрифт, font, next/font, подключение шрифта, woff]
when: "Подключение и настройка шрифтов"
---

View File

@@ -0,0 +1,5 @@
---
scope: applied
keywords: [хук, hook, use, кастомный хук, useState, useEffect]
when: "Создание или использование кастомных хуков"
---

View File

@@ -0,0 +1,5 @@
---
scope: applied
keywords: [изображение, картинка, image, next/image, public, оптимизация]
when: "Работа с изображениями: подключение, оптимизация"
---

View File

@@ -0,0 +1,5 @@
---
scope: applied
keywords: [i18n, локализация, перевод, язык, i18next, namespace]
when: "Локализация: добавление переводов, работа с i18next"
---

View File

@@ -0,0 +1,5 @@
---
scope: applied
keywords: [стор, store, zustand, состояние, глобальное состояние]
when: "Работа с глобальным состоянием: создание стора, подписка"
---

View File

@@ -1,7 +1,9 @@
--- ---
title: Стили title: Стили
scope: applied
keywords: [css, postcss, модули, css modules, токены, медиа-запросы, вложенность, класс]
when: "Стилизация: CSS Modules, PostCSS, переменные, медиа-запросы"
--- ---
# Стили # Стили
Раздел описывает правила написания CSS: PostCSS Modules, вложенность, медиа-запросы, переменные, форматирование. Раздел описывает правила написания CSS: PostCSS Modules, вложенность, медиа-запросы, переменные, форматирование.
@@ -267,3 +269,17 @@ title: Стили
- Желательно не писать комментарии в CSS. - Желательно не писать комментарии в CSS.
- Исключение — нетривиальные хаки и обходные решения, к которым стоит оставить пояснение. - Исключение — нетривиальные хаки и обходные решения, к которым стоит оставить пояснение.
## Приоритет стилизации
Основной UI-фреймворк проекта — **Mantine**. При стилизации компонентов придерживаться следующего приоритета:
1. **Mantine-компоненты и их пропсы** — в первую очередь использовать встроенные возможности Mantine (пропсы, `classNames`, `styles`).
2. **Глобальные CSS-токены** (`--color-*`, `--space-*`, `--radius-*`) — для значений, которые не покрываются Mantine.
3. **PostCSS Modules** — когда Mantine не покрывает задачу и нужна кастомная стилизация.
## Что запрещено
- **Инлайн-стили** — использование атрибута `style` в компонентах строго запрещено.
- **Магические значения** — произвольные цвета, отступы и скругления запрещены, использовать токены.
- **Глобальные стили** вне `app/styles/` запрещены.

View File

@@ -0,0 +1,7 @@
---
title: SVG-спрайты
scope: applied
keywords: [svg, спрайт, иконка, icon, sprite]
when: "Работа с SVG-иконками и спрайтами"
---
# SVG-спрайты

View File

@@ -1,7 +1,9 @@
--- ---
title: Шаблоны и генерация кода title: Шаблоны и генерация кода
scope: applied
keywords: [шаблон, генерация, template, scaffold, plop, hygen, .templates]
when: "Генерация кода из шаблонов, создание новых шаблонов"
--- ---
<!-- @formatter:off --> <!-- @formatter:off -->
::: v-pre ::: v-pre
@@ -20,7 +22,7 @@ title: Шаблоны и генерация кода
│ ├── styles/ │ ├── styles/
│ │ └── {{name.kebabCase}}.module.css │ │ └── {{name.kebabCase}}.module.css
│ ├── types/ │ ├── types/
│ │ └── {{name.kebabCase}}.interface.ts │ │ └── {{name.kebabCase}}.type.ts
│ ├── {{name.kebabCase}}.tsx │ ├── {{name.kebabCase}}.tsx
│ └── index.ts │ └── index.ts
└── store/ # шаблон Zustand стора └── store/ # шаблон Zustand стора
@@ -86,29 +88,35 @@ export { {{name.pascalCase}} } from './{{name.kebabCase}}'
``` ```
```ts ```ts
// .templates/component/types/{{name.kebabCase}}.interface.ts // .templates/component/types/{{name.kebabCase}}.type.ts
import type { HTMLAttributes } from 'react' import type { HTMLAttributes } from 'react'
/** /**
* Параметры {{name.pascalCase}}. * Параметры {{name.pascalCase}}.
*/ */
export interface {{name.pascalCase}}Props extends HTMLAttributes<HTMLDivElement> {} export type {{name.pascalCase}}Params = {}
/** HTML-атрибуты корневого элемента. */
type RootAttrs = HTMLAttributes<HTMLDivElement>
export type {{name.pascalCase}}Props = RootAttrs & {{name.pascalCase}}Params
``` ```
```tsx ```tsx
// .templates/component/{{name.kebabCase}}.tsx // .templates/component/{{name.kebabCase}}.tsx
import type { FC } from 'react'
import cl from 'clsx' import cl from 'clsx'
import type { {{name.pascalCase}}Props } from './types/{{name.kebabCase}}.interface' import type { {{name.pascalCase}}Props } from './types/{{name.kebabCase}}.type'
import styles from './styles/{{name.kebabCase}}.module.css' import styles from './styles/{{name.kebabCase}}.module.css'
/** /**
* {{name.pascalCase}}. * {{name.pascalCase}}.
*/ */
export const {{name.pascalCase}}: FC<{{name.pascalCase}}Props> = ({ className, ...htmlAttr }) => { export const {{name.pascalCase}} = (props: {{name.pascalCase}}Props) => {
const { children, className, ...htmlAttr } = props
return ( return (
<div {...htmlAttr} className={cl(styles.root, className)}> <div {...htmlAttr} className={cl(styles.root, className)}>
{{name.kebabCase}} {children}
</div> </div>
) )
} }
@@ -123,7 +131,7 @@ export const {{name.pascalCase}}: FC<{{name.pascalCase}}Props> = ({ className, .
## Генерация через VS Code ## Генерация через VS Code
[MyTemplateGenerator](https://open-vsx.org/extension/MyTemplateGenerator/mytemplategenerator) — расширение для генерации файлов и папок из шаблонов через интерфейс редактора. 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. 1. ПКМ на целевой папке в проводнике VS Code.
2. **Generate from template** → выбрать шаблон. 2. **Generate from template** → выбрать шаблон.
@@ -148,3 +156,20 @@ npx @gromlab/create <шаблон> <имя> <путь>
::: :::
## Какие модули генерируются из шаблонов
| Модуль | Слой | Шаблон |
|---|---|---|
| Компонент | `shared/ui/` | `component` |
| Фича | `features/` | `feature` |
| Виджет | `widgets/` | `widget` |
| Сущность | `entities/` | `entity` |
| Layout | `layouts/` | `layout` |
| Экран | `screens/` | `screen` |
| Стор | `model/` | `store` |
## Когда создавать новый шаблон
- Повторяющаяся структура появляется больше одного раза.
- Существующий шаблон не покрывает нужный тип модуля.

Some files were not shown because too many files have changed in this diff Show More