Os tokens de design oferecem às equipes de desenvolvimento uma linguagem compartilhada para cores, espaçamento, tipografia, bordas e outras decisões de interface. Em vez de inserir repetidamente valores como #2563eb ou 1.5remos desenvolvedores usam nomes significativos, como color-primary e space-large.
Os tokens melhoram a consistência, mas mantê-los torna-se difícil à medida que o sistema de design cresce. Um desenvolvedor pode inserir uma cor inválida, reutilizar um nome de token ou atualizar o arquivo de token sem regenerar o CSS consumido pelo aplicativo.
Neste tutorial, construiremos uma pequena ferramenta Node.js que:
- Lê tokens de design do JSON.
- Valida seus nomes e valores.
- Gera propriedades personalizadas CSS.
- Cria uma visualização HTML visual.
- Fornece a visualização por meio de um servidor Node.js local.
O aplicativo usa módulos Node.js integrados, portanto, não requer uma estrutura web.
Crie o projeto
Crie um novo diretório com a seguinte estrutura:
design-token-preview/
├── data/
│ └── tokens.json
├── public/
├── src/
│ ├── build.js
│ └── server.js
└── package.json
Adicione isto package.json arquivo:
{
"name": "design-token-preview",
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "node src/build.js",
"start": "node src/server.js"
}
}
O projeto utiliza módulos ES, permitindo-nos importar funções Node.js com sintaxe moderna.
Defina os tokens de design
Adicione o seguinte conteúdo a data/tokens.json:
{
"colors": {
"primary": "#2563eb",
"primary-dark": "#1e40af",
"surface": "#ffffff",
"surface-muted": "#f1f5f9",
"text": "#0f172a",
"text-muted": "#475569",
"danger": "#dc2626"
},
"spacing": {
"small": "0.5rem",
"medium": "1rem",
"large": "1.5rem",
"xlarge": "2rem"
},
"radius": {
"small": "0.25rem",
"medium": "0.5rem",
"large": "1rem"
}
}
Agrupar tokens por finalidade facilita a leitura do arquivo. O aplicativo converterá um valor como colors.primary na variável CSS --colors-primary.
Em um sistema de design maior, você pode criar grupos adicionais para tipografia, sombras, pontos de interrupção, transições e valores específicos de componentes.
Leia e valide o arquivo de token
Criar src/build.js:
import {
readFile,
writeFile,
mkdir
} from "node:fs/promises";
const tokenFile = new URL(
"../data/tokens.json",
import.meta.url
);
const outputDirectory = new URL(
"../public/",
import.meta.url
);
function isValidTokenName(name) {
return /^(a-z)(a-z0-9-)*$/.test(name);
}
function isValidColor(value) {
return /^#(0-9a-f){6}$/i.test(value);
}
function isValidLength(value) {
return /^-?\d*\.?\d+(px|rem|em|%)$/.test(value);
}
function validateTokens(tokens) {
const errors = ();
for (const (groupName, group) of Object.entries(tokens)) {
if (!isValidTokenName(groupName)) {
errors.push(
`Invalid group name: "${groupName}"`
);
}
if (
typeof group !== "object" ||
group === null ||
Array.isArray(group)
) {
errors.push(
`Token group "${groupName}" must be an object.`
);
continue;
}
for (const (tokenName, value) of Object.entries(group)) {
if (!isValidTokenName(tokenName)) {
errors.push(
`Invalid token name: "${groupName}.${tokenName}"`
);
}
if (typeof value !== "string") {
errors.push(
`${groupName}.${tokenName} must be a string.`
);
continue;
}
if (groupName === "colors" && !isValidColor(value)) {
errors.push(
`${groupName}.${tokenName} must use a six-digit hex color.`
);
}
if (
("spacing", "radius").includes(groupName) &&
!isValidLength(value)
) {
errors.push(
`${groupName}.${tokenName} must be a CSS length.`
);
}
}
}
if (errors.length > 0) {
throw new Error(
`Token validation failed:\n- ${errors.join("\n- ")}`
);
}
}
A validação evita que valores malformados cheguem silenciosamente ao CSS de produção. As regras atuais são intencionalmente limitadas, mas criam uma base útil.
Para um sistema de produção, você pode usar o esquema JSON ou uma biblioteca de validação para impor regras mais detalhadas.
Gerar propriedades personalizadas CSS
Adicione esta função a src/build.js:
function createCss(tokens) {
const declarations = ();
for (const (groupName, group) of Object.entries(tokens)) {
for (const (tokenName, value) of Object.entries(group)) {
declarations.push(
` --${groupName}-${tokenName}: ${value};`
);
}
}
return `:root {\n${declarations.join("\n")}\n}\n`;
}
O CSS gerado ficará assim:
:root {
--colors-primary: #2563eb;
--colors-primary-dark: #1e40af;
--spacing-medium: 1rem;
--radius-medium: 0.5rem;
}
Propriedades personalizadas CSS podem ser usadas em todo um aplicativo:
.button {
padding: var(--spacing-small) var(--spacing-medium);
border: 0;
border-radius: var(--radius-medium);
color: var(--colors-surface);
background: var(--colors-primary);
}
.button:hover {
background: var(--colors-primary-dark);
}
A alteração do token de origem atualiza todos os componentes que fazem referência à variável correspondente.
Um documentado guia de estilo web pode complementar este sistema explicando quando tokens e componentes devem ser usados.
Gere a visualização HTML
Uma visualização visual ajuda designers e desenvolvedores a identificar alterações inesperadas antes da publicação dos tokens.
Adicione a seguinte função:
function createPreview(tokens) { const colorCards = Object.entries(tokens.colors) .map(((name, value)) => ``) .join(""); return ` name="viewport" content="width=device-width, initial-scale=1" >class="color-swatch" style="background: ${value}" aria-label="${name}: ${value}" >
${name}${value}Design Token Preview Generated automatically from the project token file. class="token-grid" aria-label="Color tokens" > ${colorCards} `; }
A visualização é gerada a partir da mesma fonte usada para produzir o CSS. Isso evita a atualização manual de uma página de referência separada sempre que um token é alterado.
Escreva os arquivos gerados
Completo src/build.js com a função de construção:
async function build() {
const source = await readFile(tokenFile, "utf8");
const tokens = JSON.parse(source);
validateTokens(tokens);
const css = createCss(tokens);
const preview = createPreview(tokens);
await mkdir(outputDirectory, {
recursive: true
});
await Promise.all((
writeFile(
new URL("tokens.css", outputDirectory),
css
),
writeFile(
new URL("index.html", outputDirectory),
preview
)
));
console.log("Design token preview generated.");
}
build().catch(error => {
console.error(error.message);
process.exitCode = 1;
});
Execute a compilação:
npm run build
Se a validação for bem-sucedida, o Node.js cria public/tokens.css e public/index.html. Se um token for inválido, o comando sairá com um erro em vez de gerar uma saída incompleta.
Servir a visualização com Node.js
Criar src/server.js:
import { createServer } from "node:http";
import { readFile } from "node:fs/promises";
import { extname } from "node:path";
const publicDirectory = new URL(
"../public/",
import.meta.url
);
const contentTypes = {
".html": "text/html; charset=utf-8",
".css": "text/css; charset=utf-8"
};
const server = createServer(async (request, response) => {
const requestedPath =
request.url === "/"
? "index.html"
: request.url.slice(1);
if (!("index.html", "tokens.css").includes(requestedPath)) {
response.writeHead(404, {
"Content-Type": "text/plain; charset=utf-8"
});
response.end("Not found");
return;
}
try {
const file = await readFile(
new URL(requestedPath, publicDirectory)
);
response.writeHead(200, {
"Content-Type":
contentTypes(extname(requestedPath))
});
response.end(file);
} catch {
response.writeHead(500, {
"Content-Type": "text/plain; charset=utf-8"
});
response.end(
"Run npm run build before starting the server."
);
}
});
server.listen(3000, () => {
console.log(
"Preview available at http://localhost:3000"
);
});
O servidor usa uma lista de permissões explícita de arquivos em vez de associar um caminho de solicitação arbitrário ao diretório público. Isso evita que os visitantes solicitem arquivos locais não relacionados por meio de caminhos como ../package.json.
Execute-o com:
npm start
Abrir http://localhost:3000 para inspecionar os tokens de cores gerados.
Adicione a compilação à integração contínua
O comando build pode ser executado em integração contínua sempre que uma solicitação pull modifica o arquivo de token.
Um pipeline simples deve:
- Instale a versão necessária do Node.js.
- Correr
npm run build. - Falha se a validação reportar um erro.
- Compare os arquivos gerados com as versões confirmadas.
- Publique a visualização como um artefato de revisão temporário.
Isso torna as alterações no token de design visíveis durante a revisão do código. Os designers podem inspecionar a visualização, enquanto os desenvolvedores podem confirmar se o CSS gerado permanece válido.
Não confie apenas na revisão visual. As verificações automatizadas devem detectar formatos inválidos, remoções inesperadas de tokens e alterações de nomes fraudulentas.
Apoie a colaboração com equipes externas
Um sistema de token de design torna-se especialmente útil quando o design e o desenvolvimento são gerenciados por equipes diferentes. O arquivo token compartilhado estabelece quais valores são aprovados e reduz a necessidade de copiar estilos manualmente dos arquivos de design.
Ao colaborar com um estúdio externo ou avaliar um parceiro regional como a Web Design Toronto, inclua a estrutura do token, convenções de nomenclatura, expectativas de acessibilidade, formatos de saída e processo de aprovação na entrega do projeto.
Os contribuidores externos devem enviar alterações simbólicas através do mesmo processo de revisão e validação que os desenvolvedores internos. Não devem manter uma fonte separada de cores e valores de espaçamento que possam divergir gradativamente da aplicação.
Possíveis melhorias
A ferramenta pode ser expandida com:
- Tipografia e visualizações de sombras.
- Temas claros e escuros.
- Avisos de valor duplicado.
- Verificações de contraste automatizadas.
- Validação do esquema JSON.
- Geração de tipo TypeScript.
- Saída Sass ou JavaScript.
- Comparações visuais entre versões de token.
- Modo de observação para reconstrução automática.
- Uma implantação de visualização de solicitação pull.
Mantenha o formato de origem simples até que o sistema de design realmente exija mais complexidade. Um pipeline de tokens pequeno e compreensível é mais fácil de manter do que uma plataforma avançada que a equipe não pode modificar com segurança.
Considerações finais
Os tokens de design conectam as decisões de interface com a implementação. Armazená-los em um arquivo estruturado cria consistência, mas a validação e a documentação determinam se essa consistência sobreviverá à medida que o aplicativo crescer.
O Node.js pode transformar um arquivo JSON básico em CSS validado e uma página de referência visual sem exigir uma estrutura completa. Ao executar a compilação durante a revisão do código, as equipes podem detectar valores inválidos e alterações visuais inesperadas antes de chegarem à produção.
Isso é muito mais adequado para o SitePoint do que um artigo geral sobre serviços de design porque fornece um projeto Node.js original e prático. Contudo, a aceitação não pode ser garantida e o link comercial ainda poderá receber revisão editorial adicional.




