TL;DR
Gdy ktoś wkleja URL do Telegram, WhatsApp, Facebook, LinkedIn czy X, komunikator buduje kartę z Open Graph (og:*) i, dla X, Twitter Cards. Bez poprawnych meta tagów dostajesz losowy favicon, obcięty tytuł albo brak obrazka. Standard karty: 1200×630 (ratio ~1.91:1), absolutny URL HTTPS, og:title, og:description, og:image, og:url, og:type. W Next.js App Router ustawiasz to w generateMetadata / metadata. Deploy na DevStudioIT Cloud; dynamiczne OG z bazy case studies przez Branchly. Poniżej: checklista tagów, kod Next.js, pułapki cache crawlerów i testy.
Dla kogo to jest
- Firm z blogiem i landingami udostępnianymi w social / chat
- Developerów Next.js (App Router) bez WordPress SEO plugins
- Marketerów, którzy widzą „brzydki podgląd” mimo ładnej strony
- Zespołów wielojęzycznych (pl/en/de), osobny title/description per locale
Fraza (SEO)
open graph nextjs, twitter cards podgląd linku, og:image 1200x630, meta tagi facebook whatsapp telegram, social share card 2026, generateMetadata open graph
Co czyta crawler (i czego nie)
Komunikatory nie uruchamiają Twojego Javału w przeglądarce użytkownika, robią HTTP GET i parsują HTML (często tylko pierwsze bajty / SSR). Dlatego:
- Meta muszą być w pierwszym HTML (Server Components / SSG), nie doklejane tylko w
useEffect - Obrazek musi być publicznie dostępny (nie za auth, nie
localhost) - Duże JS-only SPA bez SSR = pusty lub zły podgląd
| Platforma | Główne tagi | Uwagi |
|---|---|---|
| Facebook / Messenger | og:* |
Debugger z wymuszeniem scrapu |
og:title, og:description, og:image |
agresywny cache | |
| Telegram | og:* |
czasem też twitter:* |
og:* |
Post Inspector | |
| X (Twitter) | twitter:card, twitter:image… |
summary_large_image |
Minimalny zestaw tagów
<meta property="og:type" content="website" />
<meta property="og:site_name" content="DevStudio.it" />
<meta property="og:locale" content="pl_PL" />
<meta property="og:url" content="https://devstudioit.com/pl/blog/slug" />
<meta property="og:title" content="Tytuł karty, max ~60–70 znaków" />
<meta property="og:description" content="1–2 zdania, ~110–160 znaków" />
<meta property="og:image" content="https://devstudioit.com/og-share.jpg" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Opis obrazka" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Tytuł karty" />
<meta name="twitter:description" content="Opis" />
<meta name="twitter:image" content="https://devstudioit.com/og-share.jpg" />Dla artykułów bloga: og:type = article + opcjonalnie article:published_time, article:author.
Specyfikacja obrazka 1200×630
| Parametr | Rekomendacja |
|---|---|
| Rozmiar | 1200×630 px (bezpieczny standard) |
| Ratio | ~1.91:1 |
| Format | JPG lub PNG; WebP bywa problematyczny u niektórych crawlerów |
| Waga | zwykle < 1 MB (lepiej < 300 KB) |
| Safe zone | tekst/logo w środkowych ~80%, brzegi mogą przyciąć |
| URL | absolutny https://... |
Domyślny fallback w projekcie: /og-share.jpg. Per-post możesz nadpisać frontmatterem ogImage.
Nie używaj screenshotu całej strony w 4K, crawler i tak skaluje; zyskujesz tylko wolniejszy scrape.
Next.js App Router, generateMetadata
import type { Metadata } from 'next';
const BASE = 'https://devstudioit.com';
export async function generateMetadata({
params,
}: {
params: Promise<{ locale: string; slug: string }>;
}): Promise<Metadata> {
const { locale, slug } = await params;
const post = await getPost(locale, slug); // markdown lub Branchly
const image = post.ogImage?.startsWith('http')
? post.ogImage
: `${BASE}${post.ogImage ?? '/og-share.jpg'}`;
const url = `${BASE}/${locale}/blog/${slug}`;
return {
title: post.title,
description: post.description,
alternates: { canonical: url },
openGraph: {
type: 'article',
locale: locale === 'pl' ? 'pl_PL' : locale === 'de' ? 'de_DE' : 'en_US',
url,
siteName: 'DevStudio.it',
title: post.title,
description: post.description,
images: [{ url: image, width: 1200, height: 630, alt: post.title }],
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.description,
images: [image],
},
};
}Layout root może ustawić domyślne OG; strony nadpisują. Unikaj dwóch sprzecznych og:image w <head>.
Cache crawlerów, najczęstsza „bug report”
Zmieniłeś obrazek, a WhatsApp dalej pokazuje stary? To cache platformy, nie Twój CDN.
| Platforma | Narzędzie / trick |
|---|---|
| Sharing Debugger → Scrape Again | |
| Post Inspector → inspect | |
| X | Card Validator |
często: dopisz ?v=2 do URL na czas testu; poczekaj lub wyślij na inne urządzenie |
|
| Telegram | @webpagebot lub ponowne wklejenie po czasie |
Na DevStudioIT Cloud trzymaj OG image z długim cache (Cache-Control) dopiero gdy finalne, przy iteracji designu użyj wersjonowanego filename (og-share-2026-07.jpg).
Dynamiczne karty (opcjonalnie)
Dla case studies z CMS/DB (Branchly) możesz:
- Trzymać
ogImageUrlw rekordzie - Albo generować PNG przez
ImageResponse(edge/runtime) z tytułem na tle brandu
Generowane karty są spójne wizualnie, ale wymagają testu na każdej platformie, niektóre limity timeout scrape.
Checklista przed publikacją
- Absolutny
og:imageHTTPS, 200 OK - Wymiary zgodne (width/height meta = realne)
- Title ≤ ~70 znaków, description nie ucięte w połowie słowa
-
og:url= canonical locale - Osobne title/description pl/en/de
-
twitter:card=summary_large_imagejeśli chcesz duży obraz - Test FB Debugger + wklejenie do Telegram/WhatsApp na staging z publicznym URL
Typografia i branding na karcie 1200×630
Karta social to mini-billboard: w 0,5 s ma przekazać markę i temat. Dobre praktyki:
- Tło, kolor brandu lub zdjęcie z mocnym overlayem (tekst musi być czytelny na mobile)
- Logo, małe, w rogu safe zone; nie zajmuj 40% kadru logo
- Tytuł na grafice, skrócony vs
og:titleHTML (max ~6–8 słów); HTML title może być dłuższy - Bez drobnego UI, nie wklejaj screenshotu całego dashboardu; wybierz 1 motyw
- Spójność locale, osobna wersja PL/EN/DE jeśli tytuł jest „wypalony” w bitmapie
Dla bloga DevStudio często wystarczy szablon: gradient + slug tytułu + marka. Unikalna grafika per post podnosi CTR w LinkedIn/FB, ale nie blokuj publikacji czekając na design, fallback /og-share.jpg jest lepszy niż brak og:image.
FAQ
Czy wystarczy jeden og-share.jpg na całą witrynę?
Jako fallback, tak. Dla bloga i kluczowych landingów lepszy unikalny obraz (tytuł + branding), wyższy CTR w feedach.
Czy og:image może być relative /og-share.jpg?
Next.js Metadata API zwykle absolutyzuje, ale crawlerzy bywają kapryśni. Preferuj pełny URL https://....
Open Graph vs JSON-LD, to samo?
Nie. OG = podgląd społecznościowy. JSON-LD = zrozumienie przez Google (Organization, BlogPosting). Robisz oba.
Dlaczego LinkedIn pokazuje inny tytuł niż og:title?
Czasem bierze z własnego cache lub z <title>. Wymuś rescrape w Inspectorze; upewnij się, że SSR serwuje aktualny HTML.
Chcesz poprawne karty social na swojej stronie?
- Skontaktuj się z nami, skonfigurujemy metadata, OG 1200×630 i testy podglądu w Next.js
- Next.js SEO metadata App Router, title, description, hreflang
- JSON-LD Schema.org, structured data obok OG
O autorze
Budujemy szybkie strony WWW, aplikacje web/mobile, chatboty AI i hosting — z naciskiem na SEO i konwersję.
Przydatne linki
Od teorii do produkcji — Branchly, hosting i realizacje.
