Que fait og-image-kit ?
Objectif : chaque page publique dispose d'une image de partage 1200×630 et des balises og:* / twitter:* correctes, et vous les avez vérifiées avec scripts/check_og.py, pas seulement écrites.
Étape 1 — Détecter la pile
Examinez le dépôt avant d'écrire quoi que ce soit :
| Signal | Pile | Aller à |
|---|---|---|
next dans package.json et un répertoire app/ (ou src/app/) | Next.js App Router | Étape 2A |
next avec uniquement pages/ | Next.js Pages Router | Étape 2C (statique) ou ajouter /api/og avec ImageResponse |
astro dans package.json | Astro | Étape 2B |
| HTML simple, Hugo, Jekyll, SPA Vite, autre chose | Statique | Étape 2C |
Trouvez aussi : l'URL de base canonique du site (variable d'environnement comme NEXT_PUBLIC_SITE_URL, site dans astro.config.*), les couleurs de la marque, le logo et la police utilisée. Ne demandez à l'utilisateur que si rien ne peut être trouvé.
Étape 2A — Next.js App Router
- Assurez-vous que la mise en page racine exporte
metadataBase(les URL OG doivent être absolues) :export const metadata = { metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000") } - Copiez
assets/nextjs/opengraph-image.tsxversapp/opengraph-image.tsx(image par défaut du site). ModifiezBRAND, les couleurs et le slogan. - Pour les routes dynamiques (articles de blog, produits), copiez-le dans le segment de route, par ex.
app/blog/[slug]/opengraph-image.tsx, et utilisezassets/nextjs/dynamic-opengraph-image.tsx, qui litparamset charge le titre depuis votre source de données. Dans Next.js 15+,paramsest une promesse — utilisezawait. - Ajoutez également
twitter-image.tsxuniquement si la carte X doit différer ; sinon Next.js réutilise l'image OG lorsque vous définisseztwitter: { card: "summary_large_image" }dans les métadonnées. - Texte par page : définissez
titleetdescriptiondans lesmetadata/generateMetadatade chaque page. - Polices personnalisées : chargez un fichier TTF/OTF (pas WOFF2) via
fetch(new URL("./Inter-Bold.ttf", import.meta.url))oureadFile. Le texte CJK nécessite une police CJK, sinon il s'affiche sous forme de boîtes — réduisez-la en sous-ensemble.
Limites à respecter (next/og / satori) : flexbox uniquement (pas de grille), chaque div avec plusieurs enfants nécessite
display: "flex", gardez le bundle petit — la documentation ImageResponse de Next.js liste une limite de 500 Ko pour
JSX + CSS + polices + images. Les grandes polices ralentissent aussi le rendu, réduisez-les en sous-ensemble.
Étape 2B — Astro
Utilisez assets/astro/og-endpoint.ts comme src/pages/og/[...slug].png.ts. Il génère un PNG par page au
moment du build avec satori + @resvg/resvg-js (npm i satori @resvg/resvg-js), et vous le référencez
depuis votre mise en page :
<meta property="og:image" content={new URL(`/og/${slug}.png`, Astro.site)} />
Astro.site doit être défini dans astro.config.mjs. Fichier de police : placez un TTF dans src/assets/fonts/.
Étape 2C — Sites statiques / autre
Générez les PNG une fois et commitez-les :
python3 scripts/generate_og.py --pages pages.json --out public/og --brand "Acme" --bg "#0f172a" --fg "#ffffff" --accent "#38bdf8"
pages.json est une liste de {"slug": "pricing", "title": "...", "subtitle": "..."} (voir
assets/pages.example.json). Nécessite Pillow (pip install pillow). Passez --font path/to/font.ttf
pour les polices de marque ou le texte CJK (ex. Noto Sans SC). Ajoutez ensuite les balises à chaque page (modèle dans
references/meta-tags.md).
Étape 3 — Balises requises (chaque page)
<meta property="og:title" content="Titre de la page" />
<meta property="og:description" content="Une phrase, ≤ ~160 caractères" />
<meta property="og:image" content="https://example.com/og/page.png" /> <!-- URL absolue -->
<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 les génère à partir de metadata + opengraph-image.tsx ; ne les écrivez pas manuellement en double.
Étape 4 — Vérifier (ne sautez pas)
Exécutez contre le site en cours d'exécution (serveur de développement, déploiement de prévisualisation ou production) :
python3 scripts/check_og.py http://localhost:3000/ http://localhost:3000/pricing
python3 scripts/check_og.py --json https://example.com/ # lisible par machine
Il récupère chaque page, vérifie les balises requises, que og:image est absolue, accessible,
un type de contenu image, ~1.91:1 et au moins 600 px de large, et moins de 5 Mo. Code de sortie 1 en cas d'erreur.
Corrigez tout ce qui est marqué ERROR ; les éléments WARN sont des recommandations.
Remarque : les plateformes sociales mettent en cache les aperçus. Après correction, utilisez le débogueur
de la plateforme (LinkedIn Post Inspector, Facebook Sharing Debugger) pour re-extraire. X n'a plus de validateur public ;
publiez dans un brouillon/DM pour vérifier. Les URL localhost ne peuvent pas être extraites par ces outils — déployez d'abord.
Règles de conception pour l'image
- 1200×630, PNG, texte dans une marge de sécurité d'environ 60 px ; titre ≤ ~60 caractères, max 3 lignes.
- Contraste élevé ; elle est affichée en petit (~500 px de large) dans les flux. Testez à 50 % de zoom.
- Incluez le nom/logo de la marque ; évitez le petit texte (< 28 px à 1200 de large).
- Voir
references/platform-specs.mdpour les notes par plateforme.
Terminé quand
- Chaque page indexable retourne og:title, og:description, og:image (absolue), twitter:card
-
check_og.pyse termine avec le code 0 pour la page d'accueil et au moins une page de chaque type de route - Les images sont correctes (ouvrez un PNG et regardez-le)