docs/, — это публичная документация, публикуемая через Mintlify. Она не
дополнение к коду: для оператора, решающего, доверить ли установке деньги, и для клиента,
решающего, доверить ли ей свой трафик, она — единственное описание продукта самим продуктом.
Поэтому AGENTS.md считает изменение поведения и его документацию одним изменением: обновляйте
документацию вместе с поведением и прогоняйте проверки документации до слияния.
В дереве два полных языковых дерева — английское в корне и русское под docs/ru/, — и оба доступны
для навигации на опубликованном сайте. Держать их в согласии — самое легко нарушаемое правило на
этой странице, поэтому ниже под него отведён отдельный раздел.
Как устроен исходник
docs.json следует схеме https://mintlify.com/docs.json. Его массив navigation.languages
содержит две записи: en, помеченную default: true, и ru. Каждая несёт собственные названия
групп — русская запись использует русские заголовки групп (Начало, Коммерция, Эксплуатация), —
и каждая группа перечисляет пути страниц без расширения .mdx. Страница, которая существует как
файл, но не появляется ни в одной группе, недостижима из навигации, а записи группы без файла за ней
нечего отдавать, поэтому файлы и записи навигации добавляются и удаляются вместе.
Группа справочника API — не страница. Она направляет Mintlify на
https://raw.githubusercontent.com/kewldan/omniflow/main/api/openapi.yaml, поэтому каждый эндпоинт,
параметр и схема в опубликованном справочнике берутся из закоммиченного контракта в main. Эндпоинт
документируется изменением api/openapi.yaml, а не написанной руками страницей, которая его
описывает, — то же самое правило не даёт разойтись серверным типам Go и клиенту на TypeScript. См.
Разработку — там о генераторах, читающих тот же файл.
Анатомия страницы
Frontmatter — ровно два ключа, на каждой из существующих страниц:title даёт заголовок страницы, поэтому тело начинается с ## и никогда не содержит #.
description — одно предложение о том, что читатель сможет сделать после прочтения; именно оно
появляется в результатах поиска и превью ссылок.
Начинайте с одного-двух абзацев ориентировки до первого ##. Читателю, пришедшему из результатов
поиска, нужно знать, что эта страница охватывает, а что нет, ещё до того, как он встретит процедуру.
Для каждой возможности, о которой рассказывает страница, отвечайте на три вопроса по порядку:
- Что это — одно-два конкретных предложения.
- Зачем это существует — какой сбой это предотвращает, какое ограничение обеспечивает или какая альтернатива была отвергнута. Обоснуйте чем-то видимым в коде: путём отказа, инвариантом, границей приватности. Никогда не выдумывайте обоснование.
- Как этим пользоваться — точный маршрут, экран или команда; поля; кнопка; и что читатель видит при успехе, в ожидании и при отказе.
Используемые компоненты
Mintlify предлагает большой набор компонентов; эта документация намеренно использует лишь малую его часть, чтобы читатель усваивал один визуальный словарь.icon принимает имя из Font Awesome — database, server, wallet, shield-halved, bullhorn и
подобные уже используются; предпочитайте иконку, которая в дереве уже есть, новой. Не ставьте три
выноски подряд: страница, где выделено всё, не выделяет ничего.
У блоков кода всегда указан язык (bash, env, json, yaml, sql, mdx). Диаграммы mermaid
допустимы для конечных автоматов и потоков и сегодня используются на трёх страницах; держите их
достаточно небольшими, чтобы читать без увеличения.
Таблицы — правильная форма для переменных окружения, ролей, прав доступа, состояний, провайдеров и
любой перечислимой матрицы. Держите набор столбцов согласованным со страницами, которые уже
документируют то же самое: все таблицы переменных окружения используют Variable / Default / Purpose,
и отклонение от этого делает два справочника невозможными для чтения рядом.
Ссылки
Внутренние ссылки — абсолютные пути с ведущим слешем и без расширения:/operations/admin-panel,
/commerce/orders-payments. Якорь — это целевой заголовок, приведённый к нижнему регистру и
соединённый дефисами: /commerce/orders-payments#refunds.
CI выполняет mint broken-links --check-anchors по английскому дереву, поэтому якорь, не совпадающий
с реальным заголовком на целевой странице, роняет сборку так же, как отсутствующая страница.
Переименовав заголовок, поищите по дереву ссылки на его якорь.
Единственный случай, которого следует избегать, — ссылка с одной русской страницы на якорь другой
русской страницы: заголовки цели переведены, поэтому английского якоря там больше нет. Ссылайтесь на
страницу целиком. Якорь на заголовок той же самой страницы допустим: оба конца под вашим контролем.
Ссылайтесь между страницами щедро. Почти у каждой возможности есть клиентская страница, операторская
страница и справочник по конфигурации, и читателю, попавшему на одну из трёх, нужны две остальные.
Тон
Ориентируйтесь на страницы, которые уже соответствуют планке, —docs/customer/web-panel.mdx,
docs/operations/admin-panel.mdx, docs/commerce/gifts-and-goods.mdx.
- Утвердительно, точно, неспешно. Полные предложения. Никаких маркетинговых прилагательных, никаких «просто», «всего лишь», никаких восклицательных знаков и эмодзи в тексте.
- Объясняйте причинность прямо в тексте: «…поэтому…», «…потому что…», «…а не…». Называйте отвергнутую альтернативу, когда код делает её очевидной.
- Второе лицо для инструкций («Откройте
/admin/catalog», «Вставьте токен»); третье лицо для описания поведения. - Предпочитайте «оператор» и «клиент» слову «пользователь».
- Точные идентификаторы в обратных кавычках:
APP_BACKUP_ENABLED,/v1/panel/orders,catalog.write. - Время в UTC, деньги в минорных единицах, даты по ISO.
Русское зеркало
docs/ru/** зеркалит английское дерево файл в файл: у docs/index.mdx есть docs/ru/index.mdx, у
docs/commerce/wallet-ledger.mdx — docs/ru/commerce/wallet-ledger.mdx, и так для каждой записи в
docs.json.
Русский здесь не перевод из вежливости. Новая запись клиента создаётся с locale по умолчанию
'ru', APP_DEFAULT_CURRENCY по умолчанию равна RUB, а панель оператора отказывается включать
режим обслуживания, пока оператор не предоставит и русское, и английское уведомление для клиентов.
Продукт рассчитан на русскоязычную аудиторию, поэтому отстающая русская страница — дефект в основной
документации, а не во второстепенной.
Что переводить, а что не трогать
Переводите тело,title и description во frontmatter, заголовки таблиц, текст выносок и текст
подписей внутри компонентов.
Никогда не переводите:
- имена переменных окружения (
APP_TELEMETRY_ENABLED), маршруты и пути API (/v1/panel/orders), имена прав доступа (system.write), идентификаторы базы данных, команды CLI, строки логов и ключи JSON или YAML; - имена компонентов (
<Note>,<Card>) и значенияicon; - названия продуктов: Omniflow, Remnawave, Telegram, YooKassa, CryptoBot, Telegram Stars, Xray, PostgreSQL, Valkey, River, Next.js.
/ru/operations/admin-panel, а не
/operations/admin-panel. Русская страница, ссылающаяся в английское дерево, выбрасывает читателя
из его языка до конца сессии.
Используйте профессиональный технический русский, «вы» со строчной буквы и «ё» там, где эта буква
уместна (кошелёк, счёт). Некоторые устоявшиеся термины:
Держите длину предложений и разбиение на абзацы близкими к английской странице. Два дерева
рецензируются как diff друг относительно друга, и русская страница, перестроенная ради стиля, делает
следующее обновление невозможным для проверки.
Локальная проверка
docs:
validate проверяет docs.json против его схемы, а страницы — против правил MDX от Mintlify:
испорченный frontmatter, неизвестный компонент, незакрытый тег. Он покрывает оба языковых дерева.
PUPPETEER_SKIP_DOWNLOAD=true не даёт CLI подтягивать headless-браузер, который ему не нужен.
broken-links получает явный список файлов, а не весь сайт, потому что он разрешает каждую ссылку
относительно языка по умолчанию: ссылка /ru/… объявляется битой, хотя страница отдаётся ровно по
этому адресу, в чём легко убедиться через mint dev. Чтобы не терять проверку для русского дерева,
её берёт на себя scripts/check-russian-mirror.sh: он требует, чтобы у каждой английской страницы
был русский двойник и не было сирот в обратную сторону, чтобы ни одна русская страница не ссылалась
наружу в английское дерево и чтобы каждая ссылка /ru/… разрешалась в реальный файл.
Задача docs в .github/workflows/ci.yml выполняет ровно эти три команды, поэтому зелёный локальный
прогон означает зелёный CI по этому участку.
Обязательства по точности
- Никогда не документируйте то, что существует только в
ROADMAP.md. Запланированная возможность либо опускается, либо прямо помечается как ещё недоступная с указанием версии, к которой она нацелена. - Никогда не выдумывайте переменную окружения, значение по умолчанию, маршрут, право доступа или экран. Если вы не можете открыть файл, который это определяет, не пишите об этом.
- Изменение телеметрии несёт свою документацию. Любое новое поле или событие требует обновления публичной документации по телеметрии и схемы в том же изменении — см. Анонимную телеметрию.
- Никогда не вставляйте на страницу настоящий секрет, учётные данные, ссылку доступа, идентификатор клиента или платёжный payload, в том числе внутри примера ответа. Синтезируйте их.
- Архитектурные решения с долгосрочными последствиями оформляются нумерованным файлом
docs/architecture/decision-NNNN-<slug>.mdx, перечисленным на странице Архитектурные решения, а не текстом на странице о возможности. Держите их плоскими:mint broken-linksне разрешает ссылку на страницу, вложенную на два уровня каталогов, поэтому папкаdocs/architecture/decisions/роняет задание docs, хотя страницы собираются.
Добавление страницы
1
Напишите английскую страницу
Создайте
docs/<section>/<slug>.mdx с frontmatter title и description и телом, которое
начинается с ##.2
Напишите русскую страницу
Создайте
docs/ru/<section>/<slug>.mdx по зеркальному пути, переведённую по правилам выше, с
внутренними ссылками, ведущими в /ru/.3
Зарегистрируйте обе в навигации
Добавьте
<section>/<slug> в подходящую группу языкового блока en в docs.json, а
ru/<section>/<slug> — в соответствующую группу блока ru. Страница в одном языковом блоке и
отсутствующая в другом — самый частый способ рассинхронизировать это дерево.4
Поставьте на неё ссылку
Добавьте ссылку хотя бы с одной страницы, на которую читатель правдоподобно попадёт первой.
Страница, на которую никто не ссылается, находится только поиском.
5
Проверьте
Запустите
make docs-check и исправьте каждую сообщённую ссылку и каждый якорь до открытия
pull request.docs: с областью по участку — docs(telemetry): document the heartbeat payload. Соглашения о коммитах и остальной процесс контрибуции — на странице
Разработка.