Embeds e white-label
Qualquer jornal, ONG ou microsite governamental pode exibir um dado real e citado do Futuros — o valor mais um chip de fonte com deep link para a fonte primária — com um único <iframe>. O contrato de honestidade viaja com o embed: um embed nunca mostra um número sem sua procedência.
Três rotas de widget mais um builder:
| Rota | Renderiza |
|---|---|
/embed/stat | Uma estatística citada — valor grande + unidade, chip de delta com sinal, chip de fonte, marca |
/embed/chart | O mesmo indicador como um pequeno gráfico de linha (último ponto rotulado) |
/embed/board | Uma grade responsiva com vários quadros stat/chart — um dashboard inteiro em um iframe |
/incrustar | A UI do builder em ES — escolha as opções, veja a prévia ao vivo, copie o snippet |
Todas as rotas de embed são embutíveis cross-origin: o vercel.json define Content-Security-Policy: frame-ancestors * em /embed/(.*) (o resto do site usa X-Frame-Options: SAMEORIGIN). O chrome do app (navegação, onboarding) é desativado sob /embed, então o widget pinta apenas a si mesmo.
/embed/stat e /embed/chart
Parâmetros de query compartilhados:
| Parâmetro | Valores | Padrão | Notas |
|---|---|---|---|
param | slug do pilar (salud, educacion, …) | salud | qual pilar |
iso | ISO3 (MEX, BRA, …) ou LATAM | MEX | convertido para maiúsculas automaticamente; LATAM renderiza o agregado regional ("América Latina y el Caribe") |
indicator | id do indicador | primeiro indicador da célula | escolha uma métrica específica |
theme | light | dark | dark | |
lang | es | en | pt | es | strings trilíngues completas + rótulos/unidades de métricas localizados |
accent | cor hex #RGB–#RRGGBBAA | azul Oxford (#11457e claro / #6496d5 escuro) | acento white-label (deve casar com /^#[0-9a-fA-F]{3,8}$/); sobrescreve tanto o acento quanto a cor de delta positivo |
O valor, o delta (vs. a média de 3 anos), a unidade e o chip de fonte vêm do mesmo payload estático de célula que o app usa; o chip de fonte aponta para a fonte primária do indicador e a marca aponta de volta para a célula viva do atlas.
Quatro mecânicas por trás desse parágrafo (todas em src/routes/_embed-shared.tsx):
- Gate somente-estático.
fetchParameter()carrega a célula gerada no build/data/parameter-cache/<param>__<ISO>.jsone reportasource: "static" | "mock"maisstatus: ready | not_generated | quarantined. Em um cache miss, o app principal pinta um mock determinístico para manter o layout vivo; o embed trata qualquer coisa que não sejasource:"static"— ou que sejanot_generated— como sem dados, porque um valor mock dentro de um iframe de terceiro seria um número fabricado vestindo um chip de fonte real. - Ordem de resolução do chip de fonte. Três passos, o primeiro acerto vence: campos inline no indicador (
source,source_url,vintage_year) → a linhacitations[]do próprio payload casada porcitation_id→ o registro de fontes (inferSourceKey(citation_id)→ metadados da instituição → template de URLdeepLinkFor()). O passo do registro é a mesma maquinaria desyntheticCitation(): o chip pode ser reconstruído apenas a partir do id, e somente um id que não mapeia para nenhuma instituição conhecida não produz nada. - Rótulos. Os payloads gerados no build carregam apenas rótulos/unidades canônicos em ES;
?lang=en|ptos sobrepõe a partir do registro de métricas gerado no build, carregado de forma assíncrona e cacheado em nível de módulo. O texto ES pinta imediatamente e permanece se esse fetch nunca resolver, e o embed honra?lang=exatamente — ao contrário do app principal, nunca recai na preferência de idioma armazenada do visitante. - A cor do delta é sensível à direção. O chip colore pelo
good_directiondo indicador (up/down/neutral): um valor em queda de uma métrica onde cair é bom renderiza como bom;neutralrenderiza cinza.
/embed/chart exige adicionalmente uma series não vazia no indicador — um valor citado sem histórico renderiza o estado sem-dados, nunca um gráfico vazio. O último ponto é marcado com um ponto de referência e repetido como valor de destaque.
Embed mínimo de estatística:
<iframe
src="https://futuros.xyz/embed/stat?param=salud&iso=MEX&theme=light&lang=pt"
width="320" height="180" style="border:0" loading="lazy"
title="Futuros — Saúde, México"></iframe>Embed de gráfico white-label (acento customizado, português, indicador específico):
<iframe
src="https://futuros.xyz/embed/chart?param=educacion&iso=BRA&indicator=se_xpd_totl_gd_zs&theme=dark&lang=pt&accent=%23004b87"
width="360" height="240" style="border:0" loading="lazy"
title="Futuros — Gasto em educação, Brasil"></iframe>Note o # codificado na URL (%23). Os tamanhos sugeridos seguem o builder /incrustar: stat 320×180, chart 360×240.
/embed/board — dashboard multi-quadro
Um único iframe renderiza uma grade responsiva e tematizada de quadros stat/chart. Um parceiro (BID / CAF / CELAC) insere um único iframe e recebe um dashboard inteiro, white-label, sem mudança de código.
Parâmetros:
| Parâmetro | Valores | Padrão | Notas |
|---|---|---|---|
panels | kind:param:iso[:indicator] separados por vírgula | — | kind = stat | chart; até 12 quadros |
theme | light | dark | dark | tematiza o shell e cada quadro |
accent | cor hex | — | repassado a cada quadro |
brand | texto livre | Futuros | substitui a marca; com um brand customizado a atribuição no rodapé lê "powered by Futuros ↗", caso contrário lê "futuros.xyz ↗" |
lang | es | en | pt | es | encaminhado a cada quadro |
Cada spec de quadro é kind:param:iso[:indicator] — p. ex. stat:salud:MEX ou chart:educacion:BRA:se_xpd_totl_gd_zs. O board monta cada quadro como um iframe same-origin de /embed/stat ou /embed/chart, encaminhando theme, lang e accent.
O parsing degrada campo a campo, nunca o board inteiro: um kind desconhecido vira stat, um param vazio vira salud, um iso vazio vira MEX (sempre em maiúsculas), e qualquer coisa além de 12 quadros é truncada silenciosamente. Os quadros renderizam como iframes de altura fixa (stat 160 px, chart 220 px) em uma grade auto-fill com coluna mínima de 260 px, então o board reflui com a largura da página hospedeira.
Um dashboard de país white-label:
<iframe
src="https://futuros.xyz/embed/board?panels=stat:salud:MEX,chart:educacion:MEX,stat:seguridad:MEX,chart:trabajo-economia:MEX&theme=light&accent=%23004b87&brand=IDB&lang=pt"
width="100%" height="640" style="border:0" loading="lazy"
title="Dashboard Futuros — México"></iframe>Se panels estiver vazio, o board mostra uma dica (?panels=stat:salud:MEX,chart:educacion:BRA) em vez de um frame em branco.
/incrustar — o builder
https://futuros.xyz/incrustar?lang=pt é o builder sem código para os embeds de widget único. Escolha pilar, país, indicador, tipo (stat/chart) e tema; ele mostra uma prévia ao vivo em iframe do valor citado real e entrega um snippet de uma linha para copiar e colar. O dropdown de indicadores é populado com os indicadores reais da célula selecionada, então você só embute uma métrica que existe.
Tematização — semântica de override de themeTokens
Cada widget aplica inline um conjunto completo de variáveis CSS na própria raiz (themeTokens() em _embed-shared.tsx) — não há classe de tema global, então os estilos da página hospedeira não vazam para dentro e o widget não vaza para fora:
| Token | Papel | ?accent= sobrescreve? |
|---|---|---|
--e-bg / --e-panel / --e-line | Fundo, cartão, borda | Não |
--e-ink / --e-ink-2 / --e-ink-3 | Hierarquia de texto | Não |
--e-accent | Marca, traço da linha do gráfico | Sim |
--e-good | Delta na direção boa | Sim — o mesmo hex do acento |
--e-bad | Delta na direção ruim, ressalva de quarentena | Não — permanece vermelho |
--e-cite | Chip de citação | Não |
O override é deliberadamente parcial: accent substitui exatamente --e-accent e --e-good, nunca --e-bad ou --e-cite. Um parceiro pode aplicar sua marca ao widget e aos deltas positivos; a cor de aviso e o chip de citação não são personalizáveis — você pode fazer white-label do número, não da ressalva.
Garantias de honestidade
O contrato de procedência tem dentes dentro do próprio widget:
- Nenhum número fabricado. Um embed se recusa a renderizar payloads mock/de fallback — se a fonte de dados da célula não for o corpus estático, ele mostra "Dados não disponíveis" em vez de um valor inventado.
- A quarentena é visível. Uma célula sinalizada pelos validadores renderiza com uma ressalva explícita de "em revisão" em vez de apresentar silenciosamente um número posto em dúvida.
- A citação viaja junto. O chip de fonte é reconstruído apenas a partir do
citation_id(veja Procedência), então o deep link funciona mesmo que o embed nunca carregue o registro completo de citações.
Framing e segurança
- As rotas de embed enviam
Content-Security-Policy: frame-ancestors *— embutíveis em qualquer página hospedeira. - Todas as outras rotas enviam
X-Frame-Options: SAMEORIGIN— o app principal não é embutível fora da origem. - Embeds são GETs puros de dados estáticos; não há auth e nada a submeter.
- Os widgets são autocontidos: o tema é aplicado via overrides inline de variáveis CSS na raiz do embed (não uma classe global), então o mesmo número lê corretamente dentro de qualquer página hospedeira.
Os valores por trás de cada embed são as mesmas observações citadas expostas pela API Pública v1 — o embed é apenas uma vista renderizada e linkável de uma célula.