Ворклог по задаче "Настроить Open Graph / meta-теги для корректных превью страниц в мессенджерах"
Прогресс: сначала исполнимая проверка, потом реализация
Перед внесением изменений сначала был написан отдельный терминальный TypeScript-скрипт, который делает HTTP-запрос к странице, парсит HTML через cheerio и проверяет обязательные Open Graph-теги. Это дало объективный baseline до начала правок и готовый критерий приёмки для ИИ-агента.
Проверочный скрипт
import * as cheerio from "cheerio";
const REQUIRED_TAGS = [
"og:title",
"og:description",
"og:image",
"og:url",
"og:type",
] as const;
function isAbsoluteHttpUrl(value: string): boolean {
try {
const url = new URL(value);
return url.protocol === "http:" || url.protocol === "https:";
} catch {
return false;
}
}
async function main() {
const targetUrl = process.argv[2];
if (!targetUrl) {
console.error("Usage: npx tsx check-open-graph.ts <url>");
process.exit(2);
}
const response = await fetch(targetUrl, {
redirect: "follow",
headers: {
"User-Agent": "OpenGraphChecker/1.0",
},
});
if (!response.ok) {
console.error(`HTTP ${response.status} ${response.statusText}`);
process.exit(1);
}
const html = await response.text();
const $ = cheerio.load(html);
let hasErrors = false;
console.log(`HTTP: ${response.status}\n`);
const values = Object.fromEntries(
REQUIRED_TAGS.map((property) => {
const value =
$(`meta[property="${property}"]`).first().attr("content")?.trim() ?? "";
if (!value) {
console.log(`✗ ${property}: missing`);
hasErrors = true;
} else {
console.log(`✓ ${property}: ${value}`);
}
return [property, value];
}),
);
const image = values["og:image"];
const ogUrl = values["og:url"];
if (image && !isAbsoluteHttpUrl(image)) {
console.log(`✗ og:image is not absolute: ${image}`);
hasErrors = true;
}
if (ogUrl && !isAbsoluteHttpUrl(ogUrl)) {
console.log(`✗ og:url is not absolute: ${ogUrl}`);
hasErrors = true;
}
console.log(
hasErrors
? "\nRESULT: invalid or incomplete"
: "\nRESULT: OK",
);
process.exit(hasErrors ? 1 : 0);
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
Состояние до реализации
Первый запуск дал ожидаемо отрицательный результат:
HTTP: 200
✗ og:title: missing
✗ og:description: missing
✗ og:image: missing
✗ og:url: missing
✗ og:type: missing
RESULT: invalid or incomplete
После этого задача была передана ИИ-агенту уже не в абстрактной формулировке «добавить Open Graph», а вместе с конкретным скриптом проверки и воспроизводимым способом проверить результат.
Отчёт агента
Агент сообщил о следующих изменениях:
Готово. Изменения:
index.tsx — добавлены props image и ogType, выводятся og:title, og:description, og:image, og:url, og:type
index.tsx — вычисляется imageUrl и передаётся в SeoHeaders с ogType="product"
Можешь проверить скриптом:
npx tsx scripts/check-page-image/index.ts "http://localhost:3000/catalog/product.html"
Повторная проверка
После изменений тот же проверочный подход дал:
HTTP: 200
✓ og:title: Мелкогабаритная площадка Корабль
✓ og:description: Размер 3.48 х 1.78 х 2.32 м.
✓ og:image: http://localhost:3000/images/resized/middle/images/img.jpg
✓ og:url: http://localhost:3000/catalog/product.html
✓ og:type: product
RESULT: OK
Практический вывод
Подход оказался полезным: сначала создаётся маленькая исполнимая проверка, фиксирующая текущее состояние и критерий готовности, а затем эта же проверка передаётся исполнителю вместе с задачей. Это уменьшает неоднозначность постановки и делает результат проверяемым не по отчёту агента, а по фактическому поведению системы.
Следующий шаг — усиливать этот шаблон: если агенту даётся проверочный скрипт, в постановке сразу требовать не только внести изменения, но и самостоятельно запустить этот скрипт после реализации и приложить фактический результат. Тогда цикл становится замкнутым: reproduce → implement → verify, а человеку остаётся уже контрольная, а не первичная проверка.
Явно задать для страниц сайта метаданные превью (заголовок, описание, изображение), чтобы мессенджеры и соцсети корректно формировали карточку ссылки.