380 статей, 5 сайтов и 10 URL в сутки: контент-сеть на GitHub Pages, которую на 90% делает AI-агент

Пять русскоязычных нишевых сайтов живут подпапками одного бесплатного домена GitHub Pages: советы для дома, авто, дата/сад/огород, здоровье и раздел 18+. На деплое 7 октября 2026 года опубликовано 380 статей — по 76 на сайт — плюс пять хаб-страниц, шесть sitemap-файлов, RSS на каждом сайте. Стоимость хостинга — 0 рублей в месяц. Около 90% работы (текст, QA, деплой, запросы на индексацию, RSS-дистрибуция, постинг в Telegram, outreach в каталоги) делает локальный AI-агент; я читаю результат и задаю правила, которые он не нарушает.

Два числа задают ритм всей системы: Google Search Console пускает 10 запросов «запросить индексирование» в сутки, Яндекс.Вебмастер — 150 URL на recrawl в сутки. Размер пакета контента, частота деплоя и темп outreach рассчитываются от них, а не наоборот.

Что построено

Адрес вида dystymis.github.io/{site}/{slug}/ — без сегмента /articles/, без базы и без CMS. У каждого сайта свой git-репозиторий, исходник истины — папка dist/: скрипт deploy.ps1 делает robocopy dist/ в репозитории и пушит. В хаб-репозитории лежат корневая страница, sitemap-hub.xml, llms.txt, robots.txt с 23 группами AI-ботов, security.txt, humans.txt, манифест и файлы верификации для Google и рекламных сетей.

На каждый сайт: sitemap на 78 URL (хаб, страница «о проекте», 76 статей), RSS на 20 элементов, JSON-LD (Article + Breadcrumb + FAQPage), OG-изображения 1200×630 из генератора на PowerShell, запись в Wikidata, снимки в Wayback и archive.today. Отдельно — 6 sitemap на весь домен (индекс + 5 подпапок) и отправка пачек в IndexNow: последний батч принят 346 URL.

Сам домен можно посмотреть здесь: https://dystymis.github.io/.

Бесплатный хостинг — это решение по стоимости, а не SEO-стратегия. Выяснилось, что у него самые тяжёлые последствия для проекта — но о нём ниже.

Конвейер: от ключевика до задеплоенной статьи

Контент уходит пакетами по 50 статей (10 на сайт). Последовательность такая:

  1. План. Ключевые слова кластеризуются в JSON-файл плана: слаг, заголовок, дата.
  2. Брифы. На каждый сайт — свой Markdown-бриф, собранный из плана.
  3. Два параллельных агента. Агент A снимает шаблонный бойлерплейт и пишет уникальные H3-секции. Агент B делает рискованное: возрастные блоки на 18+ сайте (56 из 56 файлов), дисклеймеры YMYL (56/56), description длиной 143–160 символов, две проверенные внешние цитаты на пачку в здоровье (who.int, rospotrebnadzor.ru).
  4. QA. Python-скрипт проверяет frontmatter, даты (будущие даты запрещены — Яндекс отклоняет из-за них RSS), заголовки, description, JSON-LD и внутренние ссылки. На выходе ALL OK или список правок.
  5. Сборка. build.js на Node рендерит статический HTML, функция fitTitle() обрезает заголовок на 60 символах.
  6. Деплой. deploy.ps1 пушит пять репозиториев, затем ping-indexnow.ps1 отправляет пачку.

Три пакета за три дня довели сеть с 280 до 330 и до 380 статей. Ни очередей, ни обновлений плагинов — потому что CMS нет вообще.

Пример статьи с этого конвейера: «Срок хранения хлеба: условия, упаковка» — таблица сроков, FAQ-разметка, внутренние ссылки на соседние тексты про хранение. Обратите внимание на обрезанный заголовок в вкладке — это fitTitle() в действии, один из мелких дефектов, который ещё в бэклоге.

Индексация: 10 запросов в сутки как ограничение архитектуры

Квота GSC — жёсткая стена: 11-й запрос в день заканчивается диалогом «Квота превышена». Автоматизация этой кнопки выглядит совсем не пафосно:

  • кнопка «Запросить индексирование» кликается только через JavaScript: obfuscated-класс в className, сверка textContent, getBoundingClientRect() больше нуля, затем .click();
  • поле поиска заполняется нативным setter’ом плюс события input/change/keydown, потому что обычный .click() Playwright перехватывается оверлеем;
  • перезагрузка страницы перед каждой инспекцией — панель «Отправлено» это сессионное состояние, без reload ловишь false-positive с устаревшей панели;
  • ошибка квоты приходит как [role=dialog], а не как текст страницы — регуляркой по body она не ловится;
  • таймаут MCP-вызова 60–90 с, поэтому один URL за вызов: полный день из 10 запросов — это 10 отдельных оркестрационных шагов.

Яндекс проще: 150 запросов в сутки обычным REST POST /recrawl/queue, по одному URL на запрос, ответ 202 с task_id. (Помощник в MCP отдаёт 404 — ходим в API напрямую.)

Остальное закрывается IndexNow (346 URL за одну отправку) и sitemap. Распределение простое: массово — IndexNow и sitemap, дефицитный ресурс из 10 запросов в день — на те страницы, которые важны прямо сейчас.

Два честных провала. Первый: корень домена неделями висел с noindex, follow без canonical, то есть главной страницы сети не было в индексе, хотя всё под ней индексировалось нормально; исправлено двумя коммитами, а site:dystymis.github.io в качестве отправной точки дал 5 результатов. Второй: сборка GitHub Pages простояла 55 минут в очереди — лечится отменой workflow run и пустым коммитом-триггером. Оба провала были не в контенте.

Дистрибуция, которая работает без меня

Python-скрипт autopost.py читает dist/*/feed.xml (пять фидов), дедуплицирует по GUID в posted.json, собирает HTML-пост «заголовок + описание + ссылка» и отправляет через Telegram Bot API в канал t.me/dystymis_tips, с паузой 3 секунды между сообщениями. Запуск — задача планировщика schtasks /SC HOURLY /MO 4 на .cmd-обёртке: переменные окружения в /TR ломают парсер задач, поэтому обёртка обязательна. Бот @dystymis_tips_bot не мог стать подписчиком канала — Telegram отвечает RPC 400 USER_BOT — его пришлось назначить админом с правом публикации, и нашёлся он только в веб-клиенте с глобальным поиском. Отобранные посты уходят в Дзен.

Вся эта секция стоит ноль: RSS, Bot API, Task Scheduler. Единственный платный элемент — токены модели и моё время на ревью. Токен лежит в файле UTF-8 с BOM; до того, как прочитать его как utf-8-sig, был один запоминающийся круг с 401 Unauthorized.

Что не сработало

Тизерные сети фильтруют бесплатный хостинг. Buymedia отвечает «Заблокировано — Бесплатный хостинг», TeaserMedia и Kadam отказали, Visitweb требует от 50 посещений в сутки. Adsterra и PopCash площадки приняли, HilltopAds одобрил обе зоны, Dao.AD и AdsKeeper на модерации — но при нулевом трафике это бумажка, а не выручка.

Трафика пока нет. Неделя 26.09–02.10 по Яндекс.Метрике: 77, 46, 34, 28, 25 просмотров на пять сайтов, и почти всё — собственные заходы. GSC за 14 дней показал 0 показов. 380 опубликованных статей — это предложение, а не спрос.

Outreach — это статистика с большим количеством тупиков. Один раунд, пять вкладок агентов параллельно в одном браузере, 275 попыток размещения, всё пишется в JSONL-журналы по каждой попытке:

Опубликовано — 34На модерации — 51Отправлено (без подтверждения) — 48Только платно — 31Требуют регистрацию (пропущено) — 20Мёртвые страницы / сломанные формы — 30Отказ за 18+ контент — 15Стены с капчей — 10

Оставшиеся 36 попыток — отказ в размещении, отказ по контенту, дубликаты, ошибки сервера и неопределённые исходы.

Жёсткое правило раунда: ни одна отправка не создаёт аккаунт. Поэтому каждый каталог с обязательной регистрацией помечался и пропускался — это примерно 20 потенциальных размещений в обмен на чистый след. Image-капчи агент решал сам: скриншот через Playwright, чтение картинки, ответ; всё, что требует телефон, соцсети или сложный челлендж, помечалось CAPTCHA_REQUIRED и пропускалось. Сайт 18+ массово отклоняли general-каталоги без adult-тем — ожидаемо, но это заметно сокращает пул площадок для этого хаба.

Однозначный выигрыш раунда — Telegraph: опубликованная dofollow-страница с DR около 90, написанная как настоящий чек-лист, а не свалка ссылок. Описания для каталогов — уникальные под каждую площадку, 300–700 символов, без рейтинговых формулировок, естественные анкоры, один URL хаба плюс один-два deep-link’а.

Выводы

  • Бесплатный хостинг — это фильтр, а не только экономия. Публиковать на github.io ничего не стоит, но рекламные сети и каталоги проверяют это явно. Выбор компромисса нужно делать до фиксации платформы, а не после.
  • Квоты — это элемент планирования, а не досадное ограничение. 10 запросов в сутки означают, что пакет из 50 статей требует пяти дней на индексацию: размер пакета и бюджет индексации считаются вместе, а не постфактум.
  • Журнал по каждой попытке. Строка JSONL на каждую отправку (площадка, статус, DR, заметки) — то, что делает второй раунд на порядок быстрее первого.
  • Автоматизируйте клики, правила держите у себя. Агент решает капчи, заполняет формы и ведёт журналы; запрет на фейковые аккаунты, запрет на обходчики капч и запрет маскировать тематику — это решения, которые я принимаю один раз и зашиваю в бриф.
  • Объём публикаций — не дистрибуция. При 0 показов и 0 внешних ссылок новые статьи в основном добавляют предложение. Запросы на индексацию, RSS, Telegram и outreach закрывают каждый свою конкретную дыру — считать их нужно как отдельные треки со своими метриками.
  • Статическая генерация + RSS + Bot API закрывают почти всю дистрибуцию при близкой к нулю регулярной стоимости. Настоящие затраты — токены модели и время на проверку.

План публикации

  1. Habr — эта русская версия из meta-story-ru-2026-10-07.md, адаптированная под местный формат: меньше хайпа, больше процедур и цифр.
  2. VC.ru — перепубликация после индексации на Habr.
  3. Дзен — сокращённая версия русского текста, тем же конвейером, что и обычные посты.