Grade de posts incorporável (widget)
Uma tag <script> que renderiza uma grade dos seus posts publicados dentro de uma
página que você não controla — o site de um parceiro, uma landing page, um app shell.
Ela lê a API pública de leitura e monta o DOM por conta
própria. Sem iframe.
O bundle tem 4,4 KB com gzip e não carrega mais nada.
O snippet
Seção intitulada “O snippet”-
Crie uma chave pública de leitura.
No admin, abra Configurações → Integrações API → Criar chave, escolha Pública de leitura (
pk_) e registre as origens onde o widget pode rodar (por exemplohttps://parceiro.comehttps://www.parceiro.com). O tokenpk_…é exibido uma única vez. -
Cole o snippet.
<div data-canverly-grid data-key="pk_YOURKEY" data-limit="6"></div><script src="https://docs.canverly.com/widget/v1/grid.js"integrity="sha384-pHV9vZdn2P2/wjNayBRVklmrBLFKkPT5Hz6ZAHiodvsxUo4C9Vr5pbxdIbje3MEF"crossorigin="anonymous" defer></script>Mantenha os atributos
integrityecrossorigin. São eles que fazem o navegador recusar o arquivo se um único byte dele algum dia divergir do que você auditou. -
Confira a origem.
Se a grade não aparecer, abra o console.
[canverly-grid] origem não está na allowlist da chavesignifica que a origem da página não está registrada na chave — adicione-a no admin. Nesse caso a API responde 403: a chave é válida, a página de onde ela é usada é que não é.
Atributos
Seção intitulada “Atributos”| Atributo | Padrão | Significado |
|---|---|---|
data-key |
— | Obrigatório. A chave pk_…. data-site é aceito como alias. |
data-limit |
6 |
1–50. Valores fora do intervalo são ajustados localmente, com um aviso no console. |
data-category |
— | Slug de categoria. |
data-tag |
— | Slug de tag. |
data-language |
— | Tag BCP-47, ex.: pt-BR. |
data-locale |
<html lang> ou pt-BR |
Locale para datas e rótulos. |
data-link-target |
_self |
Use _blank para abrir os posts em uma nova aba (os links sempre levam rel="noopener noreferrer"). |
data-empty-text |
localizado | Mensagem exibida quando o site não tem posts correspondentes. |
data-api |
https://api.canverly.com |
Base da API. Só https: (ou localhost) é aceito. |
Várias grades podem conviver na mesma página; cada elemento [data-canverly-grid]
é renderizado de forma independente. O estado atual é exposto como data-state:
loading, ready, empty ou error.
Content Security Policy
Seção intitulada “Content Security Policy”Se a página hospedeira envia uma CSP, ela precisa de três origens:
script-src https://docs.canverly.comconnect-src https://api.canverly.comimg-src https://canverly.b-cdn.netOs estilos não exigem mudança na CSP: o widget traz o CSS dentro do bundle e o
aplica por meio de uma constructable stylesheet, que style-src 'self' não
bloqueia. Só o fallback legado carrega grid.css como <link>, e esse precisa de
style-src https://docs.canverly.com. Toda classe tem o prefixo cvw-, então
nada vaza para os estilos da página hospedeira.
Segurança do que ele renderiza
Seção intitulada “Segurança do que ele renderiza”O widget nunca atribui HTML. Todo valor que vem da API entra por
createElement + textContent, e toda URL tem o esquema verificado antes de
chegar ao DOM. Um post com o título <script>alert(1)</script> é renderizado como
esse texto literal, de forma visível — ele não executa e não some silenciosamente.
Isso é garantido por testes que verificam o DOM resultante (nenhum nó <script>,
nenhum <img> extra, o nó do título tem zero elementos filhos), além de um teste de
mutação que falha se alguém trocar textContent por innerHTML.
Limites
Seção intitulada “Limites”- 600 requisições/minuto por chave, mais 60 requisições/minuto por (chave, IP) para chaves públicas. A dimensão por IP existe para que um único visitante hostil não consiga esgotar a cota de todas as páginas que incorporam a sua grade.
- Uma visualização de página = uma requisição. O widget renderiza uma única página de
resultados e ignora
next_cursorde propósito. - Em qualquer falha, o widget não renderiza nada visível e registra no console. Ele nunca lança erro para a página hospedeira.
Versionamento
Seção intitulada “Versionamento”A versão está no caminho, e os bytes em um caminho publicado nunca mudam.
/widget/v1/grid.js será sempre o arquivo cujo hash está acima; um build novo é
publicado em um caminho novo. É isso que permite ao snippet fixar o integrity e
o que nos permite servir o arquivo com cache imutável de um ano. Se algum dia
lançarmos uma mudança incompatível, ela vira /widget/v2/grid.js e esta página ganha
um snippet novo — o que você colou continua funcionando.
Os hashes atuais são publicados ao lado do arquivo em
/widget/v1/INTEGRITY.txt.