docs: ввести DEVELOP.md как точку входа архива
- Удалена автогенерация README.md архива (buildArchiveReadme). - Добавлен DEVELOP.md — точка входа с обязательным порядком чтения: архитектура → базовые правила → прикладные по задаче. - Добавлен MAP.md — статичная карта со ссылками на все разделы. - DEVELOP.md и MAP.md исключены из веб-сборки (srcExclude). - DEVELOP.md исключён из копирования в docs/public/docs/. - Удалено копирование llms-full.txt в архив (только для сайта). - В CONTRIBUTING.md ссылка README.md заменена на MAP.md.
This commit is contained in:
@@ -121,7 +121,11 @@ export default defineConfig({
|
|||||||
// `docs/public/` содержит сгенерированные `.md`-копии и `llms.txt` для LLM
|
// `docs/public/` содержит сгенерированные `.md`-копии и `llms.txt` для LLM
|
||||||
// (попадают в корень `dist/` как статика). Исключаем из сканирования
|
// (попадают в корень `dist/` как статика). Исключаем из сканирования
|
||||||
// страниц, иначе VitePress рендерит их как HTML-страницы.
|
// страниц, иначе VitePress рендерит их как HTML-страницы.
|
||||||
srcExclude: ['public/**'],
|
//
|
||||||
|
// `DEVELOP.md` и `MAP.md` — файлы архива (точка входа и карта).
|
||||||
|
// Содержат относительные ссылки, на сайте им делать нечего —
|
||||||
|
// эту роль выполняют сайдбар и `llms.txt`.
|
||||||
|
srcExclude: ['public/**', '**/DEVELOP.md', '**/MAP.md'],
|
||||||
lang: 'ru-RU',
|
lang: 'ru-RU',
|
||||||
title: 'NextJS Style Guide',
|
title: 'NextJS Style Guide',
|
||||||
description: 'Стандарты разработки на Next.js + TypeScript с архитектурой SLM',
|
description: 'Стандарты разработки на Next.js + TypeScript с архитектурой SLM',
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ description: Описание раздела одним предложением
|
|||||||
|
|
||||||
Каждая страница начинается с `h1`-заголовка и абзаца-описания сразу под ним.
|
Каждая страница начинается с `h1`-заголовка и абзаца-описания сразу под ним.
|
||||||
Эта пара — **навигационный маркер**: попадает в сайдбар, `llms.txt`,
|
Эта пара — **навигационный маркер**: попадает в сайдбар, `llms.txt`,
|
||||||
`README.md` архива и должна за секунду давать читателю или LLM понять,
|
`MAP.md` архива и должна за секунду давать читателю или LLM понять,
|
||||||
**когда сюда нужно идти**.
|
**когда сюда нужно идти**.
|
||||||
|
|
||||||
#### Структура заголовков
|
#### Структура заголовков
|
||||||
|
|||||||
103
docs/docs/DEVELOP.md
Normal file
103
docs/docs/DEVELOP.md
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
title: Гид для агента
|
||||||
|
description: Что AI-агент обязан прочитать перед началом работы, а что — по задаче.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Обязательное чтение перед началом работы
|
||||||
|
|
||||||
|
Этот документ определяет **строгий порядок действий агента перед выполнением любых задач**.
|
||||||
|
|
||||||
|
## Общее правило
|
||||||
|
|
||||||
|
Перед началом работы над **любой задачей** агент **обязан ознакомиться с базовой документацией проекта**.
|
||||||
|
|
||||||
|
Нарушение этого порядка считается ошибкой.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Порядок обязательного чтения
|
||||||
|
|
||||||
|
Агент должен читать документацию **строго в следующем порядке**:
|
||||||
|
|
||||||
|
### 1. Архитектура (КРИТИЧЕСКИ ВАЖНО)
|
||||||
|
|
||||||
|
* [Архитектура: Обзор](./basics/architecture/index.md)
|
||||||
|
* [Архитектура: Слои](./basics/architecture/reference/layers.md)
|
||||||
|
* [Архитектура: Модули](./basics/architecture/reference/modules.md)
|
||||||
|
* [Архитектура: Сегменты](./basics/architecture/reference/segments.md)
|
||||||
|
|
||||||
|
**Архитектура — это самое важное в проекте.**
|
||||||
|
|
||||||
|
Агент обязан:
|
||||||
|
|
||||||
|
* строго понимать архитектурный подход (SLM)
|
||||||
|
* соблюдать архитектуру **на 100% без отклонений**
|
||||||
|
* не предлагать решений, нарушающих архитектурные принципы
|
||||||
|
* не упрощать архитектуру даже ради скорости выполнения задачи
|
||||||
|
|
||||||
|
Любое нарушение архитектуры недопустимо.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Базовые правила
|
||||||
|
|
||||||
|
После архитектуры необходимо изучить:
|
||||||
|
|
||||||
|
* [Технологии и библиотеки](./basics/tech-stack.md)
|
||||||
|
* [Именование](./basics/naming.md)
|
||||||
|
* [Стиль кода](./basics/code-style.md)
|
||||||
|
* [Документирование](./basics/documentation.md)
|
||||||
|
* [Типизация](./basics/typing.md)
|
||||||
|
|
||||||
|
Агент обязан применять эти правила во всех решениях.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Использование карты документации
|
||||||
|
|
||||||
|
Для поиска дополнительных сведений агент должен использовать:
|
||||||
|
|
||||||
|
* [MAP.md](./MAP.md)
|
||||||
|
|
||||||
|
MAP.md содержит ссылки на все прикладные и вспомогательные разделы.
|
||||||
|
|
||||||
|
Агент может:
|
||||||
|
|
||||||
|
* переходить к нужным разделам через MAP.md
|
||||||
|
* уточнять детали реализации
|
||||||
|
* искать примеры и частные случаи
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Запрещено
|
||||||
|
|
||||||
|
Агенту запрещено:
|
||||||
|
|
||||||
|
* начинать выполнение задачи без изучения архитектуры
|
||||||
|
* игнорировать базовые правила
|
||||||
|
* принимать решения, противоречащие архитектуре
|
||||||
|
* придумывать собственные подходы, если они не описаны в документации
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Ожидаемое поведение агента
|
||||||
|
|
||||||
|
Перед выполнением задачи агент должен:
|
||||||
|
|
||||||
|
1. Изучить архитектуру
|
||||||
|
2. Изучить базовые правила
|
||||||
|
3. При необходимости открыть MAP.md и найти релевантные разделы
|
||||||
|
4. Только после этого приступать к решению задачи
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Приоритеты
|
||||||
|
|
||||||
|
При принятии решений агент должен руководствоваться следующим приоритетом:
|
||||||
|
|
||||||
|
1. **Архитектура**
|
||||||
|
2. Базовые правила
|
||||||
|
3. Документация из MAP.md
|
||||||
|
4. Задача пользователя
|
||||||
|
|
||||||
|
Если задача противоречит архитектуре — задача должна быть переосмыслена, а не выполнена напрямую.
|
||||||
54
docs/docs/MAP.md
Normal file
54
docs/docs/MAP.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Карта документации
|
||||||
|
|
||||||
|
Список всех разделов архива с относительными ссылками. Точка входа
|
||||||
|
— `DEVELOP.md` рядом с этим файлом.
|
||||||
|
|
||||||
|
## Подсказки
|
||||||
|
|
||||||
|
- [Подсказки](./workflow.md) — Короткие ответы на типовые вопросы и решения для спорных ситуаций.
|
||||||
|
|
||||||
|
## Базовые правила
|
||||||
|
|
||||||
|
- [Технологии и библиотеки](./basics/tech-stack.md) — Какие библиотеки и инструменты используются в проекте.
|
||||||
|
- [Именование](./basics/naming.md) — Как называть переменные, файлы и прочие сущности в коде.
|
||||||
|
- [Архитектура: Обзор](./basics/architecture/index.md) — Архитектурный подход проекта: что такое SLM и как он устроен.
|
||||||
|
- [Архитектура: Слои](./basics/architecture/reference/layers.md) — Из каких слоёв состоит SLM-архитектура и как они связаны.
|
||||||
|
- [Архитектура: Модули](./basics/architecture/reference/modules.md) — Что такое модуль в SLM-архитектуре и как он устроен.
|
||||||
|
- [Архитектура: Сегменты](./basics/architecture/reference/segments.md) — Что такое сегмент модуля в SLM-архитектуре и какие они бывают.
|
||||||
|
- [Стиль кода](./basics/code-style.md) — Как оформляется код в проекте.
|
||||||
|
- [Документирование](./basics/documentation.md) — Что и как документировать в коде.
|
||||||
|
- [Типизация](./basics/typing.md) — Как типизируется код в проекте.
|
||||||
|
|
||||||
|
## Создание проекта
|
||||||
|
|
||||||
|
- [Из шаблона](./creating-project/from-template.md) — Создание нового проекта на основе готового шаблона.
|
||||||
|
- [По гайду вручную](./creating-project/manual.md) — Поэтапное создание нового проекта без использования шаблона.
|
||||||
|
- [Чистый Next.js](./creating-project/nextjs.md) — Установка Next.js без лишнего шаблона — голый каркас под дальнейшую сборку.
|
||||||
|
|
||||||
|
## Настройка
|
||||||
|
|
||||||
|
- [Алиасы импортов](./setup/aliases.md) — Какие алиасы импортов есть в проекте и как ими пользоваться.
|
||||||
|
- [Biome](./setup/biome.md) — Установка и настройка линтера-форматтера в новом проекте.
|
||||||
|
- [PostCSS](./setup/postcss.md) — Установка и настройка CSS-процессора в новом проекте.
|
||||||
|
- [Стили](./setup/styles.md) — Подготовка стилевой основы проекта: токены, медиа-запросы, глобальные стили.
|
||||||
|
- [SVG-спрайты](./setup/svg-sprites.md) — Подключение SVG-спрайтов в новом проекте.
|
||||||
|
- [Шаблоны генерации](./setup/templates.md) — Подключение шаблонов кодогенерации в новом проекте.
|
||||||
|
- [VS Code](./setup/vscode.md) — Единые настройки редактора и расширений для команды.
|
||||||
|
|
||||||
|
## Использование
|
||||||
|
|
||||||
|
- [Структура проекта](./usage/project-structure.md) — Из чего состоит проект и где что лежит.
|
||||||
|
- [Компоненты](./usage/components.md) — Как устроен и пишется React-компонент в проекте.
|
||||||
|
- [Страницы (App Router)](./usage/page-level.md) — Что должно лежать в файлах роутинга, а что — в экранах.
|
||||||
|
- [Шаблоны и генерация кода](./usage/templates-generation.md) — Как устроены шаблоны кодогенерации и как ими пользоваться.
|
||||||
|
- [Стили](./usage/styles.md) — Как пишутся стили в проекте.
|
||||||
|
- [SVG-спрайты](./usage/svg-sprites.md) — Как добавлять и использовать SVG-иконки в коде.
|
||||||
|
|
||||||
|
## Данные
|
||||||
|
|
||||||
|
- [Введение](./usage/data/index.md) — Какие источники данных используются в проекте и как с ними работать.
|
||||||
|
- [REST: Клиенты: Автоматическая генерация](./usage/data/rest/clients/auto.md) — Генерация REST-клиента из OpenAPI-спецификации.
|
||||||
|
- [REST: Клиенты: Ручное создание](./usage/data/rest/clients/manual.md) — Создание REST-клиента вручную, когда нет OpenAPI-спецификации.
|
||||||
|
- [REST: Получение данных: Серверные компоненты](./usage/data/rest/fetching/server.md) — Получение REST-данных в серверных компонентах.
|
||||||
|
- [REST: Получение данных: Клиентские компоненты](./usage/data/rest/fetching/client.md) — Получение REST-данных в клиентских компонентах.
|
||||||
|
- [Realtime](./usage/data/realtime.md) — Работа с push-данными от сервера: подписки и события.
|
||||||
@@ -241,13 +241,20 @@ const copyDirSync = (
|
|||||||
/**
|
/**
|
||||||
* Скопировать все `.md`-файлы документации в `docs/public/docs/`,
|
* Скопировать все `.md`-файлы документации в `docs/public/docs/`,
|
||||||
* чтобы они попали в build `dist/` и были доступны по URL `/docs/path.md`.
|
* чтобы они попали в build `dist/` и были доступны по URL `/docs/path.md`.
|
||||||
|
*
|
||||||
|
* `DEVELOP.md` исключается — это точка входа архива, ссылается
|
||||||
|
* на офлайн-файлы (`MAP.md`), которых нет на сайте.
|
||||||
*/
|
*/
|
||||||
const copyMdFiles = (): void => {
|
const copyMdFiles = (): void => {
|
||||||
const srcDir = 'docs/docs';
|
const srcDir = 'docs/docs';
|
||||||
const destDir = path.join(PUBLIC_DIR, 'docs');
|
const destDir = path.join(PUBLIC_DIR, 'docs');
|
||||||
if (!fs.existsSync(srcDir)) return;
|
if (!fs.existsSync(srcDir)) return;
|
||||||
|
|
||||||
const copied = copyDirSync(srcDir, destDir, (name) => name.endsWith('.md'));
|
const copied = copyDirSync(
|
||||||
|
srcDir,
|
||||||
|
destDir,
|
||||||
|
(name) => name.endsWith('.md') && name !== 'DEVELOP.md',
|
||||||
|
);
|
||||||
console.log(`скопировано ${copied} .md-файлов в ${destDir}`);
|
console.log(`скопировано ${copied} .md-файлов в ${destDir}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -304,98 +311,31 @@ const transformLinksInDir = (rootDir: string): void => {
|
|||||||
walk(rootDir);
|
walk(rootDir);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Сгенерировать `README.md` — точка входа архива. Карта документации
|
|
||||||
* с относительными ссылками, описаниями из frontmatter/первого абзаца
|
|
||||||
* и метаинфо сборки.
|
|
||||||
*/
|
|
||||||
const buildArchiveReadme = (rootDir: string): void => {
|
|
||||||
const sidebar = cfg.themeConfig.sidebar;
|
|
||||||
const blockquote = cfg.llmsBlockquote ?? cfg.description ?? '';
|
|
||||||
const context = cfg.llmsContext;
|
|
||||||
|
|
||||||
const entries = flattenSidebar(sidebar).filter(
|
|
||||||
// «Главная» из sidebar — это страница раздела для веба, в архиве не нужна.
|
|
||||||
(e) => e.section !== 'Главная',
|
|
||||||
);
|
|
||||||
const grouped = groupBySection(entries);
|
|
||||||
|
|
||||||
const lines: string[] = [];
|
|
||||||
lines.push(`# ${cfg.title}`);
|
|
||||||
lines.push('');
|
|
||||||
if (blockquote) {
|
|
||||||
lines.push(`> ${blockquote}`);
|
|
||||||
lines.push('');
|
|
||||||
}
|
|
||||||
if (context) {
|
|
||||||
lines.push(context);
|
|
||||||
lines.push('');
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.push('## Содержание');
|
|
||||||
lines.push('');
|
|
||||||
|
|
||||||
for (const [section, items] of grouped) {
|
|
||||||
lines.push(`### ${section}`);
|
|
||||||
lines.push('');
|
|
||||||
for (const entry of items) {
|
|
||||||
const targetRel = './' + linkToArchiveRel(entry.link);
|
|
||||||
const filePath = path.join(rootDir, linkToArchiveRel(entry.link));
|
|
||||||
|
|
||||||
let description: string | null = null;
|
|
||||||
if (fs.existsSync(filePath)) {
|
|
||||||
const raw = fs.readFileSync(filePath, 'utf8');
|
|
||||||
const { data, body } = parseFrontmatter(raw);
|
|
||||||
description = data.description || firstParagraphAfterH1(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
const display = entry.prefix
|
|
||||||
? `${entry.prefix}: ${entry.text}`
|
|
||||||
: entry.text;
|
|
||||||
const descPart = description ? ` — ${description}` : '';
|
|
||||||
lines.push(`- [${display}](${targetRel})${descPart}`);
|
|
||||||
}
|
|
||||||
lines.push('');
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.push('---');
|
|
||||||
lines.push('');
|
|
||||||
lines.push(`Версия: ${VERSION} · Сборка: ${BUILD_DATE}`);
|
|
||||||
lines.push('');
|
|
||||||
|
|
||||||
fs.writeFileSync(path.join(rootDir, 'README.md'), lines.join('\n'), 'utf8');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Собрать `nextjs-style-guide.zip`. Внутри — папка `nextjs-style-guide/`
|
* Собрать `nextjs-style-guide.zip`. Внутри — папка `nextjs-style-guide/`
|
||||||
* с `.md`-файлами, README, `llms-full.txt` и `VERSION`. Внутренние ссылки
|
* с `.md`-файлами, DEVELOP.md (точка входа), MAP.md (навигационная карта)
|
||||||
* преобразуются в относительные.
|
* и `VERSION`. Внутренние ссылки преобразуются в относительные.
|
||||||
|
*
|
||||||
|
* Точка входа архива — `docs/docs/DEVELOP.md`, навигационная карта —
|
||||||
|
* `docs/docs/MAP.md`. Оба файла редактируются вручную и копируются
|
||||||
|
* в архив как есть.
|
||||||
*/
|
*/
|
||||||
const buildZip = (): void => {
|
const buildZip = (): void => {
|
||||||
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'nsg-'));
|
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'nsg-'));
|
||||||
const stage = path.join(tmpRoot, 'nextjs-style-guide');
|
const stage = path.join(tmpRoot, 'nextjs-style-guide');
|
||||||
fs.mkdirSync(stage, { recursive: true });
|
fs.mkdirSync(stage, { recursive: true });
|
||||||
|
|
||||||
// 1. Копируем все .md в staging.
|
// 1. Копируем все .md в staging (включая DEVELOP.md и MAP.md).
|
||||||
copyDirSync('docs/docs', stage, (name) => name.endsWith('.md'));
|
copyDirSync('docs/docs', stage, (name) => name.endsWith('.md'));
|
||||||
|
|
||||||
// 2. Удаляем веб-index.md — в архиве его роль выполняет README.md.
|
// 2. Удаляем веб-index.md — в архиве его роль выполняет DEVELOP.md.
|
||||||
const indexPath = path.join(stage, 'index.md');
|
const indexPath = path.join(stage, 'index.md');
|
||||||
if (fs.existsSync(indexPath)) fs.unlinkSync(indexPath);
|
if (fs.existsSync(indexPath)) fs.unlinkSync(indexPath);
|
||||||
|
|
||||||
// 3. Преобразуем абсолютные ссылки `/docs/...` в относительные.
|
// 3. Преобразуем абсолютные ссылки `/docs/...` в относительные.
|
||||||
transformLinksInDir(stage);
|
transformLinksInDir(stage);
|
||||||
|
|
||||||
// 4. Генерируем точку входа README.md.
|
// 4. Метаинформация сборки.
|
||||||
buildArchiveReadme(stage);
|
|
||||||
|
|
||||||
// 5. Кладём llms-full.txt — удобно для одноразового чтения LLM.
|
|
||||||
const llmsFullSrc = path.join(PUBLIC_DIR, 'llms-full.txt');
|
|
||||||
if (fs.existsSync(llmsFullSrc)) {
|
|
||||||
fs.copyFileSync(llmsFullSrc, path.join(stage, 'llms-full.txt'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Метаинформация сборки.
|
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(stage, 'VERSION'),
|
path.join(stage, 'VERSION'),
|
||||||
`${VERSION}\n${BUILD_DATE}\n`,
|
`${VERSION}\n${BUILD_DATE}\n`,
|
||||||
|
|||||||
Reference in New Issue
Block a user