TL;DR
-
Делали SEO-блог под SAT-направление для школьников из СНГ. Нужно было SEO сразу на трёх языках: RU, KK, EN.
-
Написали 28 уникальных статей. Каждая переведена на три языка, итого 84 файла контента и 90 URL в sitemap. От первой строки до индексации в Google и Яндексе ушло три календарных дня.
-
Пайплайн на Claude API, Next.js 16 и GitHub CI/CD. Без CMS, без Markdown, без headless платформ. Статьи хранятся как TypeScript-файлы.
-
Соотношение AI / ручная работа у нас получилось примерно 70/30. Остальные 30% (вычитка фактов, локализация идиом, финальные правки) — человек. Без этой части статьи быстро уходят в low-quality индекс.
-
В
robots.txtзапрещены AI-краулеры (GPTBot, ChatGPT-User, Google-Extended, anthropic-ai и другие). Так делают многие крупные медиа. В паре с AI-генерируемым блогом это создаёт этическую неоднозначность, про неё — ниже.

Контекст и задача
В апреле 2026 мы запустили русскоязычную SAT-платформу для школьников из Казахстана, России и Узбекистана. SAT — экзамен для поступления в американские вузы, русскоязычного аналога Khan Academy для него не существует.
Сразу стало понятно: без органического трафика платформа умрёт через месяц. Платная реклама в нашей нише неадекватно дорогая (аудитория узкая, аукцион перегрет), остаётся SEO. А у нас три языка одновременно: русский, казахский, английский. Это три разных хаба ключевиков, три блога, три версии каждой статьи.
Нанять под это в штат двух копирайтеров и переводчика — убить бюджет до запуска. Решение напросилось: автоматизировать генерацию и публикацию через Claude API.
Почему статьи как TypeScript, а не Markdown
Стандартно SEO-блоги делают на Markdown, MDX, Contentlayer или headless CMS типа Sanity. У нас каждая статья лежит в .ts файле и экспортирует типизированный объект BlogArticle.
import type { BlogArticle } from '../../types';export const satGrammarRules: BlogArticle = { slug: 'sat-grammar-rules', locale: 'ru', title: 'SAT Grammar Rules — полный список правил', description: 'Все правила грамматики для секции Reading & Writing...', keywords: ['SAT grammar', 'SAT правила грамматики', /* ... */], excerpt: 'Краткое описание для карточки...', heroImage: '/landing/blog/grammar.png', heroAlt: 'SAT Grammar Rules — список правил', publishedAt: '2026-03-20', readingTime: 12, author: 'yanina', alternates: { en: 'sat-grammar-rules-complete-list', kk: 'sat-grammatika-erezheleri', }, content: `## Первый заголовок H2Текст параграфа. Markdown формат....`,};
Почему так:
-
Типобезопасность. Забыл поле
readingTimeили опечатался вlocale. TypeScript ругается в IDE, до билда дело не доходит. С Markdown frontmatter такое ловится в рантайме, часто уже в проде. -
hreflang из коробки. Поле
alternatesнапрямую маппится в<link rel="alternate" hreflang="...">в<head>. Никакой отдельной базы соответствий. -
Нет CMS — нет зависимости. Contentful падает, блог падает. GitHub падает — ну, такое.
-
Diff-able review. Изменение статьи — это PR с понятным diff. Можно посмотреть blame, прогнать CI-проверки на обновлённый контент.
Минус один: авторам-нетехнарям нужен хотя бы VSCode и минимальное понимание git. В нашем случае автор один, и трейд-офф приемлем.
Промпт, который реально работает
Типовая ошибка AI-пайплайнов: короткий промпт «напиши SEO-статью про X». Claude пишет гладко, получается универсальный контент, который Google давно научился отсеивать в low-quality.
Наш промпт лежит в файле seo/ARTICLE-GUIDE.md на 361 строку. Передаётся целиком как system prompt. Что в нём:
-
Структура TypeScript-файла с примером корректного объекта
BlogArticle -
Требования к контенту: 3-8 секций H2, обязательные H3 внутри, таблицы где уместно, списки, итоговый CTA
-
Список существующих статей блога с URL — Claude видит и обязан проставить 2-3 internal-ссылки
-
Стилистические гайдлайны: избегать общих фраз типа «в современном мире», приводить конкретные цифры, использовать прямую речь
-
Чеклист перед выдачей: все поля заполнены, keywords не пустые, alternates содержит slug для всех трёх языков
Главное, что я вынес за два месяца экспериментов: качество AI-контента на 70% определяется не моделью, а детальностью системного промпта. Разница между 50-строчным и 350-строчным промптом на одной и той же модели — это разница между «сойдёт» и «реально ранжируется».
Internal linking — отдельная боль. Без явного списка существующих статей в промпте Claude сочиняет ссылки типа /blog/how-to-pass-sat, которых у нас нет. На выходе 404. С явным списком ставит только реальные URL, и каждая новая статья усиливает перелинковку старых.
Регистрация в 6 местах, или плата за типизацию
Про это честно скажу отдельно. Добавить статью — не одно действие, а шесть. Claude выдал .ts файл контента, дальше руками (или через скрипт-обёртку) регистрируем статью в frontend/src/lib/i18n/blog/articles.ts:
// 1. IDARTICLE_IDS.push('sat-grammar-rules');// 2. URL slug на каждом языкеSLUG_MAP['sat-grammar-rules'] = { ru: 'sat-grammar-rules', en: 'sat-grammar-rules-complete-list', kk: 'sat-grammatika-erezheleri',};// 3. КатегорияCATEGORY_MAP['sat-grammar-rules'] = 'writing';// 4. АвторAUTHOR_MAP['sat-grammar-rules'] = 'yanina';// 5. ДатыDATES_MAP['sat-grammar-rules'] = { publishedAt: '2026-03-20', updatedAt: '2026-03-20',};// 6. Рейтинг (для Review schema)RATING_MAP['sat-grammar-rules'] = { value: 4.8, count: 12 };// + loader в getArticle() для каждого языка
Зачем так, если можно было просто прочитать папку с файлами? Ради статической сборки Next.js. generateStaticParams и generateMetadata работают с этими мапами без обращения к файловой системе. На выходе быстрая сборка (1-2 минуты на 84 статьи) и стабильный SSG.
Честный минус: для массовой генерации это добавляет скрипт на 30 строк. Скрипт парсит выдачу Claude и автодополняет мапы. Один раз написал, забыл.
Как устроена локализация на 3 языках
На старте мы пробовали генерировать три версии независимо. Получили три разных фактологических варианта одной статьи. Три пруф-чека, три SEO-оптимизации, тройная нагрузка на вычитку. Отказались. Сейчас схема такая:
-
Claude пишет полную русскую версию с максимальной детализацией.
-
Отдельным вызовом с другим промптом Claude переводит и адаптирует на английский и казахский. Промпт явно говорит: не просто переводи, локализуй с учётом SAT-контекста местной аудитории.
-
Slug на каждом языке свой (не транслит), прописывается в
alternates. -
Next.js через
generateMetadataавтоматически ставит<link rel="alternate" hreflang="ru|kk|en|x-default">на все три версии.x-defaultнаправили на RU, это основная аудитория.
OG-изображения: Gemini + PIL вместо дизайнера
Для каждой статьи нужно уникальное превью 1200×630. Влияет и на SEO, и на CTR в соцсетях. 84 картинки руками в Figma — отдельная катастрофа.
Написали гибридный пайплайн в файле generate-blog-covers.py:
-
Через Gemini 2.5 Flash Image API генерируем тематический фон 1200×630 по теме статьи (например, «SAT Math formulas pattern» или «abstract reading background»).
-
Через PIL на этот фон композитим вырезанное фото автора статьи (у нас три автора: два эксперта плюс обобщённая марка проекта). Вырезание белого фона, мягкая тень, лёгкое свечение.
-
На выходе PNG, который идёт в
heroImageстатьи и в OG-метатеги.
Почему два разных AI в пайплайне вместо одного. Для связного текста Claude объективно лучше, но на генерации картинок он пока отстаёт. Gemini Flash Image — это быстро (секунды на картинку), дёшево и заточено под нашу задачу: осмысленный тематический фон, а не фотореалистичное изображение. Текст и лица генерировать ему не доверяем, поэтому фото авторов всегда настоящие, аккуратно вырезанные.
Работает минуту на всю серию. Получаем уникальные карточки для Telegram, VK, Facebook, Twitter. При шаринге статьи выглядят как у полноценного медиа.
Sitemap и robots: чего делать не стоит
Sitemap мы собираем прямо из articles.ts в файле frontend/src/app/sitemap.ts — стандартный Next.js 16 способ. На выходе 90 URL: 3 лендинга + 3 блог-индекса + 84 статьи. lastModified динамический, берётся из DATES_MAP.updatedAt.
С robots.txt мы сделали то же, что в 2025–2026 делают многие крупные медиа (NYT, Reuters, BBC, CNN): явно запретили AI-краулеры.
User-Agent: GPTBotDisallow: /User-Agent: ChatGPT-UserDisallow: /User-Agent: CCBotDisallow: /User-Agent: Google-ExtendedDisallow: /User-Agent: BytespiderDisallow: /User-Agent: anthropic-aiDisallow: /
В нашем случае это создаёт этическую неоднозначность: сами генерируем контент через Claude, но другим моделям на нём обучаться не даём. Наша позиция: мы заплатили за генерацию (API-токены), несём репутационную ответственность за факты в статьях (вычитка, правки, пруф). Отдавать этот контент бесплатно на обучение моделей, которые через полгода будут конкурировать с нашим трафиком, резона не видим. Поисковые боты (Googlebot, YandexBot) пускаем, AI-боты нет.
Понятно, что это не останавливает всех. Скрейперы, которые игнорируют robots.txt, существуют. Но на официальных краулерах крупных лабораторий работает.
Результаты и честные минусы
Что получили за три дня:
-
28 уникальных статей × 3 языка = 84 файла контента, ~75 000 слов
-
90 URL в sitemap, отправлены в GSC и Яндекс.Вебмастер
-
Все статьи с уникальными OG-превью, hreflang, JSON-LD Article schema
-
Индексация пошла в обеих системах, трафик начал расти через 2 недели после публикации
По экономике сравнение грубое и зависит от рынка. Руками 84 текста на трёх языках при средних ставках копирайтера и переводчика — это десятки тысяч долларов и 6-8 недель работы команды. У нас вся серия вписалась в несколько сотен долларов на API и инфраструктуру плюс три дня одного человека с прочими задачами параллельно. Соотношение по деньгам — порядок (десятки раз), по времени — на порядок-два. При этом 30% работы (вычитка фактов, проверка KK-локализации носителем) всё равно делал человек, и без этих 30% статьи быстро уходят в low-quality индекс.
Где AI косячит и где ручная работа неизбежна. Те самые 30% человеческой работы распределены примерно так:
-
Цифры и даты. Claude регулярно придумывает статистику типа «по данным College Board 85% студентов…» с несуществующей ссылкой. Мы ввели правило: любая статистика либо реальная с пруфом, либо её нет в тексте. Ловится только ручной вычиткой.
-
Обновление статей. SAT меняется, даты плавают, College Board обновляет формат. Автоматически Claude это не отслеживает, нужен отдельный процесс аудита раз в квартал.
-
Уникальные инсайты. AI пишет корректно, но не даёт того, что даёт эксперт после пяти лет в теме. Самые сильные статьи у нас те, где Claude написал черновик, а человек добавил свой опыт и конкретные случаи.
Как повторить этот пайплайн у себя
Если у вас есть Next.js проект и хочется закрыть SEO-блог без найма копирайтера, примерный путь такой:
-
Определите 20-30 ключевых запросов в своей нише через GSC (если уже есть сайт) или Ahrefs/Similarweb/Serpstat. Каждый запрос — это будущая статья.
-
Составьте типовую структуру статьи под свой домен: какие H2 нужны, какие поля метаданных, какие internal-ссылки. Это ваш будущий
BlogArticleтип в TypeScript. -
Напишите большой system prompt с этой структурой, примерами, стилевыми гайдлайнами («избегай общих фраз», «приводи цифры», «ссылайся только на реальные URL из списка»). Начните со 200 строк, доращивайте до 400+ по мере ошибок.
-
Пишите через Claude API (или GPT/Gemini) итеративно. Каждая статья — отдельный вызов с одним и тем же system prompt и новыми параметрами темы. Claude Sonnet для такого достаточно, Opus излишен.
-
Сохраняйте как TypeScript, коммитьте в GitHub. Настройте CI/CD на автодеплой в Vercel или AWS App Runner. Sitemap генерируется Next.js автоматически из вашего реестра статей.
-
Обязательно вручную: факт-чек цифр, финальная вычитка на калькированные обороты, если есть локализация — проверка носителем. Это те 30%, без которых статьи уходят в low-quality.
-
В
robots.txtрешите позицию по AI-краулерам. Можете пускать, можете блокировать. Главное, чтобы Googlebot и YandexBot были открыты.
Время на первый запуск (20-30 статей на одном языке): 2-3 дня работы одного человека с нормальной занятостью по основным задачам. На три языка плюс вычитка носителем — неделя.
Что дальше
-
Автоматизировать обновление статей: скрипт, который раз в месяц проверяет даты SAT-экзаменов на College Board и обновляет соответствующие поля в нужных статьях.
-
Интеграция с Google Indexing API и IndexNow для мгновенного пинга поисковиков после публикации (сейчас индексация идёт органически, через 7-14 дней).
-
A/B тест заголовков на основе данных GSC: статьи с высокими impressions и низким CTR автоматически получают 2-3 альтернативных заголовка для теста.
-
Выход на четвёртый язык (узбекский) — но только после стабилизации KK-версий.
Готов отвечать на вопросы в комментариях. Если зайдёт то напишу продолжение про техническую часть AI-тьютора (RAG + Claude tool use) и про процессы квартального аудита и обновления статей.
ссылка на оригинал статьи https://habr.com/ru/articles/1031082/