DESIGN.md vs tailwind.config.js — Por que AI agents precisam do wrapper semântico
Comparação entre DESIGN.md e configurar tokens direto no tailwind.config.js. Por que LLMs não parsam configs JavaScript bem e como DESIGN.md resolve isso.
Veredito Rápido
Se você usa Tailwind e AI coding agents (que é basicamente todo mundo em 2026), use os dois. O tailwind.config.js é o runtime — onde o framework lê os tokens. O DESIGN.md é o manual semântico — onde o agente entende por quê aqueles tokens existem e como usá-los. Colocar tudo só no tailwind.config e esperar que o Cursor entenda a intenção é como dar um dicionário pra alguém e esperar que escreva poesia.
Tabela Comparativa
| Dimensão | DESIGN.md | tailwind.config.js |
|---|---|---|
| Formato | YAML tokens + Markdown rationale | JavaScript/TypeScript object |
| Propósito primário | Documentação semântica para humanos e AI | Configuração de runtime do Tailwind |
| Consumo por LLMs | Excelente — formato nativo de LLMs | Problemático — JS nested, spread operators, imports dinâmicos |
| Decisões de design | Embutidas no documento | Inexistentes — só valores crus |
| Portabilidade | Framework-agnostic | Só Tailwind (e derivados como UnoCSS com adapter) |
| Executável | Não — é documentação | Sim — Tailwind lê e gera CSS |
| Conflitos | Raro — arquivo pequeno e focado | Comum — merge conflicts em objetos JS grandes |
| Manutenção | Atualiza quando design system muda | Atualiza quando design system muda (duplicação) |
O Problema Real: LLMs e JavaScript Config
Aqui está o elefante na sala que ninguém discutia até AI agents virarem mainstream: LLMs são péssimos em parsear configuração JavaScript complexa.
Um tailwind.config.js típico de projeto real parece isso:
import { fontFamily } from 'tailwindcss/defaultTheme'
import colors from './tokens/colors.mjs'
import typography from './tokens/typography.mjs'
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: {
extend: {
colors: {
...colors,
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
surface: {
DEFAULT: 'hsl(var(--surface))',
elevated: 'hsl(var(--surface-elevated))',
}
},
fontFamily: {
display: ['Cal Sans', ...fontFamily.sans],
body: ['Inter', ...fontFamily.sans],
},
spacing: generateSpacingScale(4),
borderRadius: {
...defaultRadius,
card: 'var(--radius-card)',
}
}
},
plugins: [require('@tailwindcss/typography'), require('@tailwindcss/forms')],
}
O que o LLM vê aqui:
- Imports dinâmicos — não sabe o que
colors.mjscontém sem ler outro arquivo - Spread operators —
...colorsé uma caixa preta - CSS variables —
hsl(var(--primary))não é um valor, é uma referência - Funções —
generateSpacingScale(4)requer execução mental - Zero contexto — por que Cal Sans? Por que ratio de 4px? Silêncio.
Quando o agente recebe um prompt “crie um card de pricing seguindo nosso design system”, ele lê esse config e… chuta. Usa cores que parecem certas. Aplica espaçamento “mais ou menos”. O resultado compila, mas não respeita a intenção.
DESIGN.md em Detalhe
O wrapper semântico
DESIGN.md não substitui o tailwind.config. Ele envelopa os mesmos tokens com significado:
colors:
primary:
value: "hsl(222 47% 11%)"
tailwind: "primary"
usage: "CTAs, links primários, headers de seção"
contrast: "Usar sempre com text-white ou primary-foreground"
surface:
default:
value: "hsl(0 0% 100%)"
tailwind: "surface"
usage: "Background padrão de cards e containers"
elevated:
value: "hsl(210 20% 98%)"
tailwind: "surface-elevated"
usage: "Cards com elevação, modals, popovers"
typography:
philosophy: |
Escala modular com ratio 1.25 (Major Third).
Display usa Cal Sans para personalidade.
Body usa Inter para legibilidade em telas.
Nunca misturar display em corpo de texto.
scale:
- name: "hero"
class: "text-5xl font-display font-bold"
usage: "Apenas hero sections — um por página"
- name: "section-title"
class: "text-3xl font-display font-semibold"
usage: "Títulos de seção — h2 na hierarquia"
- name: "body"
class: "text-base font-body"
usage: "Texto corrido — parágrafos, descrições"
spacing:
base: "4px"
philosophy: |
Múltiplos de 4px. Componentes internos usam 2-4 (8-16px).
Entre componentes usa 6-8 (24-32px).
Entre seções usa 16-24 (64-96px).
Nunca usar valores arbitrários como p-[13px].
O que muda na prática
Com esse DESIGN.md no contexto, o mesmo prompt “crie um card de pricing” gera:
- Cores corretas com contraste adequado
- Tipografia hierárquica respeitando a escala
- Espaçamento consistente com o sistema
- Classes Tailwind corretas (não inventa
bg-slate-50quando deveria serbg-surface-elevated)
Vantagens específicas sobre config puro
- Self-contained — tudo num arquivo, sem imports pra resolver
- Intenção explícita — “nunca usar display em corpo de texto” evita erros
- Classes mapeadas — o agente sabe exatamente qual classe Tailwind aplicar
- Exemplos de uso — cenários concretos, não só valores abstratos
- Restrições documentadas — o que NÃO fazer é tão importante quanto o que fazer
tailwind.config.js em Detalhe
O que faz bem
O tailwind.config.js é execução. É o que o framework realmente lê pra gerar CSS. Sem ele, não existe Tailwind customizado. Ponto.
Quando basta sozinho
Em projetos onde:
- Não usa AI agents pra gerar código
- Time pequeno (1-2 devs) que conhece o config de cor
- Design system simples (poucas cores, tipografia padrão)
- Não precisa onboardar gente nova com frequência
Problemas reais sem DESIGN.md
Cenário 1: Novo dev no time
“Qual a diferença entre bg-surface e bg-surface-elevated? Quando uso cada um?”
Resposta do tailwind.config: silêncio. Resposta do DESIGN.md: “Surface para cards padrão, surface-elevated para cards com elevação visual — modals, popovers, tooltips.”
Cenário 2: AI agent gerando página
Prompt: “Crie uma landing page com hero, features grid e pricing cards.”
Sem DESIGN.md: O agente usa text-4xl porque parece certo, mistura font-bold com font-semibold aleatoriamente, usa gap-4 e gap-6 sem critério.
Com DESIGN.md: Hero usa text-5xl font-display font-bold (um por página). Features usa text-3xl font-display font-semibold. Spacing entre seções é py-24. Consistência automática.
Cenário 3: Design system evolui
Mudou a primary de azul pra roxo. No tailwind.config, o valor muda e pronto. Mas e a regra de contraste? E os pairings que funcionavam? E as combinações que agora quebram?
DESIGN.md documenta essas relações. O agente sabe que mudar a primary afeta CTAs, links e headers — e pode ajustar tudo de forma coordenada.
A Relação Correta: Camadas
┌─────────────────────────────────────┐
│ DESIGN.md │ ← Semântica, intenção, restrições
│ (consumido por AI + humanos) │
├─────────────────────────────────────┤
│ tailwind.config.js │ ← Runtime, valores executáveis
│ (consumido pelo Tailwind CLI) │
├─────────────────────────────────────┤
│ CSS gerado │ ← Output final
│ (consumido pelo browser) │
└─────────────────────────────────────┘
DESIGN.md não compete com tailwind.config. Ele é a camada acima — a que traduz tokens em intenção. O tailwind.config continua existindo, continua sendo o que o Tailwind lê. Mas o agente lê o DESIGN.md primeiro e depois sabe quais classes do Tailwind usar.
Quando Usar Qual
Use só tailwind.config quando:
- Projeto pessoal pequeno, sem AI agents
- Você é o único dev e conhece cada token de memória
- Design system mínimo (cores da marca + tipografia padrão)
- Não vai onboardar ninguém no projeto
Use DESIGN.md + tailwind.config quando:
- Qualquer projeto que usa AI coding agents — que é 90% dos projetos em 2026
- Time com mais de 1 dev
- Design system com mais de 10 tokens customizados
- Precisa de consistência visual entre páginas/componentes
- Open-source onde contribuidores precisam entender o design
Use DESIGN.md sem Tailwind quando:
- Projeto usa outro framework CSS (vanilla, CSS Modules, styled-components)
- Design tokens precisam ser framework-agnostic
- Migrando de Tailwind pra outra solução
FAQ
DESIGN.md precisa estar sincronizado manualmente com tailwind.config?
Na maioria dos casos, sim — mas não é tão ruim quanto parece. DESIGN.md muda raramente (design system é estável por definição). Quando muda, você atualiza ambos. Existem scripts na comunidade que geram tailwind.config a partir do DESIGN.md, invertendo a direção: o DESIGN.md vira a fonte canônica e o config é derivado.
Se já tenho tailwind.config bem organizado, preciso mesmo de DESIGN.md?
Depende: seu AI agent gera código consistente? Se você pede “crie um card” e o resultado usa tokens errados ou mistura estilos, o config sozinho não está funcionando como documentação. DESIGN.md resolve exatamente esse gap.
Posso gerar DESIGN.md a partir do meu tailwind.config existente?
Sim. O designmd.app oferece geração automática de DESIGN.md a partir de configs existentes. Mas o valor real está em adicionar o rationale — as explicações de por quê — que nenhum script extrai automaticamente do config.
E se uso Tailwind v4 com CSS-first config?
Tailwind v4 move tokens pra @theme no CSS, o que melhora um pouco a legibilidade vs o JS config antigo. Mas o problema fundamental permanece: CSS não carrega semântica de uso, restrições, ou filosofia de design. DESIGN.md continua sendo a camada semântica necessária.
Quantos tokens justificam criar um DESIGN.md?
Se seu tailwind.config tem mais de 5 cores customizadas, tipografia não-padrão, ou espaçamento customizado — já justifica. Na prática, qualquer projeto que personalizou o Tailwind além do default beneficia de DESIGN.md. O custo de criar é baixo (30 minutos), o benefício de consistência é permanente.
Conclusão
tailwind.config.js é infraestrutura. DESIGN.md é comunicação.
Um fala pro Tailwind “gere essas classes CSS com esses valores”. O outro fala pro agente (e pro humano) “use essas classes nesses contextos por essas razões”.
A confusão acontece quando times tratam o config como documentação. Não é. Nunca foi. É um objeto JavaScript que configura um build tool. Tentar extrair intenção de design de um extend.colors.primary.DEFAULT: 'hsl(var(--primary))' é como tentar entender uma receita lendo só a lista de ingredientes sem as instruções.
DESIGN.md é as instruções. E em 2026, com AI agents cozinhando a maioria do frontend, as instruções importam mais que nunca.
Os 461 design systems no designmd.app incluem a maioria dos projetos Tailwind relevantes — e cada um mostra como o wrapper semântico transforma configuração em compreensão.