Common patterns for real-world templates
Receitas curtas para problemas reais que aparecem ao escrever templates: listas de opcoes que se repetem, colunas de imagem em tabelas, achatamento de querystring, e quando preferir tabela vs campos repetidos.
Short recipes for real problems you hit while authoring templates: repeated option lists, image columns in tables, querystring flattening, and when to prefer a table over repeated fields.
Quando o mesmo conjunto de opcoes aparece em varios campos (ex: lista de partidos politicos, lista de paises, lista de canais), o padrao atual e repetir o array options inline em cada campo. Verbose mas explicito e compativel com qualquer ferramenta que leia o JSON.
When the same option set appears in many fields (e.g. political parties, countries, channels), the current pattern is to repeat the inline options array on every field. Verbose but explicit, and compatible with any tool that reads the JSON.
{
"key": "b1p", "name": "bar1Party", "label": "Bar 1 — party",
"type": "dropdown",
"default": "PL",
"options": [
{ "value": "PL", "text": "PL" },
{ "value": "PT", "text": "PT" },
{ "value": "PSDB", "text": "PSDB" }
/* ... 27 mais ... */
]
}
"options": "@parties" resolvida contra schema.optionLists.parties) esta planejada mas nao implementada ainda. Por enquanto, repita o array.
"options": "@parties" resolved against schema.optionLists.parties) is planned but not implemented yet. For now, repeat the array.
Dica de autoria: gere o config.json a partir de uma fonte unica (script Node, template Jinja, etc.) para evitar erro de copia/colagem. O editor le apenas o JSON final.
Authoring tip: generate config.json from a single source (Node script, Jinja template, etc.) to avoid copy-paste drift. The editor reads only the final JSON.
Em uma tabela, defina a coluna como type: "image" e adicione accept. Ao clicar na celula, o editor abre o mesmo picker de assets do MAM usado pelo campo file raiz.
In a table, set the column to type: "image" and add accept. Clicking the cell opens the same MAM asset picker used by the top-level file field.
{
"key": "bars", "name": "bars", "label": "Barras",
"type": "table",
"maxRows": 4,
"columns": [
{ "key": "n", "label": "Candidato", "type": "text" },
{ "key": "f", "label": "Foto", "type": "image", "accept": "image", "width": 90 },
{ "key": "v", "label": "Valor", "type": "number", "min": 0, "max": 100 }
]
}
O valor armazenado por linha e o caminho do asset (string), por exemplo assets/lula.avif. O template recebe esse caminho ja resolvido na querystring.
The stored per-row value is the asset path (string), e.g. assets/lula.avif. The template receives this resolved path in the querystring.
Cada celula vira um parametro com o padrao key + indice. Um parametro lider nomeDoCampo=N indica a quantidade de linhas. Para o exemplo do item 2, com 2 linhas:
Each cell becomes a parameter with the pattern key + index. A leading fieldName=N indicates the row count. For the example in section 2, with 2 rows:
?bars=2&n1=Lula&f1=assets/lula.avif&v1=42&n2=Bolsonaro&f2=assets/bolso.avif&v2=39
No template, leia com URLSearchParams:
In the template, read with URLSearchParams:
const p = new URLSearchParams(location.search);
const count = parseInt(p.get('bars') || '0', 10);
const rows = [];
for (let i = 1; i <= count; i++) {
rows.push({
name: p.get(`n${i}`) || '',
photo: p.get(`f${i}`) || '',
value: parseFloat(p.get(`v${i}`) || '0')
});
}
console.log(rows);
// [{ name: 'Lula', photo: 'assets/lula.avif', value: 42 }, { ... }]
Quando o template tem N entidades parecidas (8 barras, 5 candidatos, 3 colunas), ha duas formas de modelar:
When the template has N similar entities (8 bars, 5 candidates, 3 columns), there are two ways to model it:
| Padrao / Pattern | Quando usar / When to use |
|---|---|
Tabela / Table — um campo type: "table" com columns |
Numero de linhas e variavel (1 a N). Cada linha tem mesmas colunas. Editor mostra UI tabular escalavel.
Row count is variable (1 to N). Each row has the same columns. Editor shows a scalable tabular UI. |
Campos repetidos / Repeated fields — b1n, b1v, b2n, b2v... |
Numero fixo (sempre 8 barras), ou cada "linha" tem schema unico, ou voce precisa de tips/labels diferentes por entidade.
Fixed count (always 8 bars), or each "row" has a unique schema, or you need different tips/labels per entity. |
Recomendacao: use tabela quando possivel — e mais facil de manter, mais facil de preencher e reduz a duplicacao no schema.
Recommendation: use a table when possible — easier to maintain, easier to fill in, and reduces schema duplication.
Padrao recomendado para o app.js de um template: ler URLSearchParams, normalizar valores, renderizar uma vez.
Recommended pattern for a template's app.js: read URLSearchParams, normalize values, render once.
const p = new URLSearchParams(location.search);
// helpers
const str = (k, d = '') => p.get(k) ?? d;
const bool = (k, d = false) => (p.get(k) ?? (d ? '1' : '0')) === '1';
const num = (k, d = 0) => parseFloat(p.get(k) ?? String(d));
// values (use the field "name", not the "key" — that's just a convention)
const data = {
title: str('t', 'Hello'),
bgColor: str('bg', '#000'),
showTime: bool('show', true),
ratio: num('pct', 0)
};
// render
document.body.style.background = data.bgColor;
document.body.querySelector('h1').textContent = data.title;
if (!data.showTime) document.body.querySelector('.time').remove();
Templates rodam em standalone (sem editor). Nesse caso, todos os defaults do schema entram em jogo. Escolha defaults visualmente plausiveis para que o template renderize bem ao ser aberto sem nenhum parametro.
Templates run standalone (without an editor). In that case, all schema defaults come into play. Choose visually plausible defaults so the template renders well when opened with no params.
"lorem ipsum" — ajuda quem testa o template / Text: use real copy, not "lorem ipsum" — helps anyone testing the template.img/default.avif dentro do ZIP / Images: point to an asset bundled in img/default.avif inside the ZIP.#000000 ou #ffffff puros / Colors: use brand palette; avoid pure #000000 or #ffffff.0 — um grafico com tudo em zero parece quebrado / Numbers: use realistic values, not 0 — a chart with all zeroes looks broken.
meta.version deve seguir semver-ish: aumente o major quando a forma do schema mudar de modo incompativel (renomeou um campo, mudou um tipo). O backend pode usar essa versao para aplicar migracoes em configuracoes salvas.
meta.version should follow semver-ish: bump major when the schema shape changes in an incompatible way (renamed a field, changed a type). The backend can use this version to migrate saved configurations.
tip, expandir options) podem aumentar apenas o patch (1.2.0 → 1.2.1). Mudancas de comportamento aumentam o minor; mudancas de schema que quebram, o major.
tip, expand options) can bump only the patch (1.2.0 → 1.2.1). Behavior changes bump the minor; breaking schema changes bump the major.