From a8867ac42e597c78619c0a513913ad3602f6d2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=B6rdle=20Bot?= Date: Mon, 1 Dec 2025 19:44:48 +0100 Subject: [PATCH] feat: Add dynamic Open Graph image generation with correct aspect ratio - Create /api/og-image endpoint that generates SVG with 1.91:1 ratio (1200x630px) - Prevents logo cropping on Facebook and Twitter - Uses safe padding (150px) to ensure content is never cut off - Update default OG image to use dynamic endpoint - Add SEO testing documentation --- app/api/og-image/route.ts | 78 +++++++++++++ docs/SEO_TESTING.md | 235 ++++++++++++++++++++++++++++++++++++++ lib/config.ts | 2 +- 3 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 app/api/og-image/route.ts create mode 100644 docs/SEO_TESTING.md diff --git a/app/api/og-image/route.ts b/app/api/og-image/route.ts new file mode 100644 index 0000000..8a15f33 --- /dev/null +++ b/app/api/og-image/route.ts @@ -0,0 +1,78 @@ +import { NextResponse } from 'next/server'; +import { config } from '@/lib/config'; +import { getBaseUrl } from '@/lib/seo'; +import { headers } from 'next/headers'; + +export const dynamic = 'force-dynamic'; +export const runtime = 'nodejs'; + +/** + * Generate Open Graph image as SVG with correct aspect ratio (1.91:1 = 1200x630) + * This prevents cropping on Facebook and Twitter + */ +export async function GET() { + const baseUrl = await getBaseUrl(); + const appName = config.appName; + const bgColor = config.colors.backgroundColor || '#ffffff'; + const primaryColor = config.colors.themeColor || '#000000'; + + // SVG with correct Open Graph dimensions: 1200x630 (1.91:1 ratio) + // Safe area: 150px padding on all sides to prevent cropping + // This ensures content is never cut off on Facebook/Twitter + const svg = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${appName} + + + + + ${config.domain} + + +`; + + return new NextResponse(svg, { + headers: { + 'Content-Type': 'image/svg+xml', + 'Cache-Control': 'public, max-age=3600, s-maxage=3600', + }, + }); +} + diff --git a/docs/SEO_TESTING.md b/docs/SEO_TESTING.md new file mode 100644 index 0000000..9704693 --- /dev/null +++ b/docs/SEO_TESTING.md @@ -0,0 +1,235 @@ +# SEO & Open Graph Testing Guide + +## Übersicht + +Diese Anleitung zeigt dir, wie du die SEO-Implementierung (Meta-Tags, Open Graph, Twitter Cards) testen kannst. + +## Lokales Testen + +### 1. Browser-Entwicklertools + +1. **App starten:** + ```bash + npm run dev + ``` + Die App läuft unter `http://localhost:3000` + +2. **Meta-Tags im HTML prüfen:** + - Öffne eine Seite (z.B. `http://localhost:3000/en` oder `http://localhost:3000/de/about`) + - Rechtsklick → "Seite untersuchen" (F12) + - Tab "Elements" → `` Bereich erweitern + - Suche nach Meta-Tags: + - `` + - `` + - `` + - `` + +3. **View Page Source:** + - Rechtsklick → "Seitenquelltext anzeigen" + - Suche nach "og:" oder "twitter:" um alle Open Graph und Twitter Meta-Tags zu sehen + +### 2. cURL-Test (für schnelle Prüfung) + +```bash +# Prüfe Meta-Tags einer Seite +curl -s http://localhost:3000/en | grep -i "og:\|twitter:" +``` + +### 3. Node.js-Script zum Testen + +Erstelle eine Test-Datei `test-og.js`: + +```javascript +const https = require('https'); +const http = require('http'); + +function fetchHTML(url) { + return new Promise((resolve, reject) => { + const client = url.startsWith('https') ? https : http; + client.get(url, (res) => { + let data = ''; + res.on('data', (chunk) => data += chunk); + res.on('end', () => resolve(data)); + }).on('error', reject); + }); +} + +async function testOGTags(url) { + try { + const html = await fetchHTML(url); + const ogTags = { + title: html.match(/` - Canonical URL +- `` - Deutsche Version +- `` - Englische Version +- `` - Standard-Version + +## Troubleshooting + +### Problem: Meta-Tags werden nicht angezeigt + +**Lösung:** +1. Prüfe, ob die App läuft: `npm run dev` +2. Prüfe Browser-Console auf Fehler +3. Stelle sicher, dass `generateMetadata` in der Seite exportiert ist +4. Prüfe, ob `lib/metadata.ts` korrekt importiert wird + +### Problem: Open Graph Image wird nicht angezeigt + +**Lösung:** +1. Prüfe, ob das Bild unter `/favicon.ico` existiert (oder konfiguriertes OG-Image) +2. Für bessere Ergebnisse: Erstelle ein dediziertes Open Graph Bild (1200x630px) +3. Platziere es in `public/og-image.png` +4. Setze in `.env`: `NEXT_PUBLIC_OG_IMAGE=/og-image.png` + +### Problem: Facebook zeigt alte Vorschau + +**Lösung:** +1. Öffne Facebook Sharing Debugger +2. Gib deine URL ein +3. Klicke auf "Scraping erneut ausführen" (mehrfach, falls nötig) +4. Facebook cached die Vorschau - Cache kann mehrere Stunden dauern + +### Problem: Domain-Erkennung funktioniert nicht + +**Lösung:** +1. Prüfe `lib/seo.ts` - `getBaseUrl()` Funktion +2. Stelle sicher, dass Request-Headers korrekt sind +3. In Produktion: Prüfe, ob Proxy-Headers (`x-forwarded-host`) korrekt gesetzt sind + +## Open Graph Bild optimieren + +Für bessere Social Media Vorschauen solltest du ein dediziertes OG-Bild erstellen: + +**Empfohlene Größe:** 1200x630px +**Format:** PNG oder JPG +**Pfad:** `public/og-image.png` + +**Konfiguration:** +```bash +# In .env +NEXT_PUBLIC_OG_IMAGE=/og-image.png +``` + +Dann wird dieses Bild in allen Open Graph Meta-Tags verwendet. + +## Nützliche Links + +- [Open Graph Protocol Dokumentation](https://ogp.me/) +- [Twitter Cards Dokumentation](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards) +- [Facebook Sharing Best Practices](https://developers.facebook.com/docs/sharing/webmasters) + diff --git a/lib/config.ts b/lib/config.ts index bf9f204..60bee98 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -14,7 +14,7 @@ export const config = { linkUrl: process.env.NEXT_PUBLIC_CREDITS_LINK_URL || 'https://digitalcourage.social/@elpatron', }, seo: { - ogImage: process.env.NEXT_PUBLIC_OG_IMAGE || '/favicon.ico', + ogImage: process.env.NEXT_PUBLIC_OG_IMAGE || '/api/og-image', twitterHandle: process.env.NEXT_PUBLIC_TWITTER_HANDLE || undefined, } };