Skip to main content
Всё, что лежит под 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 — одно предложение о том, что читатель сможет сделать после прочтения; именно оно появляется в результатах поиска и превью ссылок. Начинайте с одного-двух абзацев ориентировки до первого ##. Читателю, пришедшему из результатов поиска, нужно знать, что эта страница охватывает, а что нет, ещё до того, как он встретит процедуру. Для каждой возможности, о которой рассказывает страница, отвечайте на три вопроса по порядку:
  1. Что это — одно-два конкретных предложения.
  2. Зачем это существует — какой сбой это предотвращает, какое ограничение обеспечивает или какая альтернатива была отвергнута. Обоснуйте чем-то видимым в коде: путём отказа, инвариантом, границей приватности. Никогда не выдумывайте обоснование.
  3. Как этим пользоваться — точный маршрут, экран или команда; поля; кнопка; и что читатель видит при успехе, в ожидании и при отказе.
Страница, перечисляющая возможности, но не говорящая, как до них добраться, провалена. Страница, дающая шаги, но не говорящая, зачем возможность существует, тоже провалена.

Используемые компоненты

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.
Не превращайте настоящее ограничение в сноску. Отказы, лимиты и то, чего Omniflow намеренно не делает, — часть продукта, и им место на странице.

Русское зеркало

docs/ru/** зеркалит английское дерево файл в файл: у docs/index.mdx есть docs/ru/index.mdx, у docs/commerce/wallet-ledger.mdx — docs/ru/commerce/wallet-ledger.mdx, и так для каждой записи в docs.json.
Изменение английской страницы должно быть внесено в её русский аналог в том же коммите. Не в том же pull request, не отдельной задачей потом — в том же коммите. Частично переведённое дерево не читается русскоязычным оператором как неполное; оно читается как корректное и при этом молча устаревает, а чаще всего правятся как раз рабочие инструкции, где устаревание стоит денег или доступа.
Русский здесь не перевод из вежливости. Новая запись клиента создаётся с 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 друг относительно друга, и русская страница, перестроенная ради стиля, делает следующее обновление невозможным для проверки.

Локальная проверка

Это запускает все три проверки, которые запускает CI, из каталога docs:
validate проверяет docs.json против его схемы, а страницы — против правил MDX от Mintlify: испорченный frontmatter, неизвестный компонент, незакрытый тег. Он покрывает оба языковых дерева. PUPPETEER_SKIP_DOWNLOAD=true не даёт CLI подтягивать headless-браузер, который ему не нужен. broken-links получает явный список файлов, а не весь сайт, потому что он разрешает каждую ссылку относительно языка по умолчанию: ссылка /ru/… объявляется битой, хотя страница отдаётся ровно по этому адресу, в чём легко убедиться через mint dev. Чтобы не терять проверку для русского дерева, её берёт на себя scripts/check-russian-mirror.sh: он требует, чтобы у каждой английской страницы был русский двойник и не было сирот в обратную сторону, чтобы ни одна русская страница не ссылалась наружу в английское дерево и чтобы каждая ссылка /ru/… разрешалась в реальный файл.
Не «чините» русскую страницу удалением префиксов /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.
Используйте Conventional Commit типа docs: с областью по участку — docs(telemetry): document the heartbeat payload. Соглашения о коммитах и остальной процесс контрибуции — на странице Разработка.