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 на сайт). Последовательность такая:
- План. Ключевые слова кластеризуются в JSON-файл плана: слаг, заголовок, дата.
- Брифы. На каждый сайт — свой Markdown-бриф, собранный из плана.
- Два параллельных агента. Агент A снимает шаблонный бойлерплейт и пишет уникальные H3-секции. Агент B делает рискованное: возрастные блоки на 18+ сайте (56 из 56 файлов), дисклеймеры YMYL (56/56), description длиной 143–160 символов, две проверенные внешние цитаты на пачку в здоровье (who.int, rospotrebnadzor.ru).
- QA. Python-скрипт проверяет frontmatter, даты (будущие даты запрещены — Яндекс отклоняет из-за них RSS), заголовки, description, JSON-LD и внутренние ссылки. На выходе ALL OK или список правок.
- Сборка. build.js на Node рендерит статический HTML, функция fitTitle() обрезает заголовок на 60 символах.
- Деплой. 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 закрывают почти всю дистрибуцию при близкой к нулю регулярной стоимости. Настоящие затраты — токены модели и время на проверку.
План публикации
- Habr — эта русская версия из meta-story-ru-2026-10-07.md, адаптированная под местный формат: меньше хайпа, больше процедур и цифр.
- VC.ru — перепубликация после индексации на Habr.
- Дзен — сокращённая версия русского текста, тем же конвейером, что и обычные посты.