Páginas: o JSON do documento v2
Guia completo para criar, editar e publicar páginas por API (e por agentes de IA): modelo mental, todos os campos de todos os itens, validação e erros, mídia, fluxos seguros, receitas e prompt pronto.
Documento de página v2: guia completo para agentes
Este guia ensina uma pessoa ou um agente de IA a ler, criar, editar e publicar páginas e formulários do Asender Pages pela API pública, produzindo o JSON do documento v2 certo na primeira tentativa. As tabelas de campos, limites e tipos são geradas do JSON Schema do contrato (asender_docs/contratos/pages-documento-v2.schema.json), o mesmo que os validadores Go (autoridade, roda no servidor) e TypeScript (roda no editor) provam concordar; por isso elas não envelhecem. Tudo que aparece em JSON aqui foi validado nos três lados.
- Base da API:
https://api.pages.asender.net(JSON, UTF-8). - Referência de rotas: Pages API (operações geradas do código) e o guia Pages API: autenticação, erros, domínios. Este guia cobre o que elas não dizem: o conteúdo da página.
- Contexto inteiro para um agente:
llms-full.txtinclui este guia. - Schema:
pages-documento-v2.schema.json(JSON Schema 2020-12), também publicado comoDocumentoV2eDocV2_*na OpenAPI de Páginas.
Regra de ouro para agentes: o servidor é a autoridade. Valide localmente contra o schema, envie, e se vier422leiacodigoecaminho(seção 4), corrija só aquele nó e reenvie. Nunca invente campo: campo desconhecido é recusado.
1. Início rápido para agentes
1.1 Credenciais: o que cada uma alcança
Um agente externo trabalha com uma API key (sk_live_... / sk_test_...), criada pelo dono da conta em Desenvolvedores → Chaves de API com os escopos mínimos da tarefa. A conta é sempre a da chave (validada no servidor a cada chamada; chave revogada para na hora): nenhum header nem campo do corpo escolhe a conta, e um tenant_id no corpo é recusado. Página, rascunho, mídia ou domínio de outra conta responde 404, igual a um id que não existe.
| Escopo da chave | O que permite |
|---|---|
pages:read | ler: GET /v1/paginas, GET /v1/paginas/{id}, GET /v1/paginas/{id}/rascunho, GET /v1/paginas/{id}/seo, GET /v1/dominios, GET /v1/midias |
pages:write | criar e editar, sem publicar: POST /v1/paginas, POST /v1/paginas/{id}/versoes, PUT/DELETE /v1/paginas/{id}/rascunho, PUT /v1/paginas/{id}/seo, POST /v1/paginas/importar, POST /v1/paginas/{id}/midias/copiar, PUT /v1/paginas/{id}/dominio, POST /v1/paginas/lote com duplicar/mudar_dominio, POST /v1/midias, POST /v1/midias/de-url |
pages:publish | publicar e despublicar (o ato visível ao público e indexável): POST /v1/paginas/{id}/publicar e POST /v1/paginas/lote com publicar/despublicar |
forms:read / forms:write | formulários e o envio de leads (seção 3.8) |
Os escopos não se implicam: pages:write não lê (precisa de pages:read para listar) nem publica. Um agente que cria, confere e publica precisa dos três. Sem o escopo da rota, 403 ({"erro":"a chave não tem o escopo pages:publish"}); rota que não aceita chave, 401. A sessão OIDC de uma pessoa (Authorization: Bearer <token-de-sessão> + X-Asender-Tenant: <slug-da-conta>) continua alcançando tudo de autoria e é o que o painel usa; a chave não alcança editar slug/título (PATCH), testes A/B, roteamento, apagar mídia, SEO do site, redirects nem marca.
Regras que protegem o trabalho de pessoas (valem só para chave):
- Rascunho com
?base=obrigatório.PUT /v1/paginas/{id}/rascunhosem?base=responde428. Leia o rascunho (GET, devolverascunho_em) e devolva esse valor em?base=; sem rascunho anterior use?base=vazio. Se uma pessoa (ou outro agente) gravou no meio, o servidor responde409RascunhoConflitocom o rascunho dela e não grava nada: os dois lados ficam preservados; mescle e tente de novo com orascunho_emnovo. - Publicar exige a
versao. Com chave,POST .../publicarsem{"versao": N}responde422: o agente publica a versão que ele identificou (o retorno doPOST .../versoes, ouultima_versaoemGET /v1/paginas/{id}), nunca "a mais recente" às cegas, que pode ser uma edição de pessoa ainda não revisada.POST /v1/paginas/lotecompublicarpublica a última versão salva e pula a página com rascunho mais novo (políticapular, padrão). - Nada é sobrescrito. Cada
POST .../versoescria a versão seguinte; publicar move um ponteiro. Desfazer é publicar a versão anterior. - Autoria visível. Versões e rascunhos feitos por chave levam
apikey:<key_id>(colunacriado_por; o rascunho devolverascunho_por), distinguindo agente de pessoa; as ferramentas de importação por CLI (--nova-versao) recusam sobrescrever a última versão feita por pessoa. - Sem HTML cru. Conteúdo com bloco/item
htmlexige um usuário com nível elevado; chave de API recebe403nesse caso. - Ritmo por chave. Escritas: 60 por minuto por chave; publicar/despublicar: 20 por minuto; acima disso
429comRetry-After. Leituras não contam.POST /v1/paginas/loteainda tem o teto de 12 chamadas por minuto por conta. - Tudo fica no log. Cada chamada com chave aparece em Desenvolvedores → Logs (
servico: pages), com a rota, o status, a chave e o conteúdo redigido.
Os exemplos usam $KEY (a API key) e $API; o mesmo curl funciona com sessão trocando o header.
export API=https://api.pages.asender.net
export KEY='sk_live_...' # escopos: pages:read pages:write pages:publish
H=(-H "Authorization: Bearer $KEY" -H 'Content-Type: application/json')
# Com sessão de pessoa: -H "Authorization: Bearer $TOKEN" -H "X-Asender-Tenant: $CONTA"
1.2 O documento mínimo válido
{ "versao": 2, "secoes": [ { "id": "a", "colunas": [ { "id": "ac", "itens": [] } ] } ] }
Uma seção, uma coluna, zero itens. Com um título:
{
"versao": 2,
"secoes": [
{ "id": "s1", "colunas": [
{ "id": "s1c1", "itens": [
{ "id": "s1c1i1", "tipo": "titulo", "props": { "texto": "Olá, mundo", "nivel": 1 } }
] }
] }
]
}
Todo item tem id, tipo e props (objeto, pode ser {}).
1.3 Criar, editar e publicar (o caminho feliz)
# 1) criar a página (nasce DESPUBLICADA, com a versão 1 = o template enviado)
curl -sS -X POST "$API/v1/paginas" "${H[@]}" -d '{
"titulo": "Lançamento",
"slug": "lancamento",
"template": { "versao": 2, "secoes": [ { "id": "s1", "colunas": [ { "id": "s1c1", "itens": [
{ "id": "t1", "tipo": "titulo", "props": { "texto": "Olá, mundo", "nivel": 1 } } ] } ] } ] }
}'
# -> 201 { "id":"<pagina-id>", "slug":"lancamento", "dominio":"<conta>.apages.xyz", "titulo":"Lançamento",
# "versao_publicada":0, "ultima_versao":1, "url_publica":"https://<conta>.apages.xyz/lancamento" }
# 2) salvar uma NOVA versão (cada POST cria a versão seguinte; nada é sobrescrito)
curl -sS -X POST "$API/v1/paginas/<pagina-id>/versoes" "${H[@]}" -d @corpo-versao.json # {"template": {...}}
# -> 201 { "versao": 2 } | 422 { "erro":"...", "codigo":"ErrPropInvalida", "caminho":"secoes[0]..." }
# 3) publicar UMA versão, pelo número (chave: escopo pages:publish e `versao` obrigatória)
curl -sS -X POST "$API/v1/paginas/<pagina-id>/publicar" "${H[@]}" -d '{ "versao": 2 }'
# -> 200 { "versao_publicada": 2 }
# Rascunho (auto-save, sem versão): leia o rascunho_em e devolva em ?base= (obrigatório com chave)
curl -sS "$API/v1/paginas/<pagina-id>/rascunho" "${H[@]}" # -> 200 {template, rascunho_em} | 204
curl -sS -X PUT "$API/v1/paginas/<pagina-id>/rascunho?base=<rascunho_em>" "${H[@]}" -d '{"template": {...}}'
# -> 200 { "rascunho_em": "..." } | 409 RascunhoConflito (com o rascunho do servidor) | 428 sem ?base=
Sem template no POST /v1/paginas, a página nasce com um documento inicial (uma seção hero com o título digitado). Corpo máximo: 512 KiB.
1.4 O endereço da página e o domínio padrão
Toda conta tem um domínio padrão num subdomínio de apages.xyz (ex.: minhaconta.apages.xyz). Uma página criada sem dominio nasce nele; a url_publica da resposta é o endereço para abrir. Para usar outro domínio (um próprio, já verificado), crie/atualize a página com dominio ou, depois, mova com PUT /v1/paginas/{id}/dominio (API key pages:write):
curl -sS "$API/v1/dominios" "${H[@]}" # pages:read, o padrão vem primeiro
curl -sS -X PUT "$API/v1/paginas/<pagina-id>/dominio" "${H[@]}" -d '{ "dominio_id": "<id>", "caminho": "novo-slug" }'
Detalhes (301 do endereço antigo, erros 409/422) na seção 6.5.
1.5 Antes de gerar JSON
- Escolha a estrutura (seção 2) e os tipos de item (seção 3.1).
- Gere
ids únicos no documento inteiro (sugestão:s1,s1c1,s1c1i1...). - Use somente os campos das tabelas da seção 3; tudo que não está lá é recusado.
- Imagens: URL da galeria da conta ou
https://externa (seção 5). - Valide contra o schema, envie, leia o
422se vier (seção 4).
2. Modelo mental
documento (versao: 2)
|- configuracoes (livre, passthrough)
|- estilo (a PÁGINA: tema, fundo, textura, fontes, caixa do conteúdo)
'- secoes[] (faixas horizontais, de cima para baixo)
'- colunas[] (células lado a lado dentro da seção)
'- itens[] (objetos atômicos: titulo, texto, imagem, botao...)
'- abas / acordeao: painéis com itens aninhados (um único nível)
- Seção é uma faixa de página inteira: fundo, borda, padding, altura, âncora e comportamento (
normal,fixa_topo,popup). Tem de ter 1..12 colunas. - Coluna é a célula da grade. Seu
larguraé um peso (frdo CSS grid): colunas 1+2 ocupam 1/3 e 2/3; cinco colunas de peso 1 dão quintos. Define também o alinhamento do conteúdo e ogapentre os itens. - Item é o objeto. Mora sempre dentro de uma coluna e não contém outros itens, exceto os painéis de
abas/acordeao(um nível só, semabas,acordeao,htmlnemformulariodentro). - Estilo da página (
estilo) vem antes das seções: tema (claro/escuro/auto), fundo atrás de tudo (cor, degradê, imagem), textura sutil, fontes e a caixa do conteúdo (estilo.conteudo: o miolo contido de toda seção, a "coluna estreita" de uma página de links).
Responsividade. Os pontos de quebra são fixos: celular até 767 px, tablet 768 a 1023 px, computador a partir de 1024 px. No celular as colunas empilham (layout_celular: empilhar, o padrão) ou ficam lado a lado (manter); inverter_celular inverte a ordem da pilha. padding_celular e espacador.altura_celular ajustam o respiro no celular. ocultar_em (seção ou item) esconde por dispositivo. Não há CSS livre: tudo é campo fechado.
Ids. ^[A-Za-z0-9_-]{1,64}$, únicos no documento inteiro: seção, coluna, item e os itens dentro de painéis dividem o mesmo espaço (um item de painel com o id de uma seção é ErrID). Âncoras (secao.ancora): ^[a-z][a-z0-9-]{0,63}$, únicas na página; viram o id HTML da seção e o alvo de #ancora em botões e menus.
Ordem e tamanho. As seções são renderizadas na ordem do array. Tetos importantes: 200 seções, 12 colunas por seção, 100 itens por coluna, 1000 itens por página (contando os de painéis). Tabela completa na seção 3.
Versões do formato. Só o versao: 2 deve ser escrito. O formato v1 (lista plana de blocos) ainda é lido, mas está em saída; não gere v1.
Normalização. O servidor valida e regrava o documento na forma canônica; o que você lê de volta pode ter a ordem das chaves diferente do que enviou.
3. Referência de campos
Tudo nesta seção vem do schema. Convenções das tabelas: Tipo é o tipo JSON; "cor" e "url de mídia" são tipos nomeados (seção 3.4); Padrão é o que o renderer aplica quando a prop está ausente (só aparece quando verificado); "obrigatório" marca campos sem os quais o documento é recusado. Todas as props de item são opcionais, mas um item sem conteúdo (por exemplo um botao sem rotulo) não desenha nada útil.
3.1 Limites do documento
| Limite | Valor | O que limita |
|---|---|---|
MaxSecoes | 200 | seções por página |
MaxColunas | 12 | colunas por seção |
MaxPesoColuna | 12 | peso (largura) máximo de uma coluna |
MaxItensPorColuna | 100 | itens por coluna |
MaxItensTotal | 1000 | itens na página inteira (inclui os aninhados em abas/acordeão) |
MaxItensLista | 50 | entradas em links, tags, cartoes, redes, menu |
MaxEspaco | 400 | teto de padding/margem/gap/altura de espaçador (px) |
MaxRaio | 200 | teto de raio (px) |
MaxBorda | 20 | teto de espessura de borda (px) |
MinLarguraMax | 320 | menor largura_max de seção (px) |
MaxLarguraMax | 2400 | maior largura_max (px) |
MaxAlturaPx | 2000 | maior altura_minima em px |
MaxAlturaVh | 100 | maior altura_minima em vh |
MaxAtrasoPopup | 120 | maior atraso_popup (segundos) |
GapPadraoItens | 16 | gap padrão entre itens (px) |
GapPadraoColunas | 24 | gap padrão entre colunas (px) |
LarguraMaxPadrao | 1080 | largura do conteúdo contido sem largura_max (px) |
MaxTamanhoID | 64 | caracteres de um id |
MaxTamanhoNome | 80 | caracteres de secao.nome (conta code points, não bytes) |
MaxTamanhoURL | 2048 | caracteres de uma URL |
MaxTextoCurto | 300 | caracteres de títulos, rótulos, alt |
MaxTextoLongo | 20000 | caracteres do texto de um item texto |
MaxTamanhoHTML | 200000 | caracteres do item html |
MaxTamanhoPrazo | 64 | caracteres do prazo do contador |
MaxTextoTag | 60 | caracteres do texto de um chip / tag de cartão |
MaxPaineis | 20 | abas ou painéis por item |
MaxItensPorPainel | 20 | itens dentro de UM painel |
MaxTituloPainel | 200 | caracteres do título de aba/pergunta |
MaxIconeTag | 48 | maior tamanho_icone dos chips (px) |
MaxFAQResposta | 4000 | caracteres da resposta de uma pergunta de FAQ |
MaxFAQPagina | 50 | perguntas de FAQ somadas na página |
MaxSubir | 200 | maior estilo.subir (px) |
MaxPaddingImagem | 40 | maior padding da imagem (px) |
MinIconeFundo | 24 | menor contêiner de ícone (px) |
MaxIconeFundo | 72 | maior contêiner de ícone (px) |
MaxColunasCartoes | 4 | colunas da grade de cartões |
MinLarguraCartao | 96 | menor largura_cartao (px) |
MaxLarguraCartao | 400 | maior largura_cartao (px) |
MinMiniatura | 56 | menor miniatura (px) |
MaxMiniatura | 96 | maior miniatura (px) |
MaxInclinar | 12 | maior inclinar (graus) |
MaxRotacaoCartao | 15 | maior rotacao de um cartão (graus, para os dois lados) |
3.2 Os 20 tipos de item
| Tipo | Para que serve |
|---|---|
titulo | Título (h1..h6). Aceita marcação inline [rótulo](url) e [[trecho]]. |
texto | Parágrafo de texto. Aceita a mesma marcação inline do título e quebras de linha. |
imagem | Imagem, com forma, proporção, moldura e link opcional. |
botao | Botão (ou link-botão) com visual granular, vidro, ícones e imagem. |
tags | Chips (etiquetas) com ícone, link e visual por chip. |
links | Lista de botões de link (o miolo de um link-na-bio), com visual por entrada. |
cartoes | Galeria de cartões (foto, título, texto, tag, ícone, link) em grade, carrossel ou lista. |
abas | Abas; cada aba é um painel com itens aninhados (um nível só). |
acordeao | Acordeão (sanfona); com faq: true gera FAQPage no JSON-LD da página. |
redes | Ícones de redes sociais (Instagram, WhatsApp...) com link. |
menu | Menu de navegação (links de texto), horizontal ou vertical; pode colapsar no celular. |
formulario | Embute um formulário do Asender (campos reais, anti-spam e captura de lead). |
video | Vídeo incorporado (<iframe>) a partir de uma URL de embed. |
divisor | Linha divisória horizontal. |
espacador | Espaço vertical em branco. |
icone | Um ícone avulso (kit de ícones ou ícone clássico). |
selo | Selo (pílula de destaque com um texto curto). |
contador | Contagem regressiva até um prazo. |
marca | Logo e/ou nome da conta (vindos do kit de marca efetivo); útil em cabeçalhos. |
html | HTML cru. PRIVILEGIADO: só quem tem o nível elevado grava; sem ele a escrita é barrada (403). |
3.3 Documento, estilo da página, seção e coluna
Documento e estilo da página
Documento (raiz):
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
versao (obrigatório) | const | 2 | Sempre 2. Qualquer outro valor é ErrVersao. | |
configuracoes | qualquer JSON | Passthrough (objeto livre, ex.: encurtar links por padrão). Não é layout. | ||
estilo | estilo da página | Objeto de estilo (ver a tabela do contexto). | ||
secoes (obrigatório) | lista de secao | ≥1 · ≤200 | Lista de seções (1..200), de cima para baixo. |
estilo (a página inteira):
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
tema | enum | claro · escuro · auto | claro | claro (padrão), escuro ou auto (segue o aparelho). |
fundo | fundo | Fundo da caixa. tipo decide quais campos valem: cor exige cor; gradiente exige gradiente; imagem exige imagem.url. | ||
padrao | objeto | Textura sutil desenhada sobre o fundo da página. | ||
padrao.tipo (obrigatório) | enum | nenhum · pontos · grade · diagonal | nenhum, pontos, grade ou diagonal. | |
padrao.cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da textura (padrão: a cor do texto). | |
padrao.opacidade | inteiro | 0..100 | 8 | Opacidade da textura, em % (0..100). |
padrao.tamanho | const ou inteiro | 0 ou 8..96 | 24 | Módulo da textura em px: 0 (padrão = 24) ou 8..96. |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
fonte_titulos | const ou enum | "" ou comfortaa · urbanist · montserrat · inter · poppins · open-sans · nunito · playfair-display · merriweather · dm-sans · manrope · raleway | Família dos títulos h1..h6. Vazio herda do kit de marca. Só os ids da allowlist (auto-hospedados em /_f/). | |
fonte_texto | const ou enum | "" ou comfortaa · urbanist · montserrat · inter · poppins · open-sans · nunito · playfair-display · merriweather · dm-sans · manrope · raleway | Família do texto corrido. Mesma regra de fonte_titulos. | |
conteudo | estiloCaixa | A caixa do miolo CONTIDO de toda seção (a coluna estreita de uma página de links): fundo, borda, raio, sombra, padding. |
Famílias de fonte aceitas em estilo.fonte_titulos e estilo.fonte_texto (ids exatos, em minúsculas; vazio herda do kit de marca; qualquer outro valor é ErrEstiloInvalido):
comfortaa, urbanist, montserrat, inter, poppins, open-sans, nunito, playfair-display, merriweather, dm-sans, manrope, raleway São auto-hospedadas pelo runtime (/_f/), sem chamada a terceiros.
Seção
Seção:
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
id (obrigatório) | id | ^[A-Za-z0-9_-]{1,64}$ | Único no documento inteiro (seção, coluna, item e itens de painel dividem o mesmo espaço). | |
preset | texto | ^[a-z0-9_-]{1,40}$ | Só registra de que fábrica a seção nasceu; o renderer não desenha diferente por causa dele. | |
nome | texto | ≤80 | Rótulo livre, só para a árvore do editor. | |
ancora | âncora | ^[a-z][a-z0-9-]{0,63}$ | Vira o id HTML da seção; alvo de #ancora em botões e menus. Única na página. | |
comportamento | enum | normal · fixa_topo · popup | normal | normal; fixa_topo gruda no topo ao rolar; popup abre por cima após atraso_popup s. |
atraso_popup | inteiro | 0..120 | Segundos até o popup abrir (só com comportamento: popup). | |
ocultar_em | lista de enum | sem repetição · valores: computador, tablet, celular | Dispositivos em que o nó não aparece. Pontos de quebra: celular até 767 px, tablet 768-1023 px, computador a partir de 1024 px. | |
ocultar_se_vazia | booleano | true / false | A seção some quando nenhum item dela desenha algo (ex.: marca numa conta sem logo nem nome). | |
layout_celular | enum | empilhar · manter | empilhar | empilhar (padrão): uma coluna por linha no celular; manter conserva as colunas lado a lado. |
inverter_celular | booleano | true / false | Empilha as colunas na ordem inversa no celular. | |
estilo | estiloSecao | Objeto de estilo (ver a tabela do contexto). | ||
colunas (obrigatório) | lista de coluna | ≥1 · ≤12 | Lista de colunas da seção (1..12). |
estilo da seção (estiloSecao):
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
padding | lados | Respiro interno em px por lado (0..400). | ||
padding_celular | lados | Substitui padding abaixo de 768 px; ausente, o celular usa padding. | ||
fundo | fundo | Fundo da caixa. tipo decide quais campos valem: cor exige cor; gradiente exige gradiente; imagem exige imagem.url. | ||
borda | borda | Objeto de borda (ver borda). | ||
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
raio_sup_esq | inteiro | 0..200 | Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq. | |
raio_sup_dir | inteiro | 0..200 | Raio do canto superior direito (ver raio_sup_esq). | |
raio_inf_dir | inteiro | 0..200 | Raio do canto inferior direito (ver raio_sup_esq). | |
raio_inf_esq | inteiro | 0..200 | Raio do canto inferior esquerdo (ver raio_sup_esq). | |
sombra | enum | nenhuma · suave · media · forte | Sombra da caixa (vocabulário de caixa: suave/media/forte). | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
largura | enum | contida · total | contida | contida: o conteúdo respeita largura_max; total: ocupa a largura toda. |
largura_max | const ou qualquer JSON | 0 | 1080 | Largura do conteúdo contido, em px (320..2400); 0/ausente = 1080. Só vale com largura: contida. |
altura_minima | inteiro | 0..2000 | Altura mínima da seção; a unidade é altura_unidade (px até 2000, vh até 100). | |
altura_unidade | enum | px · vh | px (padrão) ou vh. | |
alinhamento_vertical | enum | topo · centro · base · esticar | Posição das colunas (seção) ou do conteúdo (coluna) no eixo vertical. | |
gap_colunas | inteiro | 0..400 | 24 | Espaço entre as colunas da seção, em px (padrão 24). |
Para uma seção popup, atraso_popup é em segundos (0..120). fixa_topo serve para cabeçalhos. ocultar_se_vazia esconde a seção quando nenhum item desenha algo.
Coluna
Coluna:
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
id (obrigatório) | id | ^[A-Za-z0-9_-]{1,64}$ | Único no documento inteiro (seção, coluna, item e itens de painel dividem o mesmo espaço). | |
largura | inteiro | 0..12 | 1 | PESO da coluna (unidade fr): 1+2 dá 1/3 + 2/3. Ausente/0 = peso 1. |
alinhamento_vertical | enum | topo · centro · base · esticar | Posição das colunas (seção) ou do conteúdo (coluna) no eixo vertical. | |
alinhamento_horizontal | enum | inicio · centro · fim · esticar | Posição do conteúdo da coluna no eixo horizontal. | |
gap | inteiro | 0..400 | 16 | Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos. |
estilo | estiloCaixa | Objeto de estilo (ver a tabela do contexto). | ||
itens (obrigatório) | lista de item | ≤100 |
estilo da coluna (estiloCaixa, o mesmo de estilo.conteudo da página):
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
padding | lados | Respiro interno em px por lado (0..400). | ||
padding_celular | lados | Substitui padding abaixo de 768 px; ausente, o celular usa padding. | ||
fundo | fundo | Fundo da caixa. tipo decide quais campos valem: cor exige cor; gradiente exige gradiente; imagem exige imagem.url. | ||
borda | borda | Objeto de borda (ver borda). | ||
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
raio_sup_esq | inteiro | 0..200 | Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq. | |
raio_sup_dir | inteiro | 0..200 | Raio do canto superior direito (ver raio_sup_esq). | |
raio_inf_dir | inteiro | 0..200 | Raio do canto inferior direito (ver raio_sup_esq). | |
raio_inf_esq | inteiro | 0..200 | Raio do canto inferior esquerdo (ver raio_sup_esq). | |
sombra | enum | nenhuma · suave · media · forte | Sombra da caixa (vocabulário de caixa: suave/media/forte). | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. |
O envelope do item
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
id (obrigatório) | id | ^[A-Za-z0-9_-]{1,64}$ | Único no documento inteiro (seção, coluna, item e itens de painel dividem o mesmo espaço). | |
tipo (obrigatório) | enum | titulo · texto · imagem · botao · tags · links · cartoes · abas · acordeao · redes · menu · formulario · video · divisor · espacador · icone · selo · contador · marca · html | Tipo do item (lista fechada). | |
props (obrigatório) | objeto | Props do tipo (tabela do tipo); campo desconhecido é recusado. | ||
estilo | objeto | Visual do item na coluna (margem, alinhamento, largura máxima, cor do texto, subir). | ||
estilo.margem | lados | Respiro externo do item, por lado, em px (0..400). subir > 0 substitui a margem de topo. | ||
estilo.alinhamento | enum | herdar · inicio · centro · fim | herdar | Sobrepõe o alinhamento horizontal da coluna; herdar (padrão) mantém o da coluna. |
estilo.largura_max | inteiro | 0..2400 | Largura máxima do item, em px (0 = sem limite). | |
estilo.cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
estilo.subir | inteiro | 0..200 | Puxa o item para cima, sobre o anterior (margin-top negativo), 0..200 px. Substitui a margem de topo. | |
ocultar_em | lista de enum | sem repetição · valores: computador, tablet, celular | Dispositivos em que o nó não aparece. Pontos de quebra: celular até 767 px, tablet 768-1023 px, computador a partir de 1024 px. |
Os campos id, tipo e props são obrigatórios. O estilo do item é opcional e comum a todos os tipos: margem (por lado), alinhamento, largura_max, cor_texto e subir.
3.4 Objetos e tipos reutilizados
Cores (cor)
Uma cor é um hex #rrggbb / #rrggbbaa OU um token da paleta da página: transparente, acento, texto, suave, fundo, superficie, borda. acento segue a cor da marca da conta; transparente serve de ponta de degradê (fade). Nome de cor CSS (red), rgb(), hex curto (#fff) e qualquer texto livre são recusados. Onde o schema diz "cor ou vazio", "" significa "use o padrão do tema".
lados
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
topo | inteiro | 0..400 | Px do lado superior. | |
direita | inteiro | 0..400 | Px do lado direito. | |
base | inteiro | 0..400 | Px do lado inferior. | |
esquerda | inteiro | 0..400 | Px do lado esquerdo. |
fundo
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
tipo | enum | nenhum · cor · gradiente · imagem | nenhum, cor, gradiente ou imagem. | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do fundo (obrigatória quando tipo é cor). | |
cor_base | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor sólida sob as demais camadas (gradiente/imagem/película). | |
gradiente | gradiente | Degradê (ver gradiente). Obrigatório quando fundo.tipo é gradiente; na película, use-o no lugar de cor. | ||
imagem | objeto | Imagem de fundo (obrigatória quando tipo é imagem). | ||
imagem.url (obrigatório) | url de mídia | ≤2048 · http(s) com host ou /caminho | URL da imagem de fundo (galeria da conta ou https://). Obrigatória quando fundo.tipo é imagem. | |
imagem.posicao | enum | centro · topo · base · esquerda · direita · topo-esquerda · topo-direita · base-esquerda · base-direita | Posição da imagem de fundo. | |
imagem.tamanho | enum | cobrir · conter · auto | cobrir (preenche cortando), conter (mostra inteira) ou auto (tamanho original). | |
imagem.repetir | booleano | true / false | Repete a imagem de fundo. | |
imagem.fixo | booleano | true / false | Fundo fixo (não rola com a página). | |
sobreposicao | um de | Película por cima do fundo: exige cor OU gradiente (um só) e opacidade 0..100 na camada inteira. | ||
sobreposicao.cor | cor | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da película (use esta OU gradiente). | |
sobreposicao.gradiente | gradiente | Degradê (ver gradiente). Obrigatório quando fundo.tipo é gradiente; na película, use-o no lugar de cor. | ||
sobreposicao.opacidade (obrigatório) | inteiro | 0..100 | Opacidade da película na camada inteira, em % (0..100). |
gradiente
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
tipo | enum | linear · radial | linear (padrão, no angulo) ou radial (círculo a partir do centro). | |
de (obrigatório) | cor | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor inicial do degradê (aceita transparente). | |
meio | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor intermediária opcional do degradê. | |
para (obrigatório) | cor | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor final do degradê (aceita transparente). | |
angulo | inteiro | 0..360 | Ângulo do degradê, em graus (0..360). |
borda
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
largura | inteiro | 0..20 | Espessura da borda em px (0..20). | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
estilo | enum | solida · tracejada · pontilhada | solida, tracejada ou pontilhada. | |
lados | lista de enum | sem repetição · valores: topo, direita, base, esquerda | Lados que recebem a borda (sem repetir); ausente = os quatro. |
3.5 Cada tipo de item, campo a campo
titulo
Título (h1..h6). Aceita marcação inline [rótulo](url) e [[trecho]].
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
texto | texto | ≤300 | Texto do título. Aceita a marcação inline ([rótulo](url), [[destaque]]). | |
nivel | inteiro | 1..6 | Nível do cabeçalho (h1..h6). Use um único h1 por página. | |
tamanho | enum | auto · p · m · g · gg | auto | Escala tipográfica: auto (padrão do nível), p, m, g, gg. |
transformar | enum | nenhum · caixa_alta · caixa_baixa · capitalizar | text-transform: nenhum, caixa_alta, caixa_baixa, capitalizar. | |
espacamento | inteiro | 0..6 | Espaçamento entre letras (letter-spacing) em px, 0..6. | |
destaque_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor aplicada aos trechos [[destaque]] do texto (token ou hex). |
texto
Parágrafo de texto. Aceita a mesma marcação inline do título e quebras de linha.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
texto | texto | ≤20000 | Texto do parágrafo. Aceita a marcação inline ([rótulo](url), [[destaque]]) e quebras de linha. | |
variante | enum | normal · suave · destaque · citacao | normal | normal, suave (cor atenuada), destaque, citacao. |
tamanho | enum | auto · p · m · g · gg | auto | Escala tipográfica: auto (padrão), p, m, g, gg. |
transformar | enum | nenhum · caixa_alta · caixa_baixa · capitalizar | text-transform: nenhum, caixa_alta, caixa_baixa, capitalizar. | |
espacamento | inteiro | 0..6 | Espaçamento entre letras (letter-spacing) em px, 0..6. | |
destaque_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor aplicada aos trechos [[destaque]] do texto (token ou hex). |
imagem
Imagem, com forma, proporção, moldura e link opcional.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
url | url de mídia | ≤2048 · http(s) com host ou /caminho | URL da imagem: da galeria da conta (/v1/public/midias/<id>) ou https:// externa. Sem aspas, espaços, parênteses ou <>. | |
alt | texto | ≤300 | Texto alternativo (acessibilidade e SEO). Descreva a imagem; vazio só para imagem decorativa. | |
link | url de link | ≤2048 · http/https/mailto/tel, #ancora, /caminho | Destino ao clicar na imagem (regra de href). | |
forma | enum | normal · arredondada · circulo | normal | normal, arredondada ou circulo. raio presente vence forma. |
largura | inteiro | 16..2400 | Largura em px (16..2400). Ausente = a imagem ocupa a coluna. | |
proporcao | enum | auto · 1:1 · 4:3 · 3:4 · 16:9 · 9:16 | auto | Proporção da caixa: auto (padrão) ou largura:altura. |
ajuste | enum | cobrir · conter | cobrir | cobrir (padrão: preenche cortando) ou conter (mostra inteira). |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
sombra | enum | nenhuma · leve · forte | Sombra do item (vocabulário de item: leve/forte). Não misture com o de caixa. | |
cor_fundo | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo atrás da imagem (aparece na moldura/padding). | |
padding | inteiro | 0..40 | Respiro interno em px por lado (0..400). | |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
raio_sup_esq | inteiro | 0..200 | Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq. | |
raio_sup_dir | inteiro | 0..200 | Raio do canto superior direito (ver raio_sup_esq). | |
raio_inf_dir | inteiro | 0..200 | Raio do canto inferior direito (ver raio_sup_esq). | |
raio_inf_esq | inteiro | 0..200 | Raio do canto inferior esquerdo (ver raio_sup_esq). | |
link_rastreio | objeto ou null | Objeto do encurtador para link (ver url_rastreio). |
botao
Botão (ou link-botão) com visual granular, vidro, ícones e imagem.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
rotulo | texto | ≤300 | Texto do botão. | |
transformar | enum | nenhum · caixa_alta · caixa_baixa · capitalizar | text-transform: nenhum, caixa_alta, caixa_baixa, capitalizar. | |
espacamento | inteiro | 0..6 | Espaçamento entre letras (letter-spacing) em px, 0..6. | |
url | url de link | ≤2048 · http/https/mailto/tel, #ancora, /caminho | Destino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>). | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
variante | enum | solido · contorno · texto | solido | solido (padrão), contorno ou texto. |
tamanho | enum | p · m · g | m | p, m (padrão) ou g. |
largura_total | booleano | true / false | false | O botão ocupa a largura toda da coluna. |
nova_aba | booleano | true / false | false | Abre em nova aba (target=_blank com rel=noopener). |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
raio_sup_esq | inteiro | 0..200 | Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq. | |
raio_sup_dir | inteiro | 0..200 | Raio do canto superior direito (ver raio_sup_esq). | |
raio_inf_dir | inteiro | 0..200 | Raio do canto inferior direito (ver raio_sup_esq). | |
raio_inf_esq | inteiro | 0..200 | Raio do canto inferior esquerdo (ver raio_sup_esq). | |
padding_v | inteiro | 0..400 | Respiro vertical interno em px (0..400). | |
padding_h | inteiro | 0..400 | Respiro horizontal interno em px (0..400). | |
fonte_peso | enum | 400 · 500 · 600 · 700 · 800 | Peso da fonte, como TEXTO: "400", "500", "600", "700", "800". | |
fonte_tamanho | inteiro | 10..72 | Tamanho da fonte em px (10..72). | |
sombra | enum | nenhuma · leve · forte | Sombra do item (vocabulário de item: leve/forte). Não misture com o de caixa. | |
icone | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | Nome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link). | |
icone_dir | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | Ícone do FIM (direita) do botão/entrada. Mesmas regras de icone. | |
hover_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo ao passar o mouse/foco. | |
hover_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto no hover. | |
hover_cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda no hover. | |
vidro | booleano | true / false | Liga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados. | |
vidro_opacidade | inteiro | 0..100 | Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30. | |
vidro_desfoque | inteiro | 0..40 | Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14. | |
vidro_saturacao | inteiro | 100..200 | Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160. | |
icone_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado. | |
icone_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do início. | |
icone_fundo_tamanho | inteiro | 24..72 | Lado do contêiner em px (24..72). | |
icone_dir_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do FIM: nenhum, circulo, quadrado. | |
icone_dir_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do fim. | |
icone_dir_fundo_tamanho | inteiro | 24..72 | Lado do contêiner do fim em px (24..72). | |
cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do(s) ícone(s). Vazio herda a cor do texto. | |
cor_icone_inicio | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone do início (vence cor_icone). | |
cor_icone_fim | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone do fim (vence cor_icone). | |
hover_cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone no hover. | |
imagem | url de mídia | ≤2048 · http(s) com host ou /caminho | Imagem DENTRO do botão/entrada: URL de mídia (galeria ou https://). | |
imagem_alt | texto | ≤300 | Texto alternativo da imagem do botão. | |
imagem_posicao | enum | inicio · fim · topo | inicio | Onde fica a imagem: inicio (padrão), fim ou topo. |
imagem_tamanho | enum | p · m · g | m | Tamanho da imagem: p, m (padrão) ou g. |
imagem_forma | enum | quadrada · arredondada · circulo | arredondada | quadrada, arredondada (padrão) ou circulo. |
icone_img | url de mídia | ≤2048 · http(s) com host ou /caminho | Ícone PERSONALIZADO do início: URL de mídia (vira <img>). Vence o glifo icone; cores de ícone não se aplicam. | |
icone_dir_img | url de mídia | ≤2048 · http(s) com host ou /caminho | Ícone personalizado do fim (ver icone_img). | |
url_rastreio | objeto ou null | Objeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido. |
tags
Chips (etiquetas) com ícone, link e visual por chip.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
itens | lista de objeto | ≤50 | Até 50 chips. | |
preset | enum | translucido · solido · contorno | translucido | Aparência base dos chips: translucido (padrão), solido, contorno. |
icone | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | Nome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link). | |
cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do(s) ícone(s). Vazio herda a cor do texto. | |
vidro | booleano | true / false | Liga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados. | |
vidro_opacidade | inteiro | 0..100 | Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30. | |
vidro_desfoque | inteiro | 0..40 | Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14. | |
vidro_saturacao | inteiro | 100..200 | Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160. | |
icone_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado. | |
icone_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do início. | |
icone_fundo_tamanho | inteiro | 24..72 | Lado do contêiner em px (24..72). | |
icone_dir_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do FIM: nenhum, circulo, quadrado. | |
icone_dir_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do fim. | |
icone_dir_fundo_tamanho | inteiro | 24..72 | Lado do contêiner do fim em px (24..72). | |
hover_cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone no hover. | |
tamanho_icone | inteiro | 10..48 | Tamanho do ícone em px. | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
hover_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo ao passar o mouse/foco. | |
hover_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto no hover. | |
hover_cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda no hover. | |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
padding_v | inteiro | 0..400 | Respiro vertical interno em px (0..400). | |
padding_h | inteiro | 0..400 | Respiro horizontal interno em px (0..400). | |
fonte_peso | enum | 400 · 500 · 600 · 700 · 800 | Peso da fonte, como TEXTO: "400", "500", "600", "700", "800". | |
fonte_tamanho | inteiro | 10..72 | Tamanho da fonte em px (10..72). | |
gap | inteiro | 0..400 | Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos. | |
alinhamento | enum | inicio · centro · fim | inicio | Alinhamento do conjunto de chips. |
quebra | enum | quebrar · linha | quebrar | quebrar (padrão) quebra linha; linha mantém uma linha só. |
Cada entrada de tags.itens[]:
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
texto | texto | ≤60 | Texto do chip. | |
icone | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | Nome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link). | |
url | url de link | ≤2048 · http/https/mailto/tel, #ancora, /caminho | Destino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>). | |
nova_aba | booleano | true / false | Abre em nova aba (target=_blank com rel=noopener). | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
hover_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo ao passar o mouse/foco. | |
hover_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto no hover. | |
hover_cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda no hover. | |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
padding_v | inteiro | 0..400 | Respiro vertical interno em px (0..400). | |
padding_h | inteiro | 0..400 | Respiro horizontal interno em px (0..400). | |
fonte_peso | enum | 400 · 500 · 600 · 700 · 800 | Peso da fonte, como TEXTO: "400", "500", "600", "700", "800". | |
fonte_tamanho | inteiro | 10..72 | Tamanho da fonte em px (10..72). | |
sombra | enum | nenhuma · leve · forte | Sombra do item (vocabulário de item: leve/forte). Não misture com o de caixa. | |
vidro | booleano | true / false | Liga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados. | |
vidro_opacidade | inteiro | 0..100 | Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30. | |
vidro_desfoque | inteiro | 0..40 | Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14. | |
vidro_saturacao | inteiro | 100..200 | Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160. | |
icone_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado. | |
icone_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do início. | |
icone_fundo_tamanho | inteiro | 24..72 | Lado do contêiner em px (24..72). | |
icone_dir_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do FIM: nenhum, circulo, quadrado. | |
icone_dir_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do fim. | |
icone_dir_fundo_tamanho | inteiro | 24..72 | Lado do contêiner do fim em px (24..72). | |
cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do(s) ícone(s). Vazio herda a cor do texto. | |
hover_cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone no hover. | |
imagem | url de mídia | ≤2048 · http(s) com host ou /caminho | Imagem DENTRO do botão/entrada: URL de mídia (galeria ou https://). | |
imagem_alt | texto | ≤300 | Texto alternativo da imagem do botão. | |
imagem_posicao | enum | inicio · fim · topo | Onde fica a imagem: inicio (padrão), fim ou topo. | |
imagem_tamanho | enum | p · m · g | Tamanho da imagem: p, m (padrão) ou g. | |
imagem_forma | enum | quadrada · arredondada · circulo | quadrada, arredondada (padrão) ou circulo. | |
icone_img | url de mídia | ≤2048 · http(s) com host ou /caminho | Ícone PERSONALIZADO do início: URL de mídia (vira <img>). Vence o glifo icone; cores de ícone não se aplicam. | |
icone_dir_img | url de mídia | ≤2048 · http(s) com host ou /caminho | Ícone personalizado do fim (ver icone_img). | |
cor_icone_inicio | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone do início (vence cor_icone). | |
url_rastreio | objeto ou null | Objeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido. |
links
Lista de botões de link (o miolo de um link-na-bio), com visual por entrada.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
itens | lista de objeto | ≤50 | Até 50 botões. Entrada sem titulo e sem URL válida é ignorada; sem titulo, a URL vira o texto do botão. | |
estilo | enum | cartao · preenchido · contorno · fantasma · suave · sombra | cartao | Aparência dos botões: cartao (padrão), preenchido, contorno, fantasma, suave, sombra. |
tamanho | enum | p · m · g | m | p, m (padrão) ou g. |
largura | enum | total · conteudo | total | total: cada botão ocupa a largura da coluna; conteudo: só o tamanho do conteúdo. |
alinhamento_texto | enum | centro · inicio | centro | Alinhamento do texto do botão/cartão: centro ou inicio. |
efeito | enum | elevar · escala · brilho · fundo · sublinhado · nenhum | elevar | Efeito no hover/foco: elevar (padrão), escala, brilho, fundo, sublinhado, nenhum. Desligado em prefers-reduced-motion. |
efeito_icone | enum | nenhum · deslizar · destacar · girar | nenhum | girar gira o ícone do fim no hover (bola de seta); deslizar, destacar, nenhum (padrão). |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
espaco | inteiro | 0..400 | Espaço entre os botões da lista, em px. | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do(s) ícone(s). Vazio herda a cor do texto. | |
vidro | booleano | true / false | Liga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados. | |
vidro_opacidade | inteiro | 0..100 | Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30. | |
vidro_desfoque | inteiro | 0..40 | Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14. | |
vidro_saturacao | inteiro | 100..200 | Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160. | |
icone_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado. | |
icone_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do início. | |
icone_fundo_tamanho | inteiro | 24..72 | Lado do contêiner em px (24..72). | |
icone_dir_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do FIM: nenhum, circulo, quadrado. | |
icone_dir_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do fim. | |
icone_dir_fundo_tamanho | inteiro | 24..72 | Lado do contêiner do fim em px (24..72). | |
cor_icone_inicio | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone do início (vence cor_icone). | |
cor_icone_fim | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone do fim (vence cor_icone). | |
hover_cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone no hover. | |
tamanho_icone | inteiro | 12..64 | Tamanho do ícone em px. |
Cada entrada de links.itens[]:
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
titulo | texto | ≤300 | Texto principal do botão. | |
texto | texto | ≤300 | Linha secundária sob o título do botão. | |
url | url de link | ≤2048 · http/https/mailto/tel, #ancora, /caminho | Destino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>). | |
icone | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | Nome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link). | |
icone_img | url de mídia | ≤2048 · http(s) com host ou /caminho | Ícone PERSONALIZADO do início: URL de mídia (vira <img>). Vence o glifo icone; cores de ícone não se aplicam. | |
icone_dir | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | Ícone do FIM (direita) do botão/entrada. Mesmas regras de icone. | |
icone_dir_img | url de mídia | ≤2048 · http(s) com host ou /caminho | Ícone personalizado do fim (ver icone_img). | |
destaque | booleano | true / false | Realça a entrada (visual de destaque do tema). | |
nova_aba | booleano | true / false | Abre em nova aba (target=_blank com rel=noopener). | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
hover_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo ao passar o mouse/foco. | |
hover_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto no hover. | |
hover_cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda no hover. | |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
padding_v | inteiro | 0..400 | Respiro vertical interno em px (0..400). | |
padding_h | inteiro | 0..400 | Respiro horizontal interno em px (0..400). | |
fonte_peso | enum | 400 · 500 · 600 · 700 · 800 | Peso da fonte, como TEXTO: "400", "500", "600", "700", "800". | |
fonte_tamanho | inteiro | 10..72 | Tamanho da fonte em px (10..72). | |
sombra | enum | nenhuma · leve · forte | Sombra do item (vocabulário de item: leve/forte). Não misture com o de caixa. | |
vidro | booleano | true / false | Liga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados. | |
vidro_opacidade | inteiro | 0..100 | Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30. | |
vidro_desfoque | inteiro | 0..40 | Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14. | |
vidro_saturacao | inteiro | 100..200 | Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160. | |
icone_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado. | |
icone_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do início. | |
icone_fundo_tamanho | inteiro | 24..72 | Lado do contêiner em px (24..72). | |
icone_dir_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do FIM: nenhum, circulo, quadrado. | |
icone_dir_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do fim. | |
icone_dir_fundo_tamanho | inteiro | 24..72 | Lado do contêiner do fim em px (24..72). | |
cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do(s) ícone(s). Vazio herda a cor do texto. | |
cor_icone_inicio | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone do início (vence cor_icone). | |
cor_icone_fim | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone do fim (vence cor_icone). | |
hover_cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone no hover. | |
imagem | url de mídia | ≤2048 · http(s) com host ou /caminho | Imagem DENTRO do botão/entrada: URL de mídia (galeria ou https://). | |
imagem_alt | texto | ≤300 | Texto alternativo da imagem do botão. | |
imagem_posicao | enum | inicio · fim · topo | Onde fica a imagem: inicio (padrão), fim ou topo. | |
imagem_tamanho | enum | p · m · g | Tamanho da imagem: p, m (padrão) ou g. | |
imagem_forma | enum | quadrada · arredondada · circulo | quadrada, arredondada (padrão) ou circulo. | |
url_rastreio | objeto ou null | Objeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido. |
cartoes
Galeria de cartões (foto, título, texto, tag, ícone, link) em grade, carrossel ou lista.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
itens | lista de objeto | ≤50 | Até 50 cartões. | |
layout | enum | grade · carrossel · lista | grade | grade (padrão), carrossel (rolagem com snap, sem JS) ou lista (miniatura + texto). |
colunas | inteiro | 1..4 | Colunas da grade (1..4). | |
largura_cartao | inteiro | 96..400 | Largura de cada cartão no carrossel, em px (96..400). | |
proporcao | enum | auto · 1:1 · 4:3 · 3:4 · 16:9 · 9:16 · 4:5 | auto | Proporção da caixa: auto (padrão) ou largura:altura. |
ajuste | enum | cobrir · conter | cobrir | cobrir (padrão: preenche cortando) ou conter (mostra inteira). |
legenda | enum | abaixo · sobre · nenhuma | abaixo | abaixo (padrão), sobre (texto sobre a foto, com degradê automático) ou nenhuma. |
miniatura | inteiro | 56..96 | Lado da miniatura no layout lista, em px (56..96). | |
forma_miniatura | enum | quadrada · arredondada · circulo | arredondada | Forma da miniatura da lista: quadrada, arredondada (padrão), circulo. |
moldura | enum | nenhuma · polaroid | nenhuma | nenhuma (padrão) ou polaroid. |
inclinar | inteiro | 0..12 | Inclinação alternada do conjunto, em graus (0..12), típica da moldura polaroid. | |
rotulo | texto | ≤300 | Rótulo acessível (aria-label) da galeria. | |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
raio_sup_esq | inteiro | 0..200 | Raio do canto superior esquerdo. Com ao menos um canto presente, o renderer emite os quatro; canto ausente usa raio (ou 0). Sentido horário: sup_esq, sup_dir, inf_dir, inf_esq. | |
raio_sup_dir | inteiro | 0..200 | Raio do canto superior direito (ver raio_sup_esq). | |
raio_inf_dir | inteiro | 0..200 | Raio do canto inferior direito (ver raio_sup_esq). | |
raio_inf_esq | inteiro | 0..200 | Raio do canto inferior esquerdo (ver raio_sup_esq). | |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
sombra | enum | nenhuma · leve · forte | Sombra do item (vocabulário de item: leve/forte). Não misture com o de caixa. | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
hover_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo ao passar o mouse/foco. | |
hover_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto no hover. | |
hover_cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda no hover. | |
gap | inteiro | 0..400 | Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos. | |
efeito | enum | elevar · escala · brilho · nenhum | nenhum | Efeito no hover/foco: elevar, escala, brilho, nenhum (padrão). |
alinhamento_texto | enum | centro · inicio | inicio | Alinhamento do texto do botão/cartão: centro ou inicio. |
tamanho_icone | inteiro | 12..64 | Tamanho do ícone em px. | |
cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do(s) ícone(s). Vazio herda a cor do texto. | |
hover_cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone no hover. | |
vidro | booleano | true / false | Liga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados. | |
vidro_opacidade | inteiro | 0..100 | Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30. | |
vidro_desfoque | inteiro | 0..40 | Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14. | |
vidro_saturacao | inteiro | 100..200 | Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160. | |
icone_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado. | |
icone_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do início. | |
icone_fundo_tamanho | inteiro | 24..72 | Lado do contêiner em px (24..72). | |
icone_dir_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do FIM: nenhum, circulo, quadrado. | |
icone_dir_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do fim. | |
icone_dir_fundo_tamanho | inteiro | 24..72 | Lado do contêiner do fim em px (24..72). |
Cada entrada de cartoes.itens[]:
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
img | url de mídia | ≤2048 · http(s) com host ou /caminho | Foto do cartão (URL de mídia). | |
alt | texto | ≤300 | Texto alternativo (acessibilidade e SEO). Descreva a imagem; vazio só para imagem decorativa. | |
titulo | texto | ≤300 | Título do cartão. | |
texto | texto | ≤300 | Texto do cartão. | |
tag | texto | ≤60 | Etiqueta curta do cartão (até 60). | |
icone | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | Nome do ícone (^[a-z0-9_-]{1,40}$): clássico (raio, escudo, check, seta, calendario, telefone...), rede (instagram, whatsapp...) ou do kit (tabler-, tabler-f-, ph-, hero-, hero-s- + nome; sem prefixo = Lucide). Nome desconhecido não quebra a página: o ícone some (em links vira o ícone genérico de link). | |
url | url de link | ≤2048 · http/https/mailto/tel, #ancora, /caminho | Destino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>). | |
nova_aba | booleano | true / false | Abre em nova aba (target=_blank com rel=noopener). | |
rotacao | inteiro | -15..15 | Rotação deste cartão em graus (-15..15). Vence inclinar do conjunto. | |
cor_fim | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Liga o degradê do fundo do cartão: cor é o início e cor_fim o fim. | |
angulo | inteiro | 0..360 | Ângulo do degradê, em graus (0..360). | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
hover_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo ao passar o mouse/foco. | |
hover_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto no hover. | |
hover_cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda no hover. | |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
padding_v | inteiro | 0..400 | Respiro vertical interno em px (0..400). | |
padding_h | inteiro | 0..400 | Respiro horizontal interno em px (0..400). | |
fonte_peso | enum | 400 · 500 · 600 · 700 · 800 | Peso da fonte, como TEXTO: "400", "500", "600", "700", "800". | |
fonte_tamanho | inteiro | 10..72 | Tamanho da fonte em px (10..72). | |
sombra | enum | nenhuma · leve · forte | Sombra do item (vocabulário de item: leve/forte). Não misture com o de caixa. | |
cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do(s) ícone(s). Vazio herda a cor do texto. | |
hover_cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone no hover. | |
vidro | booleano | true / false | Liga o efeito VIDRO LÍQUIDO (fundo translúcido + backdrop-filter). Sem true, os demais vidro_* são ignorados. | |
vidro_opacidade | inteiro | 0..100 | Alfa do fundo de vidro, em % (0..100). Padrão com vidro ligado: 30. | |
vidro_desfoque | inteiro | 0..40 | Desfoque do fundo atrás do vidro, em px (0..40). Padrão: 14. | |
vidro_saturacao | inteiro | 100..200 | Saturação do fundo atrás do vidro, em % (100..200). Padrão: 160. | |
icone_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado. | |
icone_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do início. | |
icone_fundo_tamanho | inteiro | 24..72 | Lado do contêiner em px (24..72). | |
icone_dir_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do FIM: nenhum, circulo, quadrado. | |
icone_dir_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do fim. | |
icone_dir_fundo_tamanho | inteiro | 24..72 | Lado do contêiner do fim em px (24..72). | |
url_rastreio | objeto ou null | Objeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido. |
abas
Abas; cada aba é um painel com itens aninhados (um nível só).
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
itens | lista de objeto | ≤20 | Até 20 abas. Cada uma: titulo (obrigatório, não vazio) e itens aninhados. | |
aberta | inteiro | 0..19 | Índice (0 = primeira) da aba aberta de início. Tem de existir. | |
rotulo | texto | ≤300 | Rótulo acessível (aria-label) da lista de abas. | |
estilo | enum | linha · pilula · cartao | linha | Aparência da barra: linha (padrão), pilula, cartao. |
alinhamento | enum | inicio · centro · fim · esticar | inicio | Alinhamento da barra de abas; esticar reparte a largura. |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
cor_ativa | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Fundo da aba ativa. | |
cor_texto_ativa | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Texto da aba ativa. | |
cor_borda_ativa | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Borda da aba ativa. | |
hover_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo ao passar o mouse/foco. | |
hover_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto no hover. | |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
padding_v | inteiro | 0..400 | Respiro vertical interno em px (0..400). | |
padding_h | inteiro | 0..400 | Respiro horizontal interno em px (0..400). | |
fonte_peso | enum | 400 · 500 · 600 · 700 · 800 | Peso da fonte, como TEXTO: "400", "500", "600", "700", "800". | |
fonte_tamanho | inteiro | 10..72 | Tamanho da fonte em px (10..72). | |
gap | inteiro | 0..400 | Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos. | |
painel_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Fundo da área de conteúdo do painel. | |
painel_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Texto da área de conteúdo do painel. | |
painel_cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Borda da área de conteúdo do painel. | |
painel_borda | inteiro | 0..20 | Espessura da borda do painel (0..20). | |
painel_raio | inteiro | 0..200 | Raio do painel (0..200). | |
painel_padding | inteiro | 0..400 | Respiro interno do painel em px. |
Cada entrada de abas.itens[]:
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
titulo | texto | ≤200 | Título da aba (obrigatório). | |
itens | lista de itens aninhados | ≤20 · tipos: titulo, texto, imagem, botao, tags, links, cartoes, redes, menu, video, divisor, espacador, icone, selo, contador, marca | Até 20 abas. Cada uma: titulo (obrigatório, não vazio) e itens aninhados. |
acordeao
Acordeão (sanfona); com faq: true gera FAQPage no JSON-LD da página.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
itens | lista de objeto | ≤20 | Até 20 painéis. Cada um: titulo (obrigatório, não vazio), aberto e itens aninhados. | |
um_por_vez | booleano | true / false | false | Abrir um painel fecha os outros. |
faq | booleano | true / false | Gera FAQPage no JSON-LD. Exige texto de resposta em cada painel (itens texto/titulo), até 4000 caracteres; até 50 perguntas na página. | |
nivel | inteiro | 2..6 | Nível do cabeçalho de cada pergunta (2..6). | |
estilo | enum | cartao · linha · simples | cartao | Aparência: cartao (padrão), linha, simples. |
indicador | enum | seta · mais · nenhum | seta | Marcador de aberto/fechado: seta (padrão), mais ou nenhum. |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo/principal (token da paleta ou hex). Vazio = a do tema. | |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto. Herda da caixa/página quando vazia. | |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da borda. | |
cor_aberto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Fundo do painel aberto. | |
cor_texto_aberto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Texto do painel aberto. | |
hover_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor de fundo ao passar o mouse/foco. | |
hover_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do texto no hover. | |
raio | inteiro | 0..200 | Raio dos cantos em px (0..200). | |
borda | inteiro | 0..20 | Espessura da borda em px (0..20). | |
padding_v | inteiro | 0..400 | Respiro vertical interno em px (0..400). | |
padding_h | inteiro | 0..400 | Respiro horizontal interno em px (0..400). | |
fonte_peso | enum | 400 · 500 · 600 · 700 · 800 | Peso da fonte, como TEXTO: "400", "500", "600", "700", "800". | |
fonte_tamanho | inteiro | 10..72 | Tamanho da fonte em px (10..72). | |
gap | inteiro | 0..400 | Espaço entre os itens da coluna, em px (padrão 16). Em tags/cartoes: espaço entre os elementos. | |
painel_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Fundo da área de conteúdo do painel. | |
painel_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Texto da área de conteúdo do painel. | |
painel_padding | inteiro | 0..400 | Respiro interno do painel em px. |
Cada entrada de acordeao.itens[]:
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
titulo | texto | ≤200 | Pergunta/título do painel (obrigatório). | |
aberto | booleano | true / false | Painel aberto de início. Com um_por_vez, no máximo um. | |
itens | lista de itens aninhados | ≤20 · tipos: titulo, texto, imagem, botao, tags, links, cartoes, redes, menu, video, divisor, espacador, icone, selo, contador, marca | Até 20 painéis. Cada um: titulo (obrigatório, não vazio), aberto e itens aninhados. |
redes
Ícones de redes sociais (Instagram, WhatsApp...) com link.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
itens | lista de objeto | ≤50 | Até 50 redes. | |
tamanho | enum | p · m · g | Tamanho dos ícones: p, m ou g. | |
cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do(s) ícone(s). Vazio herda a cor do texto. | |
icone_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do INÍCIO: nenhum, circulo, quadrado. | |
icone_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do início. | |
icone_fundo_tamanho | inteiro | 24..72 | Lado do contêiner em px (24..72). | |
icone_dir_fundo | enum | nenhum · circulo · quadrado | Contêiner atrás do ícone do FIM: nenhum, circulo, quadrado. | |
icone_dir_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do contêiner do ícone do fim. | |
icone_dir_fundo_tamanho | inteiro | 24..72 | Lado do contêiner do fim em px (24..72). |
Cada entrada de redes.itens[]:
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
rede | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | Nome da rede: instagram, x, facebook, linkedin, youtube, tiktok, whatsapp, telegram, email, site, github, pinterest. Outro nome vira o ícone genérico de link. | |
url | url de link | ≤2048 · http/https/mailto/tel, #ancora, /caminho | Destino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>). | |
url_rastreio | objeto ou null | Objeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido. |
menu
Menu de navegação (links de texto), horizontal ou vertical; pode colapsar no celular.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
itens | lista de objeto | ≤50 | Até 50 links. | |
orientacao | enum | horizontal · vertical | horizontal | horizontal (padrão) ou vertical. |
colapsar_celular | booleano | true / false | false | No celular o menu vira um botão que abre/fecha. |
Cada entrada de menu.itens[]:
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
rotulo | texto | ≤300 | Texto do link do menu. | |
url | url de link | ≤2048 · http/https/mailto/tel, #ancora, /caminho | Destino do link: http, https, mailto, tel, #ancora ou /caminho (nunca //). Vazio = sem link (o botão sai como <span>). | |
url_rastreio | objeto ou null | Objeto do encurtador de links (link_id, codigo, destino...). Normalmente gerenciado pelo editor; ao importar para outra conta é removido. |
formulario
Embute um formulário do Asender (campos reais, anti-spam e captura de lead).
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
form_id | id | ^[A-Za-z0-9_-]{1,64}$ ou vazio | Id do formulário (criado em /v1/formularios). Vazio = "ainda não configurado" (nada é desenhado). Id de outra conta é removido na importação. | |
rotulo | texto | ≤300 | Texto do botão de envio do formulário embutido (sobrepõe o do formulário). |
video
Vídeo incorporado (<iframe>) a partir de uma URL de embed.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
url | url de link | ≤2048 · http/https/mailto/tel, #ancora, /caminho | URL de EMBED (ex.: https://www.youtube.com/embed/<id>). Mesma regra de href (http/https/mailto/tel, #âncora, /caminho). Sem irmã url_rastreio. | |
titulo | texto | ≤300 | Título acessível do <iframe>. |
divisor
Linha divisória horizontal.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor da linha. | |
espessura | inteiro | 1..20 | Espessura da linha em px (1..20). | |
estilo | enum | solida · tracejada · pontilhada | Objeto de estilo (ver a tabela do contexto). | |
largura | inteiro | 10..100 | Largura da linha em % da coluna (10..100). |
espacador
Espaço vertical em branco.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
altura | inteiro | 0..400 | Altura do espaço em px (0..400). | |
altura_celular | inteiro | 0..400 | Altura do espaço no celular, em px. |
icone
Um ícone avulso (kit de ícones ou ícone clássico).
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
nome | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | Rótulo livre, só para a árvore do editor. | |
tamanho | inteiro | 12..256 | Lado do ícone em px (12..256). | |
cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | Cor do ícone. |
selo
Selo (pílula de destaque com um texto curto).
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
texto | texto | ≤300 | Texto do selo. |
contador
Contagem regressiva até um prazo.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
prazo | texto | ≤64 | Data-hora final em RFC 3339 (ex.: 2026-12-31T23:59:00-03:00). Ilegível = só o rótulo. | |
rotulo | texto | ≤300 | Texto que acompanha a contagem. |
marca
Logo e/ou nome da conta (vindos do kit de marca efetivo); útil em cabeçalhos.
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
mostrar_logo | booleano | true / false | true | Mostra o logo do kit de marca (padrão true). |
mostrar_nome | booleano | true / false | true | Mostra o nome da conta (padrão true). |
altura_logo | inteiro | 16..200 | Altura do logo em px (16..200). |
html
HTML cru. PRIVILEGIADO: só quem tem o nível elevado grava; sem ele a escrita é barrada (403).
| Prop | Tipo | Valores / faixa | Padrão | Descrição |
|---|---|---|---|---|
html | texto | ≤200000 | HTML cru (até 200000 caracteres). Privilegiado; exige nível elevado. |
3.6 Campos visuais compartilhados
Os mesmos nomes aparecem em vários tipos e têm o mesmo significado. A tabela abaixo é gerada: lista todo campo presente em três ou mais tipos.
| Campo | Tipo | Valores / faixa | Presente em |
|---|---|---|---|
alinhamento | enum | herdar · inicio · centro · fim | item |
alinhamento | enum | inicio · centro · fim | tags |
alinhamento | enum | inicio · centro · fim · esticar | abas |
cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | imagem, botao, tags, links, cartoes, abas, acordeao |
cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | botao, tags, links, cartoes, redes |
cor_icone_inicio | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | botao, tags, links |
cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | pagina, secao, coluna, item, botao, tags, links, cartoes, abas, acordeao |
espacamento | inteiro | 0..6 | titulo, texto, botao |
fonte_peso | enum | 400 · 500 · 600 · 700 · 800 | botao, tags, links, cartoes, abas, acordeao |
fonte_tamanho | inteiro | 10..72 | botao, tags, links, cartoes, abas, acordeao |
gap | inteiro | 0..400 | coluna, tags, cartoes, abas, acordeao |
hover_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | botao, tags, links, cartoes, abas, acordeao |
hover_cor_borda | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | botao, tags, links, cartoes |
hover_cor_icone | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | botao, tags, links, cartoes |
hover_cor_texto | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | botao, tags, links, cartoes, abas, acordeao |
icone | nome (ícone/rede) | ^[a-z0-9_-]{1,40}$ ou vazio | botao, tags, links, cartoes |
icone_dir_fundo | enum | nenhum · circulo · quadrado | botao, tags, links, cartoes, redes |
icone_dir_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | botao, tags, links, cartoes, redes |
icone_dir_fundo_tamanho | inteiro | 24..72 | botao, tags, links, cartoes, redes |
icone_dir_img | url de mídia | ≤2048 · http(s) com host ou /caminho | botao, tags, links |
icone_fundo | enum | nenhum · circulo · quadrado | botao, tags, links, cartoes, redes |
icone_fundo_cor | cor ou vazio | #rrggbb, #rrggbbaa ou token (ver Cores) | botao, tags, links, cartoes, redes |
icone_fundo_tamanho | inteiro | 24..72 | botao, tags, links, cartoes, redes |
icone_img | url de mídia | ≤2048 · http(s) com host ou /caminho | botao, tags, links |
imagem | url de mídia | ≤2048 · http(s) com host ou /caminho | botao, tags, links |
imagem | objeto | fundo | |
imagem_alt | texto | ≤300 | botao, tags, links |
imagem_forma | enum | quadrada · arredondada · circulo | botao, tags, links |
imagem_posicao | enum | inicio · fim · topo | botao, tags, links |
imagem_tamanho | enum | p · m · g | botao, tags, links |
largura | enum | contida · total | secao |
largura | inteiro | 0..12 | coluna |
largura | inteiro | 16..2400 | imagem |
largura | enum | total · conteudo | links |
largura | inteiro | 10..100 | divisor |
largura | inteiro | 0..20 | borda |
nova_aba | booleano | true / false | botao, tags, links, cartoes |
padding_h | inteiro | 0..400 | botao, tags, links, cartoes, abas, acordeao |
padding_v | inteiro | 0..400 | botao, tags, links, cartoes, abas, acordeao |
raio | inteiro | 0..200 | secao, coluna, imagem, botao, tags, links, cartoes, abas, acordeao |
raio_inf_dir | inteiro | 0..200 | secao, coluna, imagem, botao, cartoes |
raio_inf_esq | inteiro | 0..200 | secao, coluna, imagem, botao, cartoes |
raio_sup_dir | inteiro | 0..200 | secao, coluna, imagem, botao, cartoes |
raio_sup_esq | inteiro | 0..200 | secao, coluna, imagem, botao, cartoes |
sombra | enum | nenhuma · suave · media · forte | secao, coluna |
sombra | enum | nenhuma · leve · forte | imagem, botao, tags, links, cartoes |
tamanho | const ou inteiro | 0 ou 8..96 | pagina |
tamanho | enum | auto · p · m · g · gg | titulo, texto |
tamanho | enum | p · m · g | botao, links, redes |
tamanho | inteiro | 12..256 | icone |
tamanho | enum | cobrir · conter · auto | fundo |
tamanho_icone | inteiro | 10..48 | tags |
tamanho_icone | inteiro | 12..64 | links, cartoes |
transformar | enum | nenhum · caixa_alta · caixa_baixa · capitalizar | titulo, texto, botao |
url_rastreio | objeto ou null | botao, tags, links, cartoes, redes, menu | |
vidro | booleano | true / false | botao, tags, links, cartoes |
vidro_desfoque | inteiro | 0..40 | botao, tags, links, cartoes |
vidro_opacidade | inteiro | 0..100 | botao, tags, links, cartoes |
vidro_saturacao | inteiro | 100..200 | botao, tags, links, cartoes |
Como pensar neles:
- Cores. Hex
#rrggbb/#rrggbbaaou um token (acento,texto,suave,fundo,superficie,borda,transparente). Prefira tokens quando quiser que a página siga o kit de marca; use hex para cores fixas. Nuncared,rgb(...),#fffou texto livre. - Vidro líquido.
vidro: trueliga fundo translúcido combackdrop-filter. Ajuste comvidro_opacidade(0..100, padrão 30),vidro_desfoque(0..40 px, padrão 14) evidro_saturacao(100..200, padrão 160). Vale embotao,links,tagsecartoes(item e entradas). Não existe emtitulo,textoetc. (prop desconhecida). - Raio.
raio(0..200) arredonda todos os cantos;raio_sup_esq,raio_sup_dir,raio_inf_dir,raio_inf_esqfixam cada canto (sentido horário). Com ao menos um canto presente, o canto ausente usaraio. Emimagem,raiopresente venceforma. - Sombra. Caixas (seção, coluna, conteúdo):
nenhuma,suave,media,forte. Itens (imagem, botão, entradas, cartões):nenhuma,leve,forte. Os dois vocabulários não se misturam. - Espaçamento.
paddingemargemsão objetos{topo, direita, base, esquerda}em px (0..400);padding_v/padding_hsão o respiro interno de botões/entradas;gapé o espaço entre elementos. Lado omitido = 0. - Tipografia.
transformar(nenhum,caixa_alta,caixa_baixa,capitalizar) eespacamento(0..6 px entre letras) emtitulo,textoebotao;fonte_peso(texto:"400".."800") efonte_tamanho(10..72 px) em botões e entradas;tamanho(p/m/g/gg) em título e texto. Fontes de página: seção 3.3. - Ícones de kit.
iconeeicone_dirsão nomes, não URLs: clássicos (raio,escudo,coracao,estrela,check,seta,relogio,calendario,telefone,local,usuario,carrinho,presente,chat,cadeado,foguete,grafico,mais), redes (instagram,x,facebook,linkedin,youtube,tiktok,whatsapp,telegram,email,site,github,pinterest) e os kits: Lucide sem prefixo (mountain,arrow-right...; 1942 ícones), Tablertabler-<nome>(5826) etabler-f-<nome>(preenchidos), Phosphorph-<nome>(1434) e Heroiconshero-<nome>/hero-s-<nome>(648). Os nomes são os dos kits originais em minúsculas e com hífen. Um nome que o renderer não conhece não é erro: o ícone some (emlinksvira o ícone genérico de link), então confira o nome. - Ícone de mídia (personalizado).
icone_img/icone_dir_imgaceitam uma URL de mídia e vencem o glifoicone. Vira um<img>; as props de cor de ícone não se aplicam. - Contêiner do ícone.
icone_fundo/icone_dir_fundo(circuloouquadrado) desenham uma forma atrás do ícone, com_core_tamanho(24..72 px). Emredessó vale no item, não nas entradas. - Imagem dentro do botão.
imagem,imagem_alt,imagem_posicao,imagem_tamanho,imagem_formaembotaoe nas entradas delinks/tags. - Moldura da imagem. Em
imagem:borda,cor_borda,sombra,cor_fundoepadding(0..40) entre a borda e a foto. - Subir.
estilo.subir(0..200 px) puxa o item sobre o anterior (margem de topo negativa que substitui a margem de topo). - Camadas de fundo.
fundo.cor_basefica sob as demais camadas;fundo.sobreposicaoé uma película por cima (cor ou degradê, nunca os dois, comopacidade0..100) e vale sobre cor, degradê e imagem. Exemplo: imagem de fundo com película escura:
{ "tipo": "imagem", "cor_base": "#111111",
"imagem": { "url": "https://exemplo.test/capa.jpg", "tamanho": "cobrir", "posicao": "centro" },
"sobreposicao": { "gradiente": { "de": "#000000", "para": "transparente", "angulo": 180 }, "opacidade": 60 } }
3.7 Marcação inline em titulo.texto e texto.texto
Dentro do texto de um título ou parágrafo (e só nesses dois campos) valem duas marcações. Todo o resto é texto: HTML não é interpretado (< e & são escapados), então não envie tags.
| Marcação | Resultado |
|---|---|
[rótulo](https://exemplo.test) | link <a rel="noopener noreferrer">. Endereço permitido: http://, https://, mailto:, tel: |
[[trecho]] | trecho em destaque (span.pg-destaque); a cor vem de destaque_cor |
Regras: sem aninhamento; o rótulo não pode ter [ ou ]; o endereço vai até o primeiro ), sem espaço, aspas, <, >, \ ou crase, até 2048 caracteres; em http(s) o que vem depois de // não pode começar com /. Link com endereço não permitido reprova a validação (ErrPropInvalida, apontando ...props.texto); não use javascript:, data: nem caminho relativo na marcação (use um item botao ou links para isso). Quebras de linha são mantidas.
{ "id": "t1", "tipo": "titulo",
"props": { "texto": "Organize seus pedidos sem [[planilhas]]", "nivel": 1, "destaque_cor": "acento" } }
{ "id": "t2", "tipo": "texto",
"props": { "texto": "Veja o [portfólio](https://exemplo.test/portfolio) ou escreva para [oi@exemplo.test](mailto:oi@exemplo.test)." } }
3.8 Formulários embutidos
O item formulario renderiza um formulário real do Asender (campos, anti-spam, captura de lead). Ele referencia um formulário existente pelo form_id; a ordem é:
- Crie o formulário:
POST /v1/formularios(sessão ou API keyforms:write):
curl -sS -X POST "$API/v1/formularios" "${H[@]}" -d '{
"nome": "Contato do site",
"external_id": "site-contato",
"campos": [
{ "nome": "nome", "rotulo": "Nome", "tipo": "texto", "obrigatorio": true },
{ "nome": "email", "rotulo": "E-mail", "tipo": "email", "obrigatorio": true },
{ "nome": "mensagem", "rotulo": "Mensagem", "tipo": "texto_longo" }
],
"texto_botao": "Enviar",
"mensagem_pos_envio": "Recebemos, obrigado."
}'
# -> 201 { "id": "<form-id>", "external_id": "site-contato", ... }
- Use o
iddevolvido no item:{ "tipo": "formulario", "props": { "form_id": "<form-id>" } }. - Páginas publicadas mostram o formulário na hora; capturas viram leads no CRM. Fora de produção, use endereços
@exemplo.testem testes: nada sai para ninguém.
form_id vazio significa "ainda não configurado" (o item não desenha nada). Ao importar uma página para outra conta, form_id que a conta de destino não tem é zerado, com aviso. O tipo formulario não pode ficar dentro de abas/acordeão. Campos, destinos e envio de leads por chave: guia de Páginas.
3.9 Abas, acordeão e FAQ (JSON-LD)
abas e acordeao guardam os painéis em props.itens. Cada painel tem titulo (obrigatório, não vazio) e itens: objetos de item completos (id, tipo, props obrigatórios) dos tipos permitidos em painel (titulo, texto, imagem, botao, tags, links, cartoes, redes, menu, video, divisor, espacador, icone, selo, contador, marca). Nunca abas, acordeao, html, formulario (ErrEstruturaInvalida).
abas.abertaé o índice (0 = primeira) da aba aberta de início e tem de existir.acordeao.abertomarca painéis abertos; comum_por_vez: trueno máximo um.- Sem JavaScript todo o conteúdo fica visível; com JS há abas e sanfona acessíveis (WAI-ARIA, teclado).
- FAQ:
acordeaocomfaq: truegera um nóFAQPageno JSON-LD da página publicada. Cada painel é uma pergunta (titulo) e a resposta é o texto dos itenstexto/titulodo painel: precisa existir, ter até 4000 caracteres, e a página aceita no máximo 50 perguntas somadas.abasnão gera schema.org.
3.10 SEO e meta da página
O SEO não mora no documento: é uma rota própria, GET/PUT /v1/paginas/{id}/seo (sessão ou chave: pages:read / pages:write), e vale sem publicar nova versão (na próxima resolução do runtime). Campos: titulo (até 120), descricao (até 320), canonical_url, noindex, og_titulo, og_descricao, og_imagem_url (só https), og_imagem_alt, og_imagem_largura/og_imagem_altura (juntas, 1..10000). Vazio volta ao padrão do runtime (título da página, primeiro texto, primeira imagem).
curl -sS -X PUT "$API/v1/paginas/<pagina-id>/seo" "${H[@]}" -d '{
"titulo": "Lançamento | Minha marca", "descricao": "Conheça a novidade de 2026.",
"og_imagem_url": "https://exemplo.test/og.jpg", "og_imagem_alt": "Capa do lançamento",
"og_imagem_largura": 1200, "og_imagem_altura": 630
}'
PUT substitui todos os campos de uma vez: leia com GET, altere e devolva.
4. Validação e erros comuns
O servidor valida tudo na escrita (POST /v1/paginas, POST /v1/paginas/{id}/versoes, importação). O rascunho (seção 6.2) só confere a forma, de propósito.
4.1 O formato do erro
Recusa de documento v2 = 422 com três campos:
{
"erro": "documento: prop de item inválida: secoes[0].colunas[0].itens[0].props.url",
"codigo": "ErrPropInvalida",
"caminho": "secoes[0].colunas[0].itens[0].props.url"
}
caminho aponta o nó culpado (índices de array entre colchetes); sem nó, vale versao, secoes ou documento. O servidor devolve o primeiro erro; corrija e reenvie até passar. Os códigos:
codigo | Quando | Como corrigir |
|---|---|---|
ErrMalformado | JSON inválido, campo desconhecido em estrutura/estilo, ou lixo depois do objeto. | Remova o campo citado; confira vírgulas e aspas. Só use os campos das tabelas. |
ErrVersao | versao diferente de 2. | Envie "versao": 2 (número, não texto). |
ErrSemSecoes | secoes vazia ou ausente. | Inclua ao menos uma seção. |
ErrLimite | Algum teto foi excedido (itens, colunas, entradas de lista, FAQ...). | Reduza ou divida em seções; veja a tabela de limites. |
ErrSemColunas | Seção sem coluna. | Toda seção precisa de 1..12 colunas. |
ErrID | id com forma inválida ou repetido. | Use ^[A-Za-z0-9_-]{1,64}$ e ids ÚNICOS no documento inteiro (seção, coluna, item e itens de painel). |
ErrAncora | ancora inválida ou repetida. | Use ^[a-z][a-z0-9-]{0,63}$, única na página. |
ErrTipoDesconhecido | tipo de item fora da lista. | Use um dos 20 tipos (tabela de tipos). |
ErrPropInvalida | Prop inexistente no tipo, valor fora da faixa/enum, URL fora da allowlist, cor inválida, link da marcação recusado... | Leia o caminho; confira a tabela do tipo (nome, tipo, faixa). |
ErrEstiloInvalido | Valor de estilo inválido (fundo, borda, raio, fonte fora da allowlist, cor, faixa...). | Leia o caminho; confira as tabelas de estilo. |
ErrEstruturaInvalida | Valor estrutural inválido (enum de comportamento/dispositivo, peso de coluna, tipo proibido dentro de painel...). | Leia o caminho; dentro de abas/acordeão só entram tipos permitidos (nunca abas, acordeao, html, formulario). |
Outros status das rotas de página: 400 corpo inválido (campo desconhecido no corpo da requisição, como tenant_id, também é 400), 401 sem credencial (ou rota que não aceita chave), 403 item html sem nível ou chave sem escopo, 404 página inexistente ou de outra conta, 409 endereço em uso, 413 corpo grande demais, 422 regra de negócio (domínio não verificado, título vazio).
4.2 Regras que valem para todo valor
- Campo desconhecido é recusado em todo nível (documento, seção, coluna, item, estilo, props e entradas de lista). O erro nomeia o campo.
- Texto vale em code points, não bytes nem UTF-16: os limites
≤Ncontam caracteres. - Inteiros são inteiros.
1.5,"12"etrueno lugar de número sãoErrPropInvalida. - Cores só nos formatos do tipo
cor(seção 3.4). Nada de nome de cor CSS ou função. - URL de link (
url,link,menu.itens[].url,video.url): vazia,#ancora(^[a-z][a-z0-9-]{0,63}$),/caminho(nunca//) ou esquemahttp,https,mailto,tel; até 2048 caracteres; sem caractere de controle.javascript:,data:,vbscript:e protocolo relativo//hostsão recusados. - URL de mídia (
imagem.url,fundo.imagem.url,icone_img,img,imagem...): vazia,/caminho(nunca//) ouhttp(s)://host/...; sem aspas, apóstrofo, parênteses, barra invertida, espaço,<,>nem controle. Isso existe porque a URL vai para dentro de umurl("...")de CSS. - Valores fechados em CSS. Não existe estilo livre: tudo é enum, faixa numérica ou cor validada. Tentativas de injeção (
red;}body{...},</style><script>,url(...)) caem emErrPropInvalida/ErrEstiloInvalido. htmlé privilegiado: o itemhtmlexige nível elevado (403sem ele), e a página continua editável sem o item.<prop>_rastreio(ex.:url_rastreio) é o objeto do encurtador e só existe ao lado de uma prop de URL de link; não o envie (o editor o gerencia). Emvideonão existe.- Limites. Veja a tabela 3.1; estourar é
ErrLimite.
4.3 Exemplos reais do corpus de testes
Estes são casos do corpus hostil que os três validadores (Go, TS e schema) rodam em CI (asender_docs/contratos/fixtures/pages-v1-v2/validacao.json, centenas de casos). Cada um mostra o código e o fragmento enviado:
Caso (corpus validacao.json) | codigo | O que foi enviado (fragmento) |
|---|---|---|
versao-1 | ErrVersao | {"versao":1,"secoes":[{"id":"a","colunas":[{"id":"ac","itens":[]}]}]} |
sem-secoes | ErrSemSecoes | {"versao":2,"secoes":[]} |
treze-colunas | ErrLimite | {"versao":2,"secoes":[{"id":"a","colunas":[{"id":"c0","itens":[]},{"id":"c1","itens":[]},{"id":"c2","itens":[]},{"id":"c3","itens":[]},{"id":"c4","itens":[]},{"id":"c5","itens":[]},{"id":"c6","itens":[]},{"id":"c7","itens":[]},{"id":"c8"... |
id-repetido | ErrID | {"id":"a","tipo":"texto","props":{}} |
id-com-espaco | ErrID | {"versao":2,"secoes":[{"id":"a b","colunas":[{"id":"a bc","itens":[]}]}]} |
ancora-repetida | ErrAncora | {"versao":2,"secoes":[{"id":"a","colunas":[{"id":"ac","itens":[]}],"ancora":"x"},{"id":"b","colunas":[{"id":"bc","itens":[]}],"ancora":"x"}]} |
tipo-desconhecido | ErrTipoDesconhecido | {"id":"b","tipo":"hero","props":{}} |
prop-desconhecida | ErrPropInvalida | {"id":"b","tipo":"titulo","props":{"style":"color:red"}} |
url-javascript | ErrPropInvalida | {"id":"b","tipo":"botao","props":{"url":"javascript:alert(1)"}} |
url-protocolo-relativo | ErrPropInvalida | {"id":"b","tipo":"botao","props":{"url":"//evil.test"}} |
midia-data | ErrPropInvalida | {"id":"b","tipo":"imagem","props":{"url":"data:image/png;base64,AAAA"}} |
cor-livre-prop | ErrPropInvalida | {"id":"b","tipo":"botao","props":{"cor":"red;x:y"}} |
botao-cor-icone-style | ErrPropInvalida | {"id":"b","tipo":"botao","props":{"rotulo":"Ir","cor_icone":"</style><script>"}} |
botao-vidro-opacidade-101 | ErrPropInvalida | {"id":"b","tipo":"botao","props":{"rotulo":"Ir","vidro_opacidade":101}} |
titulo-nao-aceita-vidro | ErrPropInvalida | {"id":"b","tipo":"titulo","props":{"texto":"x","vidro":true}} |
l4-sobreposicao-cor-e-gradiente | ErrEstiloInvalido | {"versao":2,"secoes":[{"id":"a","estilo":{"fundo":{"tipo":"nenhum","sobreposicao":{"cor":"#000000","gradiente":{"tipo":"linear","de":"#ffffff","para":"transparente","angulo":90},"opacidade":50}}},"colunas":[{"id":"ac","itens":[]}]}]} |
pagina-fonte-titulos-nome-do-kit | ErrEstiloInvalido | {"versao":2,"estilo":{"fonte_titulos":"Open Sans"},"secoes":[{"id":"a","colunas":[{"id":"ac","itens":[]}]}]} |
pagina-fonte-titulos-injecao-css | ErrEstiloInvalido | {"versao":2,"estilo":{"fonte_titulos":"inter;}body{display:none}"},"secoes":[{"id":"a","colunas":[{"id":"ac","itens":[]}]}]} |
abas-item-aninhado-abas | ErrEstruturaInvalida | {"id":"ab","tipo":"abas","props":{"itens":[{"titulo":"A","itens":[{"id":"n","tipo":"abas","props":{}}]}]}} |
abas-item-aninhado-formulario | ErrEstruturaInvalida | {"id":"ab","tipo":"abas","props":{"itens":[{"titulo":"A","itens":[{"id":"n","tipo":"formulario","props":{"form_id":"f1"}}]}]}} |
acordeao-faq-sem-resposta | ErrPropInvalida | {"id":"ac1","tipo":"acordeao","props":{"faq":true,"itens":[{"titulo":"Pergunta?","itens":[{"id":"b","tipo":"botao","props":{"rotulo":"x"}}]}]}} |
acordeao-dois-abertos-um-por-vez | ErrPropInvalida | {"id":"ac1","tipo":"acordeao","props":{"um_por_vez":true,"itens":[{"titulo":"A","itens":[],"aberto":true},{"titulo":"B","itens":[],"aberto":true}]}} |
l7-titulo-href-javascript | ErrPropInvalida | {"id":"b","tipo":"titulo","props":{"texto":"[x](javascript:alert(1))"}} |
l3-subir-201 | ErrEstiloInvalido | {"id":"b","tipo":"texto","props":{"texto":"a"},"estilo":{"subir":201}} |
lista-longa | ErrLimite | {"id":"b","tipo":"menu","props":{"itens":[{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},{"rotulo":"x"},... |
estilo-campo-desconhecido | ErrMalformado | {"id":"i1","tipo":"marca","props":{"mostrar_logo":true,"mostrar_nome":false,"altura_logo":40}} |
4.4 Como consertar, por classe
| Sintoma | Causa provável | Conserto |
|---|---|---|
ErrMalformado | campo inventado ou vírgula sobrando | remova o campo; releia a tabela do nível |
ErrPropInvalida com caminho em props.<x> | x não existe no tipo, ou valor fora da faixa/enum | confira nome, tipo e faixa na tabela do tipo |
ErrPropInvalida em props.texto | link da marcação [x](y) com endereço não permitido | use https://, mailto: ou tel: |
ErrEstiloInvalido | cor, raio, fonte, sombra ou fundo inválido | veja 3.3/3.4; fonte só da allowlist |
ErrID | id repetido (inclusive entre seção e item) | gere ids únicos no documento inteiro |
ErrEstruturaInvalida em painel | abas/acordeao/html/formulario dentro de painel | tire o item do painel |
ErrLimite | lista, colunas ou FAQ acima do teto | divida em seções ou reduza |
403 | item html sem nível | remova o item html |
4.5 O laço de validação do agente
- Gere o JSON.
- Valide localmente contra o schema (qualquer validador JSON Schema 2020-12). O schema não confere ids únicos, âncoras únicas, o teto de 1000 itens, as regras de painel, o limite de FAQ nem a marcação inline; esses o servidor confere (confira ids e âncoras você mesmo).
- Envie (
POST /v1/paginasouPOST /v1/paginas/{id}/versoes). 422? Leiacodigo+caminho, corrija somente aquele nó e volte ao passo 3. Não reescreva o documento inteiro a cada erro.201? Confira a página renderizada (aurl_publicasó abre a versão publicada) antes de publicar.
5. Mídia
Uma imagem entra no documento por URL. Dois tipos servem:
- Galeria da conta (recomendado). Envie o arquivo e use o
urldevolvido:
# upload (multipart, campo "arquivo"); 201 novo, 200 se o MESMO conteúdo já existia (dedup por hash)
curl -sS -X POST "$API/v1/midias" -H "Authorization: Bearer $KEY" \
-F 'arquivo=@capa.jpg'
# -> { "id":"<midia-id>", "nome":"capa.jpg", "mime":"image/jpeg", "tamanho":123456,
# "url":"https://.../v1/public/midias/<midia-id>", ... }
# importar por URL (o servidor baixa, com defesa contra SSRF)
curl -sS -X POST "$API/v1/midias/de-url" "${H[@]}" -d '{ "url": "https://exemplo.test/foto.png", "nome": "foto" }'
Use exatamente o campo url da resposta (.../v1/public/midias/<id>) em imagem.url, fundo.imagem.url, icone_img, cartoes.itens[].img etc. A leitura é pública e anônima (a página publicada precisa dela). Variantes redimensionadas: .../v1/public/midias/<id>/w/<largura> (o renderer usa no srcset). Só imagens (JPG, PNG, GIF, WebP, AVIF, SVG; o tipo é decidido pelo conteúdo, não pelo nome; SVG é sanitizado; antivírus se configurado). GET /v1/midias lista a galeria; DELETE /v1/midias/{id} apaga (não apague mídia que uma página usa).
- Externa
https://...: aceita pelo validador, mas a página passa a depender do host de terceiros (some se ele apagar). Para algo que importa, suba para a galeria.
Vídeo não é mídia da galeria: o item video recebe uma URL de embed (ex.: https://www.youtube.com/embed/<id>).
Cópia na importação. POST /v1/paginas/importar e a galeria de templates baixam de novo cada imagem referenciada (imagem de item, galeria, fundo de seção/coluna/página, *_img, cartoes[].img, imagem de botão...) para a galeria da conta de destino e trocam as URLs; apagar a origem depois não quebra o destino. url de link e de botão nunca é baixada. O que não puder ser copiado mantém a URL original e aparece no relatório (mantido_original + motivo). Tetos: 10 MB por arquivo, 50 MB por importação, 60 URLs únicas.
6. Fluxos de trabalho
6.1 Criar do zero
- (Opcional)
POST /v1/formulariosse a página tem formulário (seção 3.8). - Suba as imagens (seção 5) e anote os
url. - Monte o documento (receitas na seção 7) e valide.
POST /v1/paginascomtitulo,slug(^[a-z0-9]+(-[a-z0-9]+)*$), opcionaldominio, e otemplate. Resposta201trazid,url_publica,ultima_versao: 1,versao_publicada: 0.PUT /v1/paginas/{id}/seo(opcional).- Revisão humana (a página ainda não está no ar).
POST /v1/paginas/{id}/publicarcom{"versao": 1}.
6.2 Editar com segurança (rascunho, versão, publicação)
Semântica. Uma página tem versões imutáveis (numeradas, só crescem), um ponteiro de publicada e, no máximo, um rascunho: o auto-save do editor, uma cópia de trabalho que não é versão e não está no ar. Publicar só move o ponteiro; versões antigas continuam e publicar uma delas de novo é o rollback.
# 1) ler o estado: a última versão (ou ?versao=N) e os contadores
curl -sS "$API/v1/paginas/<id>" "${H[@]}"
# -> { "pagina": {..., "ultima_versao": 3, "versao_publicada": 2, "url_publica": "..."},
# "template": { "versao": 2, ... }, "versao": 3 }
# 2) existe rascunho de alguém? 204 = não; 200 = sim, com o instante da última gravação
curl -sS -i "$API/v1/paginas/<id>/rascunho" "${H[@]}"
# -> 200 { "template": {...}, "rascunho_em": "2026-10-09T12:00:00.123456Z" } | 204
# 3) gravar o SEU rascunho com controle de concorrência
curl -sS -X PUT "$API/v1/paginas/<id>/rascunho?base=<rascunho_em lido, ou vazio se era 204>" "${H[@]}" \
-d '{ "template": { "versao": 2, "secoes": [ ... ] } }'
# -> 200 { "rascunho_em": "..." }
# -> 409 { "erro":"o rascunho foi alterado em outra aba", "codigo":"RascunhoConflito",
# "rascunho": { "template": {...do servidor...}, "rascunho_em": "..." } }
# 4) promover a versão (aqui o documento é validado por inteiro: 422 se inválido)
curl -sS -X POST "$API/v1/paginas/<id>/versoes" "${H[@]}" -d '{ "template": { ... } }' # -> 201 {"versao": 4}
# 5) publicar a versão pelo NÚMERO
curl -sS -X POST "$API/v1/paginas/<id>/publicar" "${H[@]}" -d '{ "versao": 4 }' # -> 200
?base=ausente grava sem condição (clientes antigos);?base=vazio diz "eu esperava que não houvesse rascunho";?base=<rascunho_em>diz "eu vi esta gravação". Se outra gravação aconteceu no meio, o servidor responde409com o rascunho dele e não sobrescreve nada: mantenha os dois lados, mescle e tente de novo com o novorascunho_em.- O rascunho só confere a forma (objeto JSON até 512 KiB); a validação completa acontece em
POST /versoes. Salvar versão não apaga o rascunho (o editor humano é quem o descarta,DELETE /v1/paginas/{id}/rascunho). - Cada
POST /versoescria a versão seguinte; ninguém sobrescreve a versão de outro. Se duas pessoas salvam ao mesmo tempo, as duas versões existem.
Nunca perca trabalho humano (regras para o agente):
- Nunca sobrescreva página publicada sem ordem expressa. Para alterar uma página que está no ar, trabalhe em versão nova (não publique), ou duplique (
6.6), edite a cópia e peça revisão. - Rascunho presente = trabalho humano em andamento. Se
GET .../rascunhodevolveu200, não o substitua: parta dele (ele é o estado mais novo), grave com?base=<rascunho_em>, ou pare e informe. Nunca useDELETE .../rascunhopor conta própria. - Publique pelo número (
{"versao": N}), a versão que você acabou de salvar e validar; não publique "a última" às cegas (uma pessoa pode ter salvado outra no meio). - Para desfazer, publique a versão anterior (
versao_publicadaantes de você mexer). - Conflito (
409)? Leia o corpo, preserve os dois lados e decida com o humano; nunca force. - Guarde o
ultima_versao/versao_publicadaque você leu e confira antes de publicar.
6.3 Importar e exportar (envelopes)
O arquivo exportado pelo editor (e os 15 link-bios de referência em asender_archive/link-bios/) tem este envelope (asender_pages_template: 2, até 256 KB):
{
"asender_pages_template": 2,
"nome": "Minha landing",
"descricao": "opcional",
"seo": { "titulo": "Minha landing", "descricao": "...", "og_titulo": "..." },
"template": { "versao": 2, "secoes": [ ... ] }
}
seo é opcional e não leva canonical_url. Para importar por API, desembrulhe o envelope e chame POST /v1/paginas/importar, que valida como a criação, copia a mídia para a conta, cria a página despublicada e grava o SEO:
curl -sS -X POST "$API/v1/paginas/importar" "${H[@]}" -d '{
"slug": "minha-landing", "titulo": "Minha landing",
"template": { "versao": 2, "secoes": [ ... ] },
"seo": { "titulo": "Minha landing" }
}'
# -> 201 { "pagina": {...}, "importacao": { "itens":[...], "avisos":[...], "copiadas":3, "ja_na_conta":0,
# "mantidas":0, "copia_disponivel":true, "seo_aplicado":true } }
Se alguma imagem não pôde ser copiada, POST /v1/paginas/{id}/midias/copiar tenta de novo (grava versão nova só se algo mudou). 409 se o endereço (slug + domínio) já existe (checado antes de copiar). Para exportar: GET /v1/paginas/{id} e monte o envelope com o template.
6.4 Ações em massa
POST /v1/paginas/lote (sessão): publicar, despublicar, duplicar, mudar_dominio, até 100 páginas por chamada, resultado por página (sem tudo-ou-nada), simular: true para ver o efeito sem escrever. Detalhes e política de rascunho (pular / publicar_salva) no guia de Páginas.
6.5 Mudar o domínio (301 do endereço antigo)
PUT /v1/paginas/{id}/dominio com {"dominio_id": "...", "caminho": "novo-slug"} (sessão ou API key pages:write; dominio_id: "" = host da plataforma, caminho: "" mantém o slug). Se a página já esteve no ar, o endereço antigo passa a responder 301 (308 para métodos que não são GET/HEAD) para o novo, preservando a query string; repetir o pedido é idempotente. 409 com motivo: caminho_em_uso ou pagina_inicial; 422 com dominio_nao_verificado ou caminho_invalido. Domínio próprio exige posse verificada (TXT) antes de qualquer uso.
6.6 Duplicar
POST /v1/paginas/lote com {"acao":"duplicar","ids":["<id>"]} cria uma cópia despublicada (slug com -copia). É a forma segura de iterar sobre uma página que está no ar: edite a cópia, revise, publique a cópia e, se for o caso, troque os endereços com PUT .../dominio.
6.7 O que a API não faz
Não existe exclusão de página nem exclusão em massa, nem listagem de versões (use ultima_versao e GET /v1/paginas/{id}?versao=N). Páginas v1 antigas continuam lidas, mas o conteúdo novo deve ser v2.
7. Receitas completas
Todas validam no schema, no validador Go e no validador TS (teste de CI). As imagens usam o domínio de teste exemplo.test: troque pelos url da sua galeria. Os ids são só exemplos.
7.1 Link na bio
Uma coluna estreita, avatar, nome, bio com marcação inline, lista de links com vidro, redes sociais e rodapé; tema escuro com degradê e textura.
{
"versao": 2,
"estilo": {
"tema": "escuro",
"fonte_titulos": "montserrat",
"fonte_texto": "inter",
"fundo": {
"tipo": "gradiente",
"gradiente": {
"tipo": "linear",
"de": "#0f172a",
"para": "#1e293b",
"angulo": 160
}
},
"padrao": {
"tipo": "pontos",
"opacidade": 6,
"tamanho": 24
}
},
"secoes": [
{
"id": "bio",
"nome": "Perfil e links",
"estilo": {
"largura": "contida",
"largura_max": 480,
"padding": {
"topo": 48,
"direita": 16,
"base": 48,
"esquerda": 16
}
},
"colunas": [
{
"id": "bio-col",
"alinhamento_horizontal": "centro",
"gap": 16,
"itens": [
{
"id": "bio-foto",
"tipo": "imagem",
"props": {
"url": "https://exemplo.test/avatar.jpg",
"alt": "Foto da Ana Souza",
"forma": "circulo",
"largura": 112,
"proporcao": "1:1",
"borda": 3,
"cor_borda": "acento"
}
},
{
"id": "bio-nome",
"tipo": "titulo",
"props": {
"texto": "Ana Souza",
"nivel": 1,
"tamanho": "g"
},
"estilo": {
"alinhamento": "centro"
}
},
{
"id": "bio-resumo",
"tipo": "texto",
"props": {
"texto": "Designer de [[interfaces]] e marcas. Veja o [portfólio](https://exemplo.test/portfolio).",
"variante": "suave",
"destaque_cor": "acento"
},
"estilo": {
"alinhamento": "centro"
}
},
{
"id": "bio-links",
"tipo": "links",
"props": {
"estilo": "suave",
"tamanho": "g",
"efeito": "elevar",
"raio": 16,
"vidro": true,
"vidro_opacidade": 30,
"itens": [
{
"titulo": "Portfólio",
"texto": "Projetos recentes",
"url": "https://exemplo.test/portfolio",
"icone": "site",
"nova_aba": true,
"destaque": true
},
{
"titulo": "Agende uma conversa",
"url": "https://exemplo.test/agenda",
"icone": "calendario",
"icone_fundo": "circulo",
"cor": "acento",
"cor_texto": "#0f172a"
},
{
"titulo": "Fale no WhatsApp",
"url": "https://wa.me/5511900000000",
"icone": "whatsapp",
"nova_aba": true
},
{
"titulo": "E-mail",
"url": "mailto:ana@exemplo.test",
"icone": "email"
}
]
}
},
{
"id": "bio-redes",
"tipo": "redes",
"props": {
"tamanho": "m",
"itens": [
{
"rede": "instagram",
"url": "https://instagram.com/exemplo"
},
{
"rede": "linkedin",
"url": "https://linkedin.com/in/exemplo"
},
{
"rede": "github",
"url": "https://github.com/exemplo"
}
]
}
},
{
"id": "bio-rodape",
"tipo": "texto",
"props": {
"texto": "© 2026 Ana Souza",
"variante": "suave",
"tamanho": "p"
},
"estilo": {
"alinhamento": "centro",
"margem": {
"topo": 16
}
}
}
]
}
]
}
]
}
7.2 Landing com hero, cartões e FAQ
Cabeçalho fixo com menu e âncoras, hero em duas colunas, três cartões em grade, FAQ (acordeao com faq: true, gera JSON-LD) e chamada final.
{
"versao": 2,
"estilo": {
"tema": "claro",
"fonte_titulos": "poppins",
"fonte_texto": "inter",
"fundo": {
"tipo": "cor",
"cor": "#ffffff"
}
},
"secoes": [
{
"id": "topo",
"nome": "Cabeçalho",
"comportamento": "fixa_topo",
"estilo": {
"fundo": {
"tipo": "cor",
"cor": "#ffffff"
},
"borda": {
"largura": 1,
"cor": "borda",
"lados": [
"base"
]
},
"padding": {
"topo": 12,
"direita": 24,
"base": 12,
"esquerda": 24
}
},
"colunas": [
{
"id": "topo-marca",
"largura": 1,
"alinhamento_vertical": "centro",
"itens": [
{
"id": "topo-logo",
"tipo": "marca",
"props": {
"mostrar_logo": true,
"mostrar_nome": true,
"altura_logo": 32
}
}
]
},
{
"id": "topo-menu",
"largura": 2,
"alinhamento_vertical": "centro",
"alinhamento_horizontal": "fim",
"itens": [
{
"id": "topo-nav",
"tipo": "menu",
"props": {
"orientacao": "horizontal",
"colapsar_celular": true,
"itens": [
{
"rotulo": "Benefícios",
"url": "#beneficios"
},
{
"rotulo": "Perguntas",
"url": "#faq"
},
{
"rotulo": "Contato",
"url": "#contato"
}
]
}
}
]
}
]
},
{
"id": "hero",
"nome": "Hero",
"ancora": "inicio",
"layout_celular": "empilhar",
"estilo": {
"fundo": {
"tipo": "gradiente",
"gradiente": {
"tipo": "linear",
"de": "#eef2ff",
"para": "#ffffff",
"angulo": 180
}
},
"padding": {
"topo": 80,
"direita": 24,
"base": 80,
"esquerda": 24
},
"padding_celular": {
"topo": 40,
"direita": 16,
"base": 40,
"esquerda": 16
},
"alinhamento_vertical": "centro"
},
"colunas": [
{
"id": "hero-texto",
"largura": 6,
"gap": 20,
"itens": [
{
"id": "hero-selo",
"tipo": "selo",
"props": {
"texto": "Novo · versão 2"
}
},
{
"id": "hero-titulo",
"tipo": "titulo",
"props": {
"texto": "Organize seus pedidos sem [[planilhas]]",
"nivel": 1,
"tamanho": "gg",
"destaque_cor": "acento"
}
},
{
"id": "hero-sub",
"tipo": "texto",
"props": {
"texto": "Cadastre, acompanhe e entregue. Tudo em um só lugar, em minutos.",
"tamanho": "g",
"variante": "suave"
}
},
{
"id": "hero-cta",
"tipo": "botao",
"props": {
"rotulo": "Começar grátis",
"url": "#contato",
"variante": "solido",
"tamanho": "g",
"icone_dir": "seta"
}
},
{
"id": "hero-cta2",
"tipo": "botao",
"props": {
"rotulo": "Ver como funciona",
"url": "#beneficios",
"variante": "texto",
"tamanho": "m"
}
}
]
},
{
"id": "hero-imagem",
"largura": 6,
"alinhamento_vertical": "centro",
"itens": [
{
"id": "hero-foto",
"tipo": "imagem",
"props": {
"url": "https://exemplo.test/produto.jpg",
"alt": "Tela do aplicativo mostrando a lista de pedidos",
"forma": "arredondada",
"proporcao": "4:3",
"sombra": "forte"
}
}
]
}
]
},
{
"id": "beneficios",
"nome": "Benefícios",
"ancora": "beneficios",
"estilo": {
"padding": {
"topo": 64,
"direita": 24,
"base": 64,
"esquerda": 24
}
},
"colunas": [
{
"id": "ben-col",
"gap": 24,
"alinhamento_horizontal": "centro",
"itens": [
{
"id": "ben-titulo",
"tipo": "titulo",
"props": {
"texto": "Por que usar",
"nivel": 2
},
"estilo": {
"alinhamento": "centro"
}
},
{
"id": "ben-cartoes",
"tipo": "cartoes",
"props": {
"layout": "grade",
"colunas": 3,
"efeito": "elevar",
"raio": 16,
"sombra": "leve",
"alinhamento_texto": "inicio",
"icone_fundo": "circulo",
"itens": [
{
"icone": "raio",
"titulo": "Rápido",
"texto": "Cadastre um pedido em menos de dez segundos.",
"tag": "Produtividade"
},
{
"icone": "escudo",
"titulo": "Seguro",
"texto": "Seus dados ficam separados dos de outras contas.",
"tag": "Confiança"
},
{
"icone": "grafico",
"titulo": "Claro",
"texto": "Relatórios simples para decidir o que fazer amanhã.",
"tag": "Controle"
}
]
}
}
]
}
]
},
{
"id": "faq",
"nome": "Perguntas frequentes",
"ancora": "faq",
"estilo": {
"largura": "contida",
"largura_max": 760,
"padding": {
"topo": 64,
"direita": 24,
"base": 64,
"esquerda": 24
}
},
"colunas": [
{
"id": "faq-col",
"gap": 24,
"itens": [
{
"id": "faq-titulo",
"tipo": "titulo",
"props": {
"texto": "Perguntas frequentes",
"nivel": 2
}
},
{
"id": "faq-acordeao",
"tipo": "acordeao",
"props": {
"faq": true,
"um_por_vez": true,
"nivel": 3,
"estilo": "cartao",
"indicador": "seta",
"itens": [
{
"titulo": "Preciso instalar alguma coisa?",
"aberto": true,
"itens": [
{
"id": "faq-r1",
"tipo": "texto",
"props": {
"texto": "Não. Funciona no navegador, no computador ou no celular."
}
}
]
},
{
"titulo": "Posso cancelar quando quiser?",
"itens": [
{
"id": "faq-r2",
"tipo": "texto",
"props": {
"texto": "Sim. Não há fidelidade e você exporta seus dados a qualquer momento."
}
}
]
},
{
"titulo": "Como falo com o suporte?",
"itens": [
{
"id": "faq-r3",
"tipo": "texto",
"props": {
"texto": "Escreva para [suporte@exemplo.test](mailto:suporte@exemplo.test); respondemos em até um dia útil."
}
}
]
}
]
}
}
]
}
]
},
{
"id": "final",
"nome": "Chamada final",
"ancora": "contato",
"estilo": {
"fundo": {
"tipo": "cor",
"cor": "acento"
},
"padding": {
"topo": 56,
"direita": 24,
"base": 56,
"esquerda": 24
}
},
"colunas": [
{
"id": "final-col",
"gap": 16,
"alinhamento_horizontal": "centro",
"itens": [
{
"id": "final-titulo",
"tipo": "titulo",
"props": {
"texto": "Pronto para começar?",
"nivel": 2
},
"estilo": {
"alinhamento": "centro"
}
},
{
"id": "final-botao",
"tipo": "botao",
"props": {
"rotulo": "Criar minha conta",
"url": "https://exemplo.test/cadastro",
"variante": "contorno",
"tamanho": "g",
"nova_aba": true
}
}
]
}
]
}
]
}
7.3 Página com formulário
Crie o formulário (seção 3.8), copie o id e troque SUBSTITUA_PELO_ID_DO_FORMULARIO.
{
"versao": 2,
"estilo": {
"tema": "claro",
"fonte_titulos": "manrope",
"fonte_texto": "inter"
},
"secoes": [
{
"id": "contato",
"nome": "Contato",
"ancora": "contato",
"estilo": {
"largura": "contida",
"largura_max": 560,
"padding": {
"topo": 64,
"direita": 16,
"base": 64,
"esquerda": 16
}
},
"colunas": [
{
"id": "contato-col",
"gap": 16,
"itens": [
{
"id": "contato-titulo",
"tipo": "titulo",
"props": {
"texto": "Fale com a gente",
"nivel": 1
}
},
{
"id": "contato-texto",
"tipo": "texto",
"props": {
"texto": "Deixe seu e-mail e retornamos em até um dia útil.",
"variante": "suave"
}
},
{
"id": "contato-form",
"tipo": "formulario",
"props": {
"form_id": "SUBSTITUA_PELO_ID_DO_FORMULARIO",
"rotulo": "Enviar mensagem"
}
},
{
"id": "contato-lgpd",
"tipo": "texto",
"props": {
"texto": "Usamos seus dados só para responder a esta mensagem.",
"variante": "suave",
"tamanho": "p"
}
}
]
}
]
}
]
}
8. Checklist e prompt para agentes
8.1 Checklist
- [ ] Tenho um token de sessão (páginas) ou uma API key com o escopo certo (formulários/domínio).
- [ ] O JSON tem
versao: 2e só campos das tabelas da seção 3. - [ ] Todo
idé único no documento (seção, coluna, item e itens de painel) e casa^[A-Za-z0-9_-]{1,64}$. - [ ] Âncoras únicas,
^[a-z][a-z0-9-]{0,63}$; links#xapontam para âncoras que existem. - [ ] URLs: link só
http/https/mailto/tel,#ancoraou/caminho; mídia sóhttp(s)ou/caminho. - [ ] Cores em hex ou token; fontes da allowlist; inteiros dentro das faixas.
- [ ] Imagens enviadas para a galeria (ou
https://externa consciente). - [ ]
form_idde formulário existente (ou vazio de propósito). - [ ] Antes de editar: li o rascunho; não vou sobrescrever rascunho humano nem página publicada.
- [ ] Salvei versão, li o
422se veio, e publico pelo número só com autorização. - [ ] Guardei a versão publicada anterior para rollback.
8.2 Prompt para colar no agente
Você cria e edita páginas do Asender Pages pela API https://api.pages.asender.net.
Fonte da verdade: https://docs.asender.net/guias/pages-documento-v2.html (e llms-full.txt).
REGRAS
1. Escreva SEMPRE documentos {"versao": 2, "secoes": [...]} (seção > colunas > itens). Cada seção tem
"id" e "colunas"; cada coluna tem "id" e "itens"; cada item tem "id", "tipo" e "props" (objeto).
2. Use SOMENTE os campos documentados para cada tipo (titulo, texto, imagem, botao, tags, links, cartoes,
abas, acordeao, redes, menu, formulario, video, divisor, espacador, icone, selo, contador, marca, html).
Campo desconhecido é recusado. Não use o tipo "html" (privilegiado).
3. "id": ^[A-Za-z0-9_-]{1,64}$, ÚNICO no documento inteiro (inclusive itens dentro de abas/acordeão).
"ancora" de seção: ^[a-z][a-z0-9-]{0,63}$, única.
4. Cores: "#rrggbb", "#rrggbbaa" ou token (acento, texto, suave, fundo, superficie, borda, transparente).
Nunca nomes de cor CSS, rgb() ou CSS livre. Fontes (estilo.fonte_titulos/fonte_texto): somente
comfortaa, urbanist, montserrat, inter, poppins, open-sans, nunito, playfair-display, merriweather,
dm-sans, manrope, raleway.
5. URLs de link: http, https, mailto, tel, "#ancora" ou "/caminho" (nunca "//" nem javascript:).
URLs de mídia: https://host/... ou /caminho, sem aspas, espaços ou parênteses. Imagens: suba por
POST /v1/midias (multipart, campo "arquivo") e use o campo "url" devolvido.
6. Texto de titulo/texto aceita [rótulo](https://...) e [[destaque]]; nada de HTML.
7. Limites: 200 seções, 12 colunas/seção, 100 itens/coluna, 1000 itens/página, listas até 50 entradas,
abas/acordeão até 20 painéis (um nível, sem html/formulario/abas/acordeao dentro).
FLUXO
- Criar: POST /v1/paginas {"titulo","slug","template"} -> nasce DESPUBLICADA.
- Editar: GET /v1/paginas/{id} (template + ultima_versao + versao_publicada); GET /v1/paginas/{id}/rascunho.
Se houver rascunho (200), é trabalho humano: parta dele e grave com PUT .../rascunho?base=<rascunho_em>
(409 RascunhoConflito = preserve os dois lados, não force). Para versionar: POST .../versoes {"template"}.
- Publicar: SOMENTE com autorização do usuário, pelo número: POST .../publicar {"versao": N}.
Nunca sobrescreva uma página publicada sem ordem expressa; prefira duplicar (POST /v1/paginas/lote
{"acao":"duplicar","ids":[...]}) e editar a cópia. Rollback = publicar a versão anterior.
- Nunca chame DELETE .../rascunho. Não há exclusão de página.
VALIDAÇÃO
- Valide o JSON contra o schema (pages-documento-v2.schema.json) antes de enviar.
- Se vier 422 {"erro","codigo","caminho"}: corrija SOMENTE o nó em "caminho" conforme "codigo" e reenvie
(ErrPropInvalida/ErrEstiloInvalido = valor ou campo fora do contrato; ErrID/ErrAncora = repetido ou
mal formado; ErrLimite = teto; ErrEstruturaInvalida = tipo proibido em painel ou enum). Repita até 201.
- Em testes use apenas e-mails @exemplo.test e imagens de exemplo.test; nunca dados reais de terceiros.
9. Manutenção deste guia
As seções de referência (3.1 a 3.6, 4.1, 4.3 e 7) são geradas. Mudou o contrato do documento (schema, Go, TS)? Rode:
node scripts/docs-pages/gerar-referencia.mjs # reescreve os blocos gerados deste arquivo
node scripts/docs-pages/gerar-referencia.mjs --check # CI: falha se o guia está defasado
node --test scripts/docs-pages/documento-v2.test.mjs # guia em dia + receitas no schema
e commite este arquivo. As notas em prosa das tabelas (finalidade de cada tipo, descrição e padrão de cada prop) ficam em scripts/docs-pages/referencia-notas.mjs; o gerador reprova nota sobre prop que saiu do schema. Receitas: asender_docs/apis/pages/exemplos-v2/*.json; cada uma é validada contra o schema (node), o validador Go (receitas_docs_test.go) e o validador TS (receitas-docs.test.ts).