
OG-Image Best Practices für SPAs: So werden deine Vibe-Coding-Projekte teilbar
TL;DR: „SPAs liefern keine OG-Meta-Tags – Social Previews sind leer. Die Lösung: Pre-Rendering für statische Tags + dynamische OG-Image-Generierung via Edge Functions für individuelle Seiten."
— Till FreitagDas Problem: Dein Link sieht aus wie Spam
Du hast mit Lovable oder Bolt eine App gebaut. Sie funktioniert. Sie sieht gut aus. Aber wenn du den Link auf LinkedIn teilst, passiert das hier:
- Kein Bild – nur ein generisches Platzhalter-Icon
- Kein Titel – oder schlimmer: "React App"
- Keine Beschreibung – LinkedIn zeigt nichts
Das Problem ist nicht dein Content. Das Problem ist die Architektur.
Warum SPAs keine Social Previews haben
Single Page Applications rendern alles im Browser. Wenn LinkedIn, Twitter oder WhatsApp deinen Link crawlen, führen sie kein JavaScript aus. Sie bekommen nur die leere index.html:
<!DOCTYPE html>
<html>
<head>
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script src="/assets/index.js"></script>
</body>
</html>Keine og:title. Kein og:image. Kein og:description. Keine Preview.
Was Open Graph Tags sind – und warum sie wichtig sind
Open Graph (OG) Tags sind Meta-Tags im <head> deiner HTML-Seite, die Social-Media-Plattformen lesen:
<meta property="og:title" content="Dein Seitentitel" />
<meta property="og:description" content="Beschreibung für die Preview" />
<meta property="og:image" content="https://example.com/og-image.jpg" />
<meta property="og:url" content="https://example.com/seite" />
<meta property="og:type" content="website" />Das Problem bei SPAs: Diese Tags werden erst zur Laufzeit via JavaScript gesetzt (z.B. mit react-helmet-async). Aber Crawler warten nicht auf JavaScript.
Die Lösung: 3-Schichten-Strategie
Schicht 1: Pre-Rendering für statische OG-Tags
Playwright SSG rendert jede Seite vorab und baked die Meta-Tags ins HTML:
// playwright-ssg.ts
const pages = ['/blog/mein-artikel', '/services/beratung'];
for (const path of pages) {
const page = await browser.newPage();
await page.goto(`http://localhost:5173${path}`);
await page.waitForSelector('meta[property="og:title"]');
const html = await page.content();
// Speichere als statische HTML-Datei
}Ergebnis: Crawler bekommen vollständig gerenderte Seiten mit allen OG-Tags.
→ Playwright SSG Tutorial: Schritt für Schritt
Schicht 2: Dynamische OG-Images mit Edge Functions
Für Blog-Artikel oder Produktseiten willst du individuelle Preview-Bilder. Vercel Edge Functions generieren diese on-the-fly:
// api/og-image.tsx (Vercel Edge Function)
import { ImageResponse } from '@vercel/og';
export const config = { runtime: 'edge' };
export default function handler(req: Request) {
const { searchParams } = new URL(req.url);
const title = searchParams.get('title') || 'Default Title';
return new ImageResponse(
<div style={{
display: 'flex',
fontSize: 48,
background: 'linear-gradient(135deg, #1a2744, #0d1b2a)',
color: 'white',
width: '100%',
height: '100%',
padding: 60,
alignItems: 'center',
}}>
{title}
</div>,
{ width: 1200, height: 630 }
);
}Im HTML:
<meta property="og:image" content="https://example.com/api/og-image?title=Mein+Artikel" />Schicht 3: Fallback-Image als Sicherheitsnetz
Definiere immer ein Default-OG-Image in deiner index.html:
<meta property="og:image" content="https://example.com/og-default.jpg" />Falls Pre-Rendering oder Edge Function fehlschlagen, zeigt LinkedIn wenigstens dein Brand-Image statt eines leeren Kästchens.
Die OG-Image Checkliste
Format & Größe
- 1200×630px – das universelle OG-Image-Format
- < 1 MB Dateigröße (LinkedIn schneidet größere Bilder ab)
- WebP oder JPG – PNG nur wenn Transparenz nötig
- Kein wichtiger Content in den äußeren 10% – Plattformen croppen unterschiedlich
Meta-Tags
og:imagemit absoluter URL (nicht relativ!)og:image:widthundog:image:heightsetzenog:image:altfür Accessibilitytwitter:cardaufsummary_large_imagesetzen
Technisch
- HTTPS obligatorisch – HTTP-Images werden blockiert
- Cache-Header setzen (
Cache-Control: public, max-age=31536000) - Keine Redirects – OG-Image-URL muss direkt zum Bild führen
- CDN nutzen – schnelle Ladezeiten für Crawler
Häufige Fehler bei Vibe-Coding-Projekten
1. react-helmet-async allein reicht nicht
react-helmet-async setzt die Tags client-seitig. Crawler sehen sie trotzdem nicht. Du brauchst immer Pre-Rendering.
2. Relative Bild-URLs
<!-- ❌ Falsch -->
<meta property="og:image" content="/images/preview.jpg" />
<!-- ✅ Richtig -->
<meta property="og:image" content="https://example.com/images/preview.jpg" />3. Kein Twitter-Card Fallback
Twitter/X liest og:image, aber bevorzugt twitter:image. Setze beide:
<meta property="og:image" content="https://example.com/og.jpg" />
<meta name="twitter:image" content="https://example.com/og.jpg" />
<meta name="twitter:card" content="summary_large_image" />4. OG-Image wird gecacht
LinkedIn und Facebook cachen OG-Images aggressiv. Nach Änderungen musst du den Cache manuell invalidieren:
- LinkedIn: Post Inspector
- Facebook: Sharing Debugger
- Twitter: Card Validator
Unsere Implementierung: till-freitag.com
Auf unserer eigenen Website nutzen wir exakt diese Strategie:
- react-helmet-async setzt OG-Tags pro Seite im React-Code
- Playwright SSG rendert alle Seiten vorab – OG-Tags sind im statischen HTML
- Statische OG-Images in WebP für Blog-Artikel aus dem Asset-Registry
- Absolute URLs über eine zentrale
BASE_URLKonfiguration
Ergebnis: Jeder geteilte Link zeigt ein perfektes Preview-Bild auf LinkedIn, Twitter und WhatsApp.
Quick-Win: OG-Image in 5 Minuten
Wenn du sofort starten willst, hier der minimale Ansatz:
- Erstelle ein 1200×630px Bild mit deinem Brand
- Lege es in
/public/og-image.jpg - Füge in
index.htmlein:
<meta property="og:image" content="https://deine-domain.com/og-image.jpg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="https://deine-domain.com/og-image.jpg" />Das ist kein Ersatz für dynamische OG-Images – aber deutlich besser als nichts.
Nächste Schritte
OG-Images sind nur ein Teil des SEO-Puzzles für Vibe-Coding-Projekte. Der vollständige Stack umfasst Pre-Rendering, Schema-Markup und Edge Delivery.
→ Vibe Coding SEO Guide: Der komplette Überblick → JSON-LD Schema für SPAs automatisieren → Lovable → GitHub → Vercel: Der Production-Workflow








