आलसी डेवलपर्स के लिए रिच लिंक

जब मैं Twitter या Slack पर एक ब्लॉग लिंक साझा करता हूं, तो यह सादे टेक्स्ट के रूप में दिखाई देता है। कोई पूर्वावलोकन छवि नहीं। बस एक URL जैसे granda.org/en/2026/01/02/claude-code-on-the-go/

मुझे Open Graph छवियों की आवश्यकता थी। मानक दृष्टिकोण: प्रत्येक पोस्ट के लिए मैन्युअल रूप से 1200x630 छवि बनाएं। यह थकाऊ है। मैंने Claude से इसे स्वचालित करने के लिए कहा।

flowchart LR
    Push[git push] --> GHA[GitHub Actions]
    GHA --> Hugo[Hugo Server]
    GHA --> PW[Playwright]
    PW -->|screenshot| Hugo
    PW --> IMG[OG Image]
    IMG --> Commit[git commit]
    Commit --> Deploy[Deploy]
flowchart TB
    Push[git push] --> GHA[GitHub Actions]
    GHA --> Hugo[Hugo Server]
    GHA --> PW[Playwright]
    PW -->|screenshot| Hugo
    PW --> IMG[OG Image]
    IMG --> Commit[git commit]
    Commit --> Deploy[Deploy]

सेटअप

मैंने Claude को समस्या बताई: पोस्ट को सोशल पूर्वावलोकन छवियों की आवश्यकता है, लेकिन मैं उन्हें मैन्युअल रूप से नहीं बनाना चाहता। लेख की सामग्री का स्क्रीनशॉट लें, इसे OG छवि के रूप में सहेजें, फ्रंटमैटर को स्वचालित रूप से अपडेट करें।

Claude ने क्या बनाया

घटकउद्देश्य
generate-og-image.jsपोस्ट के स्क्रीनशॉट के लिए Playwright स्क्रिप्ट
generate-og-images.ymlपोस्ट परिवर्तनों पर ट्रिगर होने वाला GitHub Action
baseof.html परिवर्तनसशर्त og:image मेटा टैग

Playwright स्क्रिप्ट हेडलेस Chrome लॉन्च करती है, पोस्ट पर नेविगेट करती है, लाइट मोड को मजबूर करती है, हेडर और फुटर को छिपाती है, और 1200x630 पर स्क्रीनशॉट लेती है:

const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
  viewport: { width: 1200, height: 630 },
  deviceScaleFactor: 2, // Retina for crisp text
});

// Force light mode, hide nav
await page.evaluate(() => {
  document.documentElement.setAttribute("data-theme", "light");
  document.querySelector("header").style.display = "none";
  document.querySelector("footer").style.display = "none";
});

await page.screenshot({ path: outputPath, type: "png" });

GitHub Action किसी भी .en.md फ़ाइल परिवर्तन पर ट्रिगर होता है, Hugo शुरू करता है, स्क्रिप्ट चलाता है, और उत्पन्न छवि को रेपो में वापस कमिट करता है:

on:
  push:
    branches: [main]
    paths:
      - "content/posts/**/*.md"

steps:
  - name: Start Hugo server
    run: hugo server --bind 0.0.0.0 --port 1313 &

  - name: Generate OG images
    run: node scripts/generate-og-image.js "$file"

  - name: Commit changes
    run: |
      git add static/images/posts/ content/posts/
      git commit -m "Generate Open Graph images for blog posts"
      git push

टेम्पलेट सशर्त रूप से छवि शामिल करता है जब फ्रंटमैटर में image फ़ील्ड होता है:

{{- if .Params.image -}}
<meta property="og:image" content="{{ $canonical }}{{ .Params.image }}">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="{{ $canonical }}{{ .Params.image }}">
{{- else -}}
<meta name="twitter:card" content="summary">
{{- end -}}

404: स्लग नहीं मिला

पहला रन। Playwright ने एक खाली पृष्ठ का स्क्रीनशॉट लिया। URL ने 404 लौटाया।

स्क्रिप्ट ने फ़ाइल नाम से URL बनाया था: automatic-blog-translations.en.md/en/2025/12/23/automatic-blog-translations/

लेकिन Hugo स्लग के लिए फ़ाइल नाम का उपयोग नहीं करता है। यह शीर्षक का उपयोग करता है। वास्तविक URL /en/2025/12/23/automatic-blog-translations-with-claude-and-github-actions/ था।

मैं JavaScript में Hugo के slugify एल्गोरिदम को पुनर्कार्यान्वित कर सकता था। इसके बजाय: Hugo से पूछें।

const output = execSync("hugo list all", { encoding: "utf8" });
// CSV output includes the exact permalink Hugo generates

एक पंक्ति। कोई एज केस नहीं। Hugo पहले से ही अपने स्वयं के URL जानता है।

आगे क्या है

वर्तमान कार्यान्वयन केवल अंग्रेजी पोस्ट के लिए छवियां उत्पन्न करता है। अनुवादित संस्करण उसी छवि पथ का संदर्भ देते हैं, जो काम करता है, लेकिन इसका मतलब है कि स्पेनिश या जापानी संस्करण साझा करते समय भी OG छवि हमेशा अंग्रेजी पाठ दिखाती है।

सच्चा i18n समर्थन अगले PR में आ रहा है। अभी के लिए, प्रत्येक पोस्ट को एक सोशल छवि मिलती है, जो कुछ नहीं से बेहतर है।

निष्कर्ष

इसे बनाने और डीबग करने में 14 मिनट लगे। अब प्रत्येक पोस्ट को स्वचालित रूप से एक सोशल पूर्वावलोकन छवि मिलती है। प्रति पोस्ट कोई मैन्युअल काम नहीं। स्वचालन मुट्ठी भर पोस्ट के बाद खुद को चुका देता है।

काम करने वाले संस्करण को भेजें, अंतराल की खोज करें, पुनरावृत्ति करें।


संबंधित पोस्ट: