Was macht og-image-kit?
Ziel: Jede öffentliche Seite hat ein 1200×630-Sharing-Bild und korrekte og:* / twitter:*-Tags, und du hast sie überprüft mit scripts/check_og.py, nicht nur geschrieben.
Schritt 1 – Stack erkennen
Sieh dir das Repository an, bevor du etwas schreibst:
| Signal | Stack | Gehe zu |
|---|---|---|
next in package.json und ein app/ (oder src/app/)-Verzeichnis | Next.js App Router | Schritt 2A |
next nur mit pages/ | Next.js Pages Router | Schritt 2C (statisch) oder /api/og mit ImageResponse hinzufügen |
astro in package.json | Astro | Schritt 2B |
| Reines HTML, Hugo, Jekyll, Vite SPA, alles andere | Statisch | Schritt 2C |
Finde auch: die kanonische Basis-URL der Seite (Umgebungsvariable wie NEXT_PUBLIC_SITE_URL, site in astro.config.*), Markenfarben, Logo und die verwendete Schriftart. Frage den Benutzer nur, wenn nichts gefunden werden kann.
Schritt 2A – Next.js App Router
- Stelle sicher, dass das Root-Layout
metadataBaseexportiert (OG-URLs müssen absolut sein):export const metadata = { metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000") } - Kopiere
assets/nextjs/opengraph-image.tsxnachapp/opengraph-image.tsx(Seitenstandard). BearbeiteBRAND, Farben und Tagline. - Für dynamische Routen (Blogbeiträge, Produkte) kopiere es in das Routensegment, z.B.
app/blog/[slug]/opengraph-image.tsx, und verwendeassets/nextjs/dynamic-opengraph-image.tsx, dasparamsliest und den Titel aus deiner Datenquelle lädt. In Next.js 15+ istparamsein Promise –awaites. - Füge
twitter-image.tsxnur hinzu, wenn sich die X-Karte unterscheiden muss; andernfalls verwendet Next.js das OG-Bild erneut, wenn dutwitter: { card: "summary_large_image" }in den Metadaten setzt. - Pro-Seite-Text: Setze
titleunddescriptionin denmetadata/generateMetadatajeder Seite. - Benutzerdefinierte Schriftarten: Lade eine TTF/OTF (nicht WOFF2) via
fetch(new URL("./Inter-Bold.ttf", import.meta.url))oderreadFile. CJK-Text benötigt eine CJK-Schriftartdatei, sonst werden sie als Kästchen dargestellt – subsette sie, um die Größe klein zu halten.
Zu beachtende Grenzen (next/og / satori): nur Flexbox (kein Grid), jedes div mit mehreren Kindern benötigt
display: "flex", halte das Bundle klein – die Next.js-Dokumentation zu ImageResponse listet ein 500-KB-Limit für
JSX + CSS + Schriftarten + Bilder auf. Große Schriftarten verlangsamen auch das Rendering, subsette sie daher.
Schritt 2B – Astro
Verwende assets/astro/og-endpoint.ts als src/pages/og/[...slug].png.ts. Es rendert ein PNG pro Seite zur
Build-Zeit mit satori + @resvg/resvg-js (npm i satori @resvg/resvg-js), und du referenzierst es von deinem Layout:
<meta property="og:image" content={new URL(`/og/${slug}.png`, Astro.site)} />
Astro.site muss in astro.config.mjs gesetzt sein. Schriftartdatei: Lege eine TTF in src/assets/fonts/ ab.
Schritt 2C – Statische Seiten / alles andere
Generiere PNGs einmalig und committe sie:
python3 scripts/generate_og.py --pages pages.json --out public/og --brand "Acme" --bg "#0f172a" --fg "#ffffff" --accent "#38bdf8"
pages.json ist eine Liste von {"slug": "pricing", "title": "...", "subtitle": "..."} (siehe
assets/pages.example.json). Erfordert Pillow (pip install pillow). Übergib --font path/to/font.ttf
für Markenschriftarten oder CJK-Text (z.B. Noto Sans SC). Füge dann die Tags zu jeder Seite hinzu (Vorlage in
references/meta-tags.md).
Schritt 3 – Erforderliche Tags (jede Seite)
<meta property="og:title" content="Seitentitel" />
<meta property="og:description" content="Ein Satz, max. ~160 Zeichen" />
<meta property="og:image" content="https://example.com/og/page.png" /> <!-- absolute URL -->
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:url" content="https://example.com/page" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" />
Next.js generiert diese aus metadata + opengraph-image.tsx; schreibe keine Duplikate von Hand.
Schritt 4 – Überprüfen (nicht überspringen)
Führe es gegen die laufende Seite aus (Dev-Server, Preview-Deploy oder Produktion):
python3 scripts/check_og.py http://localhost:3000/ http://localhost:3000/pricing
python3 scripts/check_og.py --json https://example.com/ # maschinenlesbar
Es ruft jede Seite ab, überprüft die erforderlichen Tags, dass og:image absolut, erreichbar,
ein Bild-Content-Type, ~1,91:1 und mindestens 600 Pixel breit und unter 5 MB ist. Exit-Code 1 bei jedem Fehler.
Behebe alles, was als ERROR markiert ist; WARN-Einträge sind Empfehlungen.
Hinweis: Soziale Plattformen cachen Vorschauen. Nach der Behebung verwende den Debugger der Plattform selbst
(LinkedIn Post Inspector, Facebook Sharing Debugger), um erneut zu scrapen. X hat keinen öffentlichen Validator mehr;
poste in einem Entwurf/einer DM, um zu überprüfen. localhost-URLs können von diesen Tools nicht gescrapt werden – deploye zuerst.
Gestaltungsrichtlinien für das Bild
- 1200×630, PNG, Text innerhalb eines ~60 px Sicherheitsabstands; Titel ≤ ~60 Zeichen, max. 3 Zeilen.
- Hoher Kontrast; es wird klein (~500 px breit) in Feeds angezeigt. Teste bei 50 % Zoom.
- Markenname/Logo einfügen; vermeide winzigen Text (< 28 px bei 1200 Breite).
- Siehe
references/platform-specs.mdfür plattformspezifische Hinweise.
Erledigt, wenn
- Jede indexierbare Seite gibt og:title, og:description, og:image (absolut), twitter:card zurück
-
check_og.pybeendet sich mit Exit-Code 0 für die Startseite und mindestens eine Seite jedes Routentyps - Bilder sehen richtig aus (öffne ein PNG und schau es dir an)