Worklog for task "Configure Open Graph / meta tags for correct page previews in messengers"
Progress: First an Executable Check, Then Implementation
Before making any changes, a separate terminal TypeScript script was written first. It makes an HTTP request to the page, parses the HTML via cheerio, and checks for required Open Graph tags. This provided an objective baseline before making edits and a ready-made acceptance criterion for the AI agent.
Verification Script
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);
});
State Before Implementation
The first run yielded the expected negative result:
HTTP: 200
β og:title: missing
β og:description: missing
β og:image: missing
β og:url: missing
β og:type: missing
RESULT: invalid or incomplete
After that, the task was passed to the AI agent not as an abstract formulation like "add Open Graph", but along with a specific verification script and a reproducible way to check the result.
Agent Report
The agent reported the following changes:
Done. Changes:
index.tsx β added props image and ogType, rendering og:title, og:description, og:image, og:url, og:type
index.tsx β computed imageUrl and passed it to SeoHeaders with ogType="product"
You can check with the script:
npx tsx scripts/check-page-image/index.ts "http://localhost:3000/catalog/product.html"
Re-Verification
After the changes, the same verification approach yielded:
HTTP: 200
β og:title: Small-sized Playground Korabl
β og:description: Size 3.48 x 1.78 x 2.32 m.
β og:image: http://localhost:3000/images/resized/middle/images/img.jpg
β og:url: http://localhost:3000/catalog/product.html
β og:type: product
RESULT: OK
Practical Conclusion
The approach proved useful: first, a small executable check is created that captures the current state and readiness criteria, and then this same check is passed to the executor along with the task. This reduces ambiguity in the task assignment and makes the result verifiable not by the agent's report, but by the actual behavior of the system.
The next step is to strengthen this pattern: if the agent is given a verification script, the assignment should immediately require not only making changes, but also independently running this script after implementation and attaching the actual result. Then the cycle becomes closed-loop: reproduce β implement β verify, and the human is left with control verification rather than primary verification.
Explicitly define preview metadata (title, description, image) for website pages so that messengers and social networks correctly generate link cards.