Editorial OG Card
Uma imagem de pré-visualização de link consistente por post. Cada cartão tem:
- uma linha superior com um subtítulo (a série ou seção), o tópico e uma linha de metadados (tempo de leitura ou data),
- o título em uma serifa grande, definido como texto real para garantir a ortografia correta, reduzido apenas o necessário para caber, com uma ou duas palavras na cor de acento,
- uma linha de autoria com iniciais ou foto, e a URL do post,
- arte à direita: uma de quatro composições de blocos escolhidas a partir do slug do post (para que um post mantenha seu cartão), uma imagem que você escolher, ou nada, com o título ocupando mais espaço.
Um script lê seus posts e gera cards.json, você o revisa, e um segundo script renderiza cada cartão usando o Chrome já instalado na máquina. Nada para instalar.
O que você precisa
- Node.js 18 ou superior.
- Chrome, Chromium ou Edge. O script o encontra nos lugares comuns; defina
CHROME_PATHse não encontrar. - Acesso à internet durante a renderização, para a folha de estilo do Google Fonts (Instrument Serif, Inter, IBM Plex Mono). Consulte Solução de Problemas para renderizar offline.
A pasta deste skill é <skill> abaixo: a pasta onde este SKILL.md está.
Passos
1. Criar cards.json
A partir de posts Markdown (Astro, Hugo, Jekyll, Eleventy, Next.js MDX, qualquer coisa com front matter):
node <skill>/scripts/from-posts.mjs content/blog --site=yourblog.example --path=/blog/ --out-dir=public/og
Ele lê todos os arquivos .md, .mdx e .markdown sob a pasta e gera um cartão por post, do mais recente ao mais antigo. Posts com draft: true são ignorados. Do front matter, ele extrai:
| Campo do cartão | De |
|---|---|
slug | slug, senão permalink, senão o nome do arquivo (ou pasta para index.md), sem uma data inicial |
title | og_title, senão title |
kicker | kicker, senão series, senão --kicker=..., senão "Article" |
topic | topic, senão a primeira category, senão a primeira tag |
meta | reading_time, senão a contagem de palavras a 230 palavras por minuto: "8 min read" |
author | author (texto, ou name dentro dele), senão --author=... |
url | --site + --path + slug, exibido abaixo do autor |
out | <out-dir>/<slug>.png; sem --out-dir, ao lado do post como <name>.og.png (ou og.png ao lado de um index.md) |
Execute novamente quando novos posts forem adicionados: cartões já em cards.json mantêm suas edições, novos posts são adicionados e os removidos são descartados.
Manualmente, para páginas que não são Markdown (newsletter, landing pages, seções de documentação), escreva a mesma estrutura você mesmo:
{
"theme": { "paper": "#131313", "ink": "#f2ede4", "accent": "#ff7a45" },
"defaults": { "kicker": "Night Desk", "author": "Ines Varga" },
"cards": [
{
"slug": "issue-41",
"title": "Why every newsroom is quietly *rebuilding its CMS*",
"topic": "Issue 41",
"meta": "Oct 2026",
"url": "nightdesk.example/41",
"tags": ["#media", "№ 41"]
}
]
}
defaults preenche qualquer campo que um cartão deixar de fora.
2. Editar os cartões
Abra cards.json e revise os títulos:
- Coloque entre
*asteriscos*a(s) palavra(s) que carregam o ponto principal; elas serão exibidas em itálico na cor de acento."Implementando um design system *em uma semana*". - Títulos ficam melhores com menos de 70 caracteres; o limite é 110. Acima de cerca de 80, o tipo fica menor. Encurte usando
og_titleno front matter do post, ou diretamente emcards.json.
Todos os campos que um cartão pode ter:
| Campo | O que é | Limite |
|---|---|---|
title | O título (obrigatório) | 110 |
slug | Nomeia o arquivo e escolhe o layout (obrigatório, a menos que out esteja definido) | – |
out | Onde o PNG será salvo, relativo a cards.json (padrão og/<slug>.png) | – |
kicker | Rótulo superior esquerdo, na cor de acento | 24 |
topic | Após o subtítulo; também a hashtag padrão na arte | 28 |
meta | Superior direito: tempo de leitura, data, edição | 20 |
author | Nome do autor; as iniciais vão no círculo | 32 |
avatar | Uma foto para o círculo em vez das iniciais (caminho ou URL) | – |
url | Exibido abaixo do nome | 48 |
art | blocks (padrão), image ou none | – |
image | A imagem para "art": "image" (caminho ou URL); cortada para 390×430 | – |
layout | 1 a 4, para escolher você mesmo a composição de blocos | – |
tags | Até dois pequenos rótulos na arte, ex.: ["#css", "Part 2"] | 16 cada |
O tema define a aparência de cada cartão: paper (fundo), ink (texto) e accent, em hexadecimal, além de serif, sans e mono para outras famílias do Google Fonts. O acento é usado como está para os blocos; para o texto, o cartão escurece ou clareia até ficar legível. Dois temas para começar: o padrão azul tinta (#fafaf7, #17181c, #2433e8) e noturno (#131313, #f2ede4, #ff7a45).
3. Renderizar
node <skill>/scripts/render.mjs cards.json
Ele verifica cada cartão primeiro e lista todos os problemas de uma vez, depois renderiza os cartões quatro de cada vez (cerca de um segundo cada) e verifica se cada PNG tem 1200×630. Adicione --scale=2 para imagens de 2400×1260 (mais nítidas em telas de alta densidade, cerca do dobro do tamanho do arquivo), ou --only=slug,slug para refazer alguns cartões.
4. Visualizar
Abra og-preview.html, criado ao lado de cards.json: todos os cartões lado a lado. Verifique títulos que encolheram muito (encurte-os), palavras de acento que caíram na frase errada e se cartões vizinhos são diferentes o suficiente. Altere o layout em um cartão para escolher outra composição.
5. Integrar ao site
Os cartões só aparecem nas pré-visualizações quando cada página aponta para sua imagem com uma URL absoluta. No <head> da página:
<meta
property="og:image"
content="https://yourblog.example/og/design-system-in-a-week.png"
/>
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="Implementando um design system em uma semana" />
<meta name="twitter:card" content="summary_large_image" />
Faça isso uma vez no layout ou template do post, construído a partir do slug, não por post:
- Next.js (App Router): no
generateMetadatada rota do post, retorneopenGraph: { images: [{ url: `/og/${slug}.png`, width: 1200, height: 630 }] }etwitter: { card: 'summary_large_image' }, commetadataBasedefinido no layout raiz para que a URL se torne absoluta. - Astro, Eleventy, Jekyll, Hugo: adicione as tags ao cabeçalho do layout base, usando a URL do site mais
/og/mais o slug da página. - Imagens ao lado do post (sem
--out-dir): use o caminho que seu framework serve para arquivos co-localizados.
Após implantar, cole a URL de um post em um verificador de pré-visualização de links, ou em um rascunho no X, LinkedIn ou Slack, para ver o cartão. As plataformas armazenam pré-visualizações em cache; uma imagem alterada pode demorar para aparecer.
6. Manter funcionando (opcional)
Para gerar cartões para novos posts a cada build, copie as pastas scripts/ e template/ deste skill para o repositório (digamos tools/og/) e execute ambos os scripts antes do build, por exemplo como um script prebuild em package.json:
"prebuild": "node tools/og/scripts/from-posts.mjs content/blog --site=yourblog.example --path=/blog/ --out-dir=public/og && node tools/og/scripts/render.mjs cards.json"
A máquina de build precisa do Chrome; a maioria das imagens de CI já o tem, ou defina CHROME_PATH.
Solução de Problemas
render: fix cards.json first: cada linha nomeia o cartão, o campo e o limite.- Chrome não encontrado: instale Chrome ou Chromium, ou defina
CHROME_PATHpara o executável. - O título está em uma serifa simples ou os rótulos em uma fonte do sistema: a folha de estilo do Google Fonts não foi carregada. Para renderizar offline, instale Instrument Serif, Inter e IBM Plex Mono (todas gratuitas do Google Fonts) e defina
"fonts": ""no tema."fonts"também pode ser a URL da sua própria folha de estilo para outras famílias. - A pré-visualização em uma plataforma mostra a imagem antiga ou nenhuma: verifique se a URL
og:imageabre em um navegador e é absoluta (comhttps://e seu domínio), depois peça à plataforma para re-raspar a página ou aguarde o cache expirar.
Arquivos
scripts/from-posts.mjs: front matter paracards.json, mantendo suas edições em execuções posteriores. Sem dependências.scripts/render.mjs: verificacards.json, renderiza os PNGs e escreveog-preview.html. Sem dependências.scripts/chrome.mjs: encontra o Chrome e tira as capturas de tela.template/: o próprio cartão.card.htmlecard.csssão o layout,card.jspreenche o texto, escolhe cores legíveis, desenha a arte e ajusta o título.examples/field-notes/: um pequeno blog (posts/) e ocards.jsongerado a partir dele comfrom-posts.mjs, com palavras de acento adicionadas.examples/night-desk/: umcards.jsonescrito à mão para uma newsletter, escuro. As pré-visualizações no Lookbk são renderizadas a partir destes.NOTICE.md: as fontes e o software que este skill utiliza.