style: Обновлены правила код стайла

This commit is contained in:
2026-05-08 08:21:34 +03:00
parent 7c0f597840
commit fec5ca78d0
32 changed files with 688 additions and 557 deletions

View File

@@ -1,7 +1,7 @@
---
title: Алиасы импортов
description: Какие алиасы импортов есть в проекте и как ими пользоваться.
keywords: [алиасы, aliases, paths, tsconfig, импорты, baseUrl, app, layouts, screens, widgets, business, infrastructure, ui, shared]
keywords: [алиасы, aliases, paths, tsconfig, импорты, baseUrl, app, layouts, screens, widgets, business, infra, ui, shared]
---
# Алиасы импортов
@@ -21,7 +21,7 @@ keywords: [алиасы, aliases, paths, tsconfig, импорты, baseUrl, app,
"screens/*": ["./src/screens/*"],
"widgets/*": ["./src/widgets/*"],
"business/*": ["./src/business/*"],
"infrastructure/*": ["./src/infrastructure/*"],
"infra/*": ["./src/infra/*"],
"ui/*": ["./src/ui/*"],
"shared/*": ["./src/shared/*"]
}
@@ -36,7 +36,7 @@ keywords: [алиасы, aliases, paths, tsconfig, импорты, baseUrl, app,
- **Каждый импорт между модулями — через алиас слоя.** Относительные пути (`../../`) запрещены за пределами своего модуля.
- **Внутри одного модуля** допустимы относительные импорты (`./model`, `./ui/button`) — это часть инкапсуляции модуля.
- **Префикс `@/` не используется.** Имя слоя — само по себе адрес.
- **Направление импортов** определяется архитектурой, не алиасами. Алиас разрешает импорт технически, но не отменяет правила слоёв (→ [Слои](../basics/architecture/reference/layers.md)).
- **Направление импортов** определяется архитектурой, не алиасами. Алиас разрешает импорт технически, но не отменяет правила слоёв (→ [Слои](../basics/architecture/layers.md)).
**Хорошо**

View File

@@ -1,201 +1,165 @@
---
title: Компонент
description: Как создавать React-компоненты внутри SLM-модулей.
description: Как должен выглядеть сгенерированный React-компонент внутри SLM-модуля.
---
# Компонент
Как создавать React-компоненты внутри SLM-модулей.
Как должен выглядеть сгенерированный React-компонент внутри SLM-модуля.
## Назначение
Компонент — минимальная UI-единица проекта. Это один `.tsx` файл без собственной папки, сегментов и публичного API.
Архитектурное определение компонента описано в разделе [Модули → Компонент](../basics/architecture/modules.md#компонент), а структура сегмента `ui/` — в разделе [Сегменты → ui/](../basics/architecture/segments.md#сегмент-ui).
Компонент может использовать стили, типы, хуки и другие ресурсы родительского модуля. Наличие связанных файлов в `styles/` или `types/` не превращает компонент в модуль.
Эта страница не повторяет архитектурные ограничения. Она показывает, каким должен быть результат генерации компонента: структура папки, `.tsx`, типы, стили и локальный экспорт.
## Компонент или модуль
::: danger Компоненты не создаются вручную
Компоненты в проекте создаются только через кодогенератор: через [VS Code](./templates/templates-usage.md#через-vs-code) или [CLI](./templates/templates-usage.md#через-cli).
Классификация определяется границей владения:
Ручное создание компонента запрещено. Это грубое нарушение правил работы в проекте для разработчика и AI-ассистента.
- `component` — один `.tsx` файл внутри модуля;
- `module` — папка с `index.ts`, сегментами и собственной публичной границей.
Если в проекте нет шаблона `.templates/component`, сначала создайте шаблон по разделу [Создание шаблонов](./templates/templates-create.md), и только потом генерируйте компонент на его основе.
:::
## Создание
1. Проверьте, что в проекте есть шаблон `.templates/component`.
2. Если шаблона нет — создайте его по разделу [Создание шаблонов](./templates/templates-create.md).
3. Сгенерируйте компонент через [VS Code или CLI](./templates/templates-usage.md).
Структура и код ниже показывают ожидаемый результат генерации. Их нельзя использовать как инструкцию для ручного создания файлов.
## Структура
Компонент размещается в `ui/{component-name}/` родительского модуля.
Для каждого компонента обязательны `.tsx`, типы, стили и локальный `index.ts`.
```text
user/
├── ui/
│ └── user-avatar.tsx # компонент
├── styles/
│ └── user-avatar.module.css # ресурс родительского модуля
├── types/
│ └── user-avatar.type.ts # ресурс родительского модуля
└── user.tsx # корневой компонент модуля
```
`user-avatar.tsx` остаётся компонентом, потому что у него нет собственной папки, `index.ts` и сегментов.
## Где размещать
Компонент размещается внутри модуля:
- В корне модуля, если это главная UI-сущность модуля.
- В `ui/`, если это вспомогательный компонент модуля.
```text
user/
├── ui/
│ └── user-avatar.tsx
├── styles/
│ ├── user.module.css
│ └── user-avatar.module.css
├── types/
│ ├── user.type.ts
│ └── user-avatar.type.ts
├── user.tsx
└── index.ts
```
`user.tsx` — корневой компонент модуля. `ui/user-avatar.tsx` — вспомогательный компонент этого же модуля.
## Что запрещено
- Заворачивать компонент в папку: `ui/header/header.tsx`.
- Создавать для компонента отдельный `index.ts`.
- Создавать собственные сегменты внутри папки компонента: `ui/header/styles/`, `ui/header/types/`, `ui/header/hooks/` и т.п.
- Декларировать внутри `.tsx` сторы, сервисы, API-клиенты, мапперы или утилиты. Для этого есть сегменты родительского модуля.
- Размещать бизнес-правила прямо в компоненте. Компонент может использовать готовые зависимости модуля, но не определяет их.
- Размещать компонент в `parts/` напрямую. `parts/` содержит только модули.
**Плохо**
```text
user/
user-card/
└── ui/
└── user-avatar/
└── user-status/
├── styles/
│ └── user-avatar.module.css
├── user-avatar.tsx
│ └── user-status.module.css
├── types/
│ └── user-status-props.type.ts
├── user-status.tsx
└── index.ts
```
**Хорошо**
```text
user/
├── ui/
│ └── user-avatar.tsx
├── styles/
│ └── user-avatar.module.css
└── types/
└── user-avatar.type.ts
```
## Стили и типы
Компонент использует ресурсы родительского модуля.
`styles/` и `types/` рядом с корневым компонентом — это сегменты модуля, а не собственные папки `.tsx` файла.
- CSS Module компонента лежит в `styles/` родительского модуля и называется по компоненту: `user-avatar.module.css`.
- Если у компонента есть CSS Module, его корневой класс всегда называется `.root`.
- Типы компонента лежат в `types/` родительского модуля и называются по компоненту: `user-avatar.type.ts`.
- Локальный `type Props` внутри `.tsx` не используется. Типы пропсов всегда выносятся в `types/` родительского модуля.
- Экспорт типа из `types/` не делает его публичным API. Публичным он становится только при реэкспорте из `index.ts` модуля.
Причина `.root`: в DevTools проще находить корневой DOM-узел компонента и отличать его от внутренних элементов.
## Реализация
- Компоненты объявляются через `const`.
- `React.FC` не используется.
- JSDoc-комментарий обязателен для компонента.
- Пропсы деструктурируются в теле компонента.
- `className` объединяется с `styles.root` через `cl()`.
- Побочные эффекты и состояние выносятся в хуки модуля, если перестают быть тривиальными.
- Компонент возвращает JSX и не содержит orchestration-код страницы или бизнес-домена.
Пример ниже показывает файлы базового компонента.
`user/types/user-avatar.type.ts`
### Типы
Файл типов делится на три части:
- `UserStatusParams` — собственные параметры компонента. Здесь лежат только данные, которые нужны именно этому компоненту.
- `RootAttrs` — параметры корневой обёртки: `div`, `span`, `a`, `button` или другого HTML-элемента. Если компонент сам управляет `children`, они исключаются через `Omit`.
- `UserStatusProps` — итоговые пропсы компонента. Тип объединяет собственные параметры и параметры корневой обёртки.
Собственные параметры и их поля документируются по правилам раздела [Документирование → Типы, интерфейсы, enum](../basics/documentation.md#типы-интерфейсы-enum).
`user-card/ui/user-status/types/user-status-props.type.ts`
```ts
import type { ImageProps } from 'next/image'
import type { ComponentPropsWithoutRef } from 'react'
/**
* Параметры UserAvatar.
* Параметры UserStatus.
*/
export type UserAvatarParams = {}
export type UserStatusParams = {
/** Текст статуса пользователя. */
label: string
/** Доступен ли пользователь сейчас. */
isOnline: boolean
}
/** Пропсы базового изображения. */
type RootAttrs = ImageProps
/** Атрибуты корневого элемента без children. */
type RootAttrs = Omit<ComponentPropsWithoutRef<'span'>, 'children'>
export type UserAvatarProps = RootAttrs & UserAvatarParams
export type UserStatusProps = RootAttrs & UserStatusParams
```
`user/ui/user-avatar.tsx`
### TSX
В `.tsx` лежит только сам компонент:
- Компонент объявляется через `const` и именованный экспорт.
- `React.FC` не используется.
- Параметры компонента типизируются через `Props`.
- Возвращаемый тип не указывается: TypeScript корректно выводит JSX-результат, а явный `ReactElement` сужает допустимые варианты возврата.
- JSDoc-комментарий обязателен и пишется по правилам раздела [Документирование → Компоненты](../basics/documentation.md#компоненты).
- Пропсы деструктурируются в теле компонента, а не в сигнатуре.
- Из пропсов обязательно выделяются `className` и `...rootAttrs`.
- Функция конкатенации CSS-классов импортируется и именуется `cl`.
- Корневой CSS-класс всегда называется `.root`.
Комментарий описывает назначение и сценарии применения компонента, а не DOM-разметку или внутреннюю реализацию.
`className` — внешний CSS-класс, который родитель может передать компоненту. `rootAttrs` — остальные атрибуты корневой обёртки: `id`, `aria-*`, `data-*`, обработчики событий и другие HTML-атрибуты. Они прокидываются на корневой DOM-элемент компонента.
`.root` нужен, чтобы в DevTools быстро находить корневой DOM-узел компонента и одинаково подключать внешний `className` к реальному корню.
`user-card/ui/user-status/user-status.tsx`
```tsx
import cl from 'clsx'
import Image from 'next/image'
import type { UserAvatarProps } from '../types/user-avatar.type'
import styles from '../styles/user-avatar.module.css'
import type { UserStatusProps } from './types/user-status-props.type'
import styles from './styles/user-status.module.css'
/**
* Аватар пользователя.
* Статус пользователя в карточке профиля.
*
* Используется для:
* - отображения пользователя в карточке
* - отображения пользователя в шапке профиля
* - отображения текущей доступности пользователя
* - визуального выделения онлайн- и офлайн-состояний
*/
export const UserAvatar = (props: UserAvatarProps) => {
const { className, ...imageProps } = props
export const UserStatus = (props: UserStatusProps) => {
const { label, isOnline, className, ...rootAttrs } = props
return <Image {...imageProps} className={cl(styles.root, className)} />
return (
<span
{...rootAttrs}
className={cl(styles.root, isOnline && styles.online, className)}
>
{label}
</span>
)
}
```
`user/styles/user-avatar.module.css`
### Стили
`user-card/ui/user-status/styles/user-status.module.css`
```css
.root {
display: block;
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--color-text-muted);
}
.root::before {
content: '';
width: 6px;
height: 6px;
border-radius: 50%;
background: currentColor;
}
.online {
color: var(--color-success);
}
```
## Когда нужен модуль
### Локальный экспорт
Решение о выделении модуля остаётся за разработчиком. Поднимать компонент в модуль стоит, если он становится самостоятельной областью:
`user-card/ui/user-status/index.ts`
- получает свои вложенные компоненты;
- получает свои хуки, стор или сервисы;
- получает внутренние мапперы или утилиты;
- требует собственного публичного API;
- начинает переиспользоваться вне родительского модуля;
- становится отдельной зоной параллельной разработки.
Пример: страница — это screen-модуль, а самостоятельные секции страницы — вложенные модули в `parts/`.
```text
screens/home/
├── parts/
│ ├── hero-section/
│ │ ├── styles/
│ │ │ └── hero-section.module.css
│ │ ├── types/
│ │ │ └── hero-section.type.ts
│ │ ├── hero-section.tsx
│ │ └── index.ts
│ └── features-section/
│ ├── styles/
│ │ └── features-section.module.css
│ ├── types/
│ │ └── features-section.type.ts
│ ├── features-section.tsx
│ └── index.ts
├── styles/
│ └── home.module.css
├── types/
│ └── home.type.ts
├── home.screen.tsx
└── index.ts
```ts
export { UserStatus } from './user-status'
export type { UserStatusProps } from './types/user-status-props.type'
```
`hero-section` и `features-section` — модули, потому что это самостоятельные части страницы со своей структурой и публичной точкой входа.

View File

@@ -1,22 +1,22 @@
---
title: Локализация
description: Как организовать локализацию как infrastructure-модуль.
description: Как организовать локализацию как infra-модуль.
---
# Локализация
Как организовать локализацию как infrastructure-модуль.
Как организовать локализацию как infra-модуль.
## Назначение
Локализация — инфраструктурная подсистема приложения. Она отвечает за текущую локаль, словари, форматирование переводов и API для компонентов.
Код локализации живёт в `src/infrastructure/i18n/`. Компоненты и модули не читают словари напрямую — они используют публичный API infrastructure-модуля.
Код локализации живёт в `src/infra/i18n/`. Компоненты и модули не читают словари напрямую — они используют публичный API infra-модуля.
## Структура
```text
src/infrastructure/i18n/
src/infra/i18n/
├── config/
│ └── i18n.config.ts
├── dictionaries/
@@ -31,16 +31,16 @@ src/infrastructure/i18n/
└── index.ts
```
Набор сегментов может отличаться, но публичная точка входа остаётся одна — `infrastructure/i18n`.
Набор сегментов может отличаться, но публичная точка входа остаётся одна — `infra/i18n`.
## Подключение
`app/` только подключает готовый провайдер локализации. Реализация провайдера, словари и конфиг остаются в `infrastructure/i18n/`.
`app/` только подключает готовый провайдер локализации. Реализация провайдера, словари и конфиг остаются в `infra/i18n/`.
```tsx
// src/app/layout.tsx
import type { ReactNode } from 'react'
import { I18nProvider } from 'infrastructure/i18n'
import { I18nProvider } from 'infra/i18n'
type RootLayoutProps = {
children: ReactNode
@@ -62,7 +62,7 @@ export default function RootLayout({ children }: RootLayoutProps) {
Компоненты получают переводы через готовый API модуля локализации:
```tsx
import { useTranslation } from 'infrastructure/i18n'
import { useTranslation } from 'infra/i18n'
export const ProfileTitle = () => {
const { t } = useTranslation()
@@ -73,9 +73,9 @@ export const ProfileTitle = () => {
## Правила
- Локализация живёт в `infrastructure/i18n/`.
- Локализация живёт в `infra/i18n/`.
- `app/` только подключает готовый provider и передаёт locale.
- Словари не импортируются напрямую в компоненты, screens или business-модули.
- Ключи переводов не собираются динамически из строк, если это ломает типизацию и поиск.
- Тексты интерфейса не хардкодятся в переиспользуемых компонентах, если они должны переводиться.
- Форматирование дат, чисел и валют должно проходить через API локализации или отдельные утилиты infrastructure-модуля.
- Форматирование дат, чисел и валют должно проходить через API локализации или отдельные утилиты infra-модуля.

View File

@@ -1,162 +1,156 @@
---
title: Модуль
description: Как создавать и организовывать SLM-модули в проекте.
description: Как должен выглядеть сгенерированный SLM-модуль в проекте.
---
# Модуль
Как создавать и организовывать SLM-модули в проекте.
Как должен выглядеть сгенерированный SLM-модуль в проекте.
## Назначение
Модуль — основной строительный блок SLM-архитектуры. Это папка с публичным API (`index.ts`) и опциональными сегментами: компонентами, стилями, типами, хуками, сторами, сервисами и вложенными модулями.
Архитектурное определение модуля описано в разделе [Архитектура → Модули](../basics/architecture/modules.md). Список сегментов описан в разделе [Архитектура → Сегменты](../basics/architecture/segments.md).
Если UI-сущность остаётся одним `.tsx` файлом и использует ресурсы родительского модуля — это [компонент](./component.md), а не модуль. Связанные файлы в `styles/` и `types/` родителя не создают новую модульную границу.
Эта страница показывает прикладное оформление трёх типов модулей: UI, бизнес и инфраструктурный.
Архитектурное определение: [Модули SLM](../basics/architecture/reference/modules.md). Список сегментов: [Сегменты SLM](../basics/architecture/reference/segments.md).
## Создание
## Когда нужен модуль
1. Проверьте, что в проекте есть нужный шаблон в `.templates/`.
2. Если шаблона нет — создайте его по разделу [Создание шаблонов](./templates/templates-create.md).
3. Сгенерируйте модуль через [VS Code или CLI](./templates/templates-usage.md).
Создавайте модуль, если сущности нужны:
## Типы модулей
- публичный API;
- хуки, сторы, сервисы, мапперы или утилиты;
- вложенные части;
- переиспользование вне родительского модуля;
- самостоятельная ответственность на слое.
Архитектура определяет три типа модулей ([Типы модулей](../basics/architecture/modules.md#типы-модулей)):
Если понадобилась папка вокруг компонента — это сигнал, что нужен модуль.
| Тип | Обязательный файл | Описание |
|---|---|---|
| UI-модуль | `{name}.tsx` | Модуль, выросший из компонента |
| Бизнес-модуль | `{name}.factory.ts` | Модуль вокруг публичного runtime API |
| Инфраструктурный модуль | нет | Модуль вокруг технического сервиса |
## Где размещать
## UI-модуль
Модуль размещается на самом низком уровне использования.
UI-модуль — это компонент, который перерос ограничения компонента: получил собственные хуки, вложенные модули в `parts/`, сценарную логику или публичный API. Внутренняя структура та же, что у компонента: корневой `.tsx`, типы, стили, `ui/`. Но без ограничений компонента.
- Нужен только одному модулю — размещается в `parts/` родителя.
- Нужен одной странице — размещается в `screens/{name}/parts/`.
- Нужен одному layout — размещается в `layouts/{name}/parts/`.
- Переиспользуется между страницами или layout — поднимается в `widgets/`.
- Представляет бизнес-домен — размещается в `business/`.
- Является UI-китом — размещается в `ui/`.
Подробное оформление компонентов внутри `ui/` описано в разделе [Компонент](./component.md).
`app/` не содержит модулей. Это слой файлового роутинга и инициализации.
## Бизнес-модуль
## Структура
Бизнес-модуль строится вокруг публичного runtime API. Ключевой файл — фабрика (`{name}.factory.ts`), которая возвращает всё, что нужно внешнему коду в runtime.
Минимальный UI-модуль:
Архитектурное описание фабрики: [Архитектура → Фабрика](../basics/architecture/modules.md#фабрика).
### Структура
```text
user/
├── user.tsx
── index.ts
business/customer/
├── customer.factory.ts
── index.ts
└── types/
├── customer.type.ts
├── customer-api.type.ts
├── customer-deps.type.ts
└── customer-factory.type.ts
```
Модуль расширяется сегментами только при реальной потребности:
### Типы
```text
user/
├── ui/
│ └── user-avatar.tsx
├── parts/
│ └── user-posts/
│ ├── user-posts.tsx
│ └── index.ts
├── styles/
│ ├── user.module.css
│ └── user-avatar.module.css
├── types/
│ ├── user.type.ts
│ └── user-avatar.type.ts
├── user.tsx
└── index.ts
```
Корневой компонент опционален. Business- и infrastructure-модули могут состоять только из хуков, сервисов, типов и публичного API.
## `ui/` и `parts/`
`ui/` содержит только компоненты: отдельные `.tsx` файлы без собственных сегментов.
`parts/` содержит только модули: каждая запись внутри `parts/` — папка с собственным `index.ts`. Отдельные `.tsx`, стили, хуки или произвольные файлы в `parts/` не кладутся.
```text
user/
├── ui/
│ └── user-avatar.tsx # компонент
└── parts/
└── user-posts/ # модуль
├── styles/
│ └── user-posts.module.css
├── user-posts.tsx
└── index.ts
```
Если компоненту в `ui/` понадобились стили или типы, они добавляются в `styles/` и `types/` родительского модуля. Если компоненту нужны собственные хуки, вложенные части или публичная граница — он переносится в `parts/` как модуль.
## Публичный API
`index.ts` — единственная точка входа в модуль. Внешние импорты внутренних файлов запрещены.
`business/customer/types/customer-api.type.ts`
```ts
// user/index.ts
export { User } from './user'
export type { UserProps } from './types/user.type'
export type CustomerApi = {
useCustomer: () => Customer
CustomerCard: (props: CustomerCardProps) => ReactNode
}
```
`business/order/types/order-deps.type.ts`
```ts
// Плохо: импорт в обход публичного API.
import { UserPosts } from 'screens/user/parts/user-posts/user-posts'
// Хорошо: импорт через публичный API родительского модуля.
import { User } from 'screens/user'
export type OrderDeps = {
customer: Pick<CustomerApi, 'useCustomer'>
}
```
Вложенный модуль имеет свой `index.ts`, но наружу родителя экспортируется только при необходимости.
`business/order/types/order-factory.type.ts`
## Именование
Базовые правила описаны в разделе [Именование](../basics/naming.md).
- Папка модуля — `kebab-case`: `user-posts/`.
- Файл корневого компонента повторяет имя папки: `user-posts/user-posts.tsx`.
- Корневые модули слоёв наследуют роль слоя в имени файла: `screens/profile/profile.screen.tsx`, `layouts/main/main.layout.tsx`.
- Корневой компонент именуется в `PascalCase`: `UserPosts`.
- Если имя без контекста слишком общее, добавляется префикс родителя или роль слоя: `ProfileUserPosts`, `ProfileScreen`, `MainLayout`.
## Примеры
### Screen-модуль
```text
screens/profile/
├── ui/
│ └── profile-heading.tsx
├── parts/
│ └── activity-feed/
│ ├── styles/
│ │ └── activity-feed.module.css
│ ├── activity-feed.tsx
│ └── index.ts
├── styles/
│ ├── profile.module.css
│ └── profile-heading.module.css
├── types/
│ ├── profile.type.ts
│ └── profile-heading.type.ts
├── profile.screen.tsx
└── index.ts
```ts
export type OrderFactory = (deps: OrderDeps) => OrderApi
```
### Business-модуль без корневого компонента
### Фабрика без зависимостей
`business/customer/customer.factory.ts`
```ts
import type { CustomerFactory } from './types/customer-factory.type'
export const customerFactory: CustomerFactory = () => {
return {
useCustomer,
CustomerCard,
}
}
```
### Фабрика с зависимостями
`business/order/order.factory.ts`
```ts
import type { OrderFactory } from './types/order-factory.type'
export const orderFactory: OrderFactory = (deps) => {
return {
useOrder,
OrderCard,
}
}
```
### Композиция на уровне screen
```tsx
// screens/home/home.screen.tsx
import { customerFactory } from '@/business/customer'
import { orderFactory } from '@/business/order'
const customer = customerFactory()
const order = orderFactory({ customer })
const { useOrder, OrderCard } = order
export const HomeScreen = () => {
const currentOrder = useOrder()
return <OrderCard order={currentOrder} />
}
```
## Инфраструктурный модуль
Инфраструктурный модуль строится вокруг технического сервиса или интеграции. Его структура определяется природой сервиса — фиксированного корневого файла нет.
Архитектурное описание: [Архитектура → Типы модулей → Инфраструктурный модуль](../basics/architecture/modules.md#инфраструктурный-модуль).
Пример модуля темы:
```text
business/auth/
theme/
├── index.ts
├── config/
├── hooks/
│ └── use-auth.hook.ts
── services/
│ └── auth.service.ts
├── stores/
│ └── auth.store.ts
├── styles/
── ui/
```
Пример модуля API-клиента:
```text
backend-api/
├── backend-api.client.ts
├── config/
├── types/
│ └── auth.type.ts
└── index.ts
```

View File

@@ -13,7 +13,7 @@ description: Как работать со страницами и другими
Файлы роутинга не реализуют интерфейс. Они описывают маршрут: читают параметры, получают данные первого рендера, подготавливают кеш или состояние и передают результат в screen.
Границы слоя описаны в [Архитектура → Слои → App](../basics/architecture/reference/layers.md#слой-app).
Границы слоя описаны в [Архитектура → Слои → App](../basics/architecture/layers.md#слой-app).
## Граница ответственности
@@ -25,7 +25,7 @@ description: Как работать со страницами и другими
| Прогрев SWR-кеша, начальное состояние, подключение провайдеров | `src/app/**`, только через готовые обёртки из нижних слоёв |
| UI страницы | `screens/` |
| Каркас страницы: header, footer, sidebar | `layouts/` |
| Провайдеры, сторы, хуки, API-клиенты, сервисы | нижние слои (`screens/`, `business/`, `infrastructure/`, `shared/`) |
| Провайдеры, сторы, хуки, API-клиенты, сервисы | нижние слои (`screens/`, `business/`, `infra/`, `shared/`) |
| CSS Modules и стили компонентов | рядом с компонентами, не в `src/app/**` |
## Что можно делать в `page.tsx`
@@ -79,7 +79,7 @@ export default async function ProfilePage({ params }: ProfilePageProps) {
```tsx
import { notFound } from 'next/navigation'
import { userApi } from 'infrastructure/backend-api'
import { userApi } from 'infra/backend-api'
import { UserScreen } from 'screens/user'
type UserPageProps = {
@@ -109,7 +109,7 @@ import {
backendApi,
getCurrentUserKey,
getPostListKey,
} from 'infrastructure/backend-api'
} from 'infra/backend-api'
type FeedLayoutProps = {
children: ReactNode

View File

@@ -46,7 +46,7 @@ src/
├── screens/ # Контент конкретной страницы
├── widgets/ # Составные блоки интерфейса, не привязанные к домену
├── business/ # Бизнес-домены (auth, catalog, orders)
├── infrastructure/ # Техсервисы (theme, i18n, API-адаптеры)
├── infra/ # Техсервисы (theme, i18n, API-адаптеры)
├── ui/ # UI-кит без бизнес-логики
└── shared/ # Общие ресурсы (утилиты, типы, стили)
```
@@ -58,7 +58,7 @@ src/
Точка входа приложения и файловый роутинг Next.js (`layout.tsx`, `page.tsx`, route-сегменты).
`app/` подключает готовую инициализацию из нижних слоёв, но не реализует провайдеры, стили, UI-компоненты, хуки, сторы или сервисы.
Подробнее о границах слоя: [Архитектура → Слои → App](../basics/architecture/reference/layers.md#слой-app).
Подробнее о границах слоя: [Архитектура → Слои → App](../basics/architecture/layers.md#слой-app).
```text
src/app/

View File

@@ -22,7 +22,7 @@ keywords: [шаблоны, templates, .templates, syntax, переменные,
│ ├── styles/
│ │ └── {{name.kebabCase}}.module.css
│ ├── types/
│ │ └── {{name.kebabCase}}.type.ts
│ │ └── {{name.kebabCase}}-props.type.ts
│ ├── {{name.kebabCase}}.tsx
│ └── index.ts
└── store/ # шаблон Zustand стора
@@ -32,6 +32,12 @@ keywords: [шаблоны, templates, .templates, syntax, переменные,
└── index.ts
```
## Обязательный шаблон компонента
Перед созданием компонентов в проекте должен существовать шаблон `.templates/component`.
Если шаблона нет, компонент не создаётся вручную. Сначала создаётся шаблон компонента, затем компонент генерируется через [VS Code или CLI](./templates-usage.md).
## Синтаксис шаблонов
### Переменные

View File

@@ -8,6 +8,12 @@ keywords: [шаблоны, templates, generate, VS Code, CLI, gromlab/create, np
Генерация файлов из шаблонов через VS Code плагин и CLI.
::: danger Ручное создание запрещено
Файлы, для которых есть шаблоны в `.templates/`, создаются только генератором. Ручное создание компонента, модуля, стора или другого шаблонного блока запрещено.
Если нужного шаблона нет, сначала создайте шаблон в `.templates/`, затем сгенерируйте код на его основе.
:::
## Через VS Code
Template File Generator | gromlab ([Marketplace](https://marketplace.visualstudio.com/items?itemName=gromlab.vscode-templateFileGenerator), [Open VSX](https://open-vsx.org/extension/gromlab/vscode-templateFileGenerator)) — расширение для генерации файлов и папок из шаблонов через интерфейс редактора.