|
Professor Seleznov
|
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 напрямую маппится в в . Никакой отдельной базы соответствий.
- Нет 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. ID ARTICLE_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 автоматически ставит на все три версии. x-default направили на RU, это основная аудитория.

Одна статья блога в трёх языковых версиях: русская, казахская, английская. hreflang связывает все три через автоматически — редактировать вручную ничего не нужно». 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. При шаринге статьи выглядят как у полноценного медиа.

Сетка статей на главной блога. У каждой — своя OG-обложка: Gemini API генерирует тематический фон, PIL композитит его с фото автора из списка AUTHOR_MAP. Три автора, четыре категории, один фирменный стиль 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: GPTBot Disallow: / User-Agent: ChatGPT-User Disallow: / User-Agent: CCBot Disallow: / User-Agent: Google-Extended Disallow: / User-Agent: Bytespider Disallow: / User-Agent: anthropic-ai Disallow: /
В нашем случае это создаёт этическую неоднозначность: сами генерируем контент через 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) и про процессы квартального аудита и обновления статей.-Источник
|