
Todas as capturas deste case vêm do Norte rodando no navegador, sem mockup nem frame do Figma.
Em 30 segundos
- O app e o site mobile rodavam havia anos com decisões de interface que ninguém tinha escrito. A mesma decisão existia em várias versões, e design e código tinham fontes de verdade separadas.
- Consolidei as fundações e criei o Norte: uma especificação por componente que vira documentação, componentes de web e app e um pacote que a IA lê e usa para revisar código.
- Os 11 fundamentos estão em uso. Dos 33 componentes especificados, 12 já estão no Norte, e o app de hoje tem um de/para documentado para o sistema novo.
- Bemol Digital
- Senior Product Designer
- Design system · Fundações e componentes
- App e site mobile
- Em produção · hub interno · biblioteca em construção
O sistema veio depois do produto
O produto já rodava havia anos, entre app e site mobile, com as decisões de interface já tomadas. Só que não estavam escritas, e não tinham saído de um lugar só. Um design system que começa do zero escolhe como as coisas serão; este teve que descobrir como elas já eram.
Então a primeira metade do trabalho foi mais arqueologia que design: achar onde uma decisão já tinha sido tomada, decidir se valia manter, e dar a ela um endereço único.
Esse endereço se chama Norte, nos dois sentidos da palavra: o da bússola, o ponto que todo mundo consulta antes de decidir para onde ir, e o do mapa, a região onde fica Manaus e de onde o produto sai.
O tamanho do sistema
Números de escopo, medidos em 18 de setembro de 2026.
- 33
- componentes especificados
- 330
- variações documentadas
- 12
- já no Norte, com as diretrizes do Design
Ninguém precisava decidir como um botão deveria ser. A parte difícil era achar os onze lugares que já tinham decidido, e escolher um.
Três problemas, e nenhum deles é estético
A mesma decisão existia em várias versões
Espaçamento, raio e tamanho de texto tinham se afastado entre telas construídas por pessoas diferentes em momentos diferentes. Nenhuma versão estava errada sozinha. Juntas, significavam que nenhuma tela era montada sem redecidir o que já deveria estar resolvido.
Documentação que ninguém abre não é documentação
Um sistema só se sustenta se o designer responde a dúvida mais rápido consultando do que perguntando. Isso é requisito de usabilidade sobre a própria documentação, e define o formato: resposta curta, um lugar só, achável sob pressão.
Design e código tinham fontes de verdade separadas
Biblioteca de componente que concorda com o arquivo de design só no instante em que é escrita vai discordar na sprint seguinte. O sistema precisava ser definido de modo que os dois lados lessem os mesmos valores, em vez de copiá-los.
O Figma decide, e o resto lê
De onde vêm os nomes que aparecem logo abaixo.
Nenhum dos lugares onde o sistema aparece decide alguma coisa. Todos leem, e quem decide é o Figma. Toda cor, todo raio e todo espaçamento nascem lá e são transcritos para um arquivo de tokens. São 367, num arquivo só, no formato aberto que o W3C mantém para design tokens.
Troque o degrau da rampa, ou o raio, e veja o que se move junto. Nenhuma dessas superfícies guarda uma cor ou um raio: todas leem a mesma variável, e é por isso que uma decisão chega em quatro lugares de uma vez.
Desse arquivo saem quatro coisas com um comando: as variáveis CSS da documentação web, a classe de tokens do app em Dart, as constantes que os componentes em código consomem e uma versão para ferramenta de IA, sem nenhuma cópia feita à mão.
As saídas não são iguais de propósito. As de código guardam a cadeia inteira: o componente aponta para o semântico, que aponta para a primitiva. A do agente entrega o valor já resolvido, porque quem lê ali quer o hexadecimal e não precisa da linhagem.
O preço está na primeira frase. A transcrição é manual: alguém abre o Figma, vê o que mudou e escreve no arquivo. Enquanto for assim, o sistema é tão atual quanto a última vez que uma pessoa olhou.
O estado vem da matriz
No momento em que os estados de um componente são desenhados à mão, eles começam a divergir: uma tela tem anel de foco, outra esqueceu, uma terceira inventou um diferente.
| tipo | enabled | pressed | loading | disabled |
|---|---|---|---|---|
| primary | ||||
| secondary | ||||
| tertiary |
As duas regras que o texto logo abaixo explica estão desenhadas aqui, e dá para conferir sem ler: as células de carregando e pressionado têm a mesma cor, e o secundário desabilitado é o único que continua branco. Abaixo, os três tamanhos: o pequeno tem 32px de visual dentro de 44px de área de toque.
Definir estado como matriz, cada tipo contra cada estado, transforma uma questão de design em conferência de completude. Célula vazia é buraco no sistema, visível antes de virar bug em produção.
E a matriz decide coisas que ninguém decidiria olhando um botão sozinho. Duas delas estão na grade acima: carregando usa as cores do pressionado, porque o botão continua ativo enquanto espera; e o secundário desabilitado continua branco, já que quem apaga ali é a borda e o texto.
Acessibilidade é propriedade de sistema
Visibilidade de foco, contraste e tratamento de erro são as primeiras coisas a sumir quando cada tela é construída em separado, porque cada uma é fácil de pular e ninguém percebe até uma auditoria.
Usamos só para contato.
Desabilitado: não se chega nele por uso.
Escreva, apague, deixe de fora o @. A borda troca de token e a mensagem aparece nos 16px que já estavam reservados abaixo do campo. O bloco inteiro ocupa os mesmos 72px em qualquer estado, e nada empurra nada.
Postas no sistema, deixam de ser decisão por tela. Duas delas ficam escritas na especificação, fora do alcance do bom senso de quem monta: erro é borda mais ícone mais texto, nunca só cor, porque quem não distingue vermelho de cinza precisa de outra pista; e a altura da mensagem é reservada antes de a mensagem existir, senão o conteúdo abaixo dá um salto no instante em que a validação aparece.
O Norte: quatro portas, uma casa
Um endereço, e cada perfil entra pela porta dele.
Um sistema espalhado por ferramentas diferentes cobra de cada pessoa o mesmo pedágio: descobrir onde procurar. O Norte responde com um endereço só. A primeira página pergunta o que você veio fazer em vez de qual ferramenta quer abrir, e as quatro portas são desenhar, construir para app, construir para web e gerar com IA.
A entrada pergunta quem você é antes de mostrar qualquer ferramenta. A porta de web é a única com aviso de obra, porque a biblioteca dela no Figma ainda não fechou.
Atrás das portas, a mesma fonte. Cada componente tem uma especificação escrita em Markdown, e é dela que saem a página que o designer consulta, o React de referência da web, o widget Flutter do app e o arquivo que uma ferramenta de IA carrega. Como o arquivo é um só, ninguém edita os quatro lugares separadamente.
No começo eram três vitrines, cada uma com seu endereço: uma central, o Storybook e o Widgetbook. Viraram uma casa só. O Storybook é a moldura, o Widgetbook roda dentro dele, e cada componente mora num lugar, com a especificação e o código de app e de web lado a lado. A barra lateral separa app e web porque a biblioteca web no Figma ainda não fechou, e quem entra precisa saber disso.
Web e app não são duas cópias
A pergunta que decide se um design system multiplataforma funciona é banal: quando o botão muda, quantos lugares precisam ser editados? Se a resposta for dois, o sistema já perdeu. Os dois vão divergir, e a divergência aparece meses depois, numa tela que ninguém está olhando.
À esquerda, a especificação que o time lê, nas mesmas quatro abas das diretrizes que o Design entrega no Figma. À direita, na aba ao lado, o mesmo botão como widget Flutter. É o código que o app consome, rodando no mesmo endereço.
Aqui a especificação é uma só, e cada ambiente lê a sua parte dela. Entre um e outro muda só a linguagem em que o componente é escrito; a decisão é a mesma.
O app de hoje também mora aqui
O de/para entre o que o app usa hoje e o que o sistema novo define.
O app já tinha um design system em código, escrito antes de vários fundamentos fecharem no Figma e parado desde então. Ignorá-lo seria fingir que o produto começa agora. Ele virou uma raiz própria no Norte, Produção (app hoje), com um de/para por fundamento: o token que o app usa, o valor que ele tem hoje e o token novo que ocupa o lugar dele.
Em cima, onde cada fundamento dói. Embaixo, as cinco armadilhas lado a lado: o nome em Dart que o app usa hoje, o valor dele, o token novo e o valor novo.
A tabela existe por causa de uma armadilha específica. A maior parte da migração é troca de nome, mas cinco tokens têm o mesmo nome e valor diferente, e são exatamente os que passam batido numa busca e substituição. O raio grande era 24px e virou 20; a borda média era 2px e virou 1,5. Nenhum deles quebra o build, mas todos mudam o pixel na tela sem que ninguém tenha decidido isso.
A página não diz qual valor está certo. Quem decide continua sendo o Figma; o de/para só mostra, troca a troca, se ela é direta ou se precisa de olho de designer antes de subir.
A quarta porta é para a máquina
Se o time gera código com IA, o sistema precisa estar onde a IA lê.
Designer e desenvolvedor deixaram de ser os únicos leitores de um design system. Quando alguém pede uma tela nova a um agente, quem escolhe espaçamento e cor é o agente. Sem o sistema por perto ele inventa um valor plausível, que é o pior tipo de erro: passa na revisão de olho e não bate com nada.
À esquerda, o índice: cada componente com o estado em que está e de quem depende, o que impede um agente de montar um componente em cima de outro que ainda não ficou pronto. À direita, a página da skill de revisão, com os dois modos e o arquivo para baixar.
Então a mesma fonte gera um pacote para ferramenta: o índice do que existe e em que estado, a especificação de cada componente e os valores de token, em três arquivos para baixar e colar na ferramenta, um de fundamentos, um de componentes de app e um de web. Junto vai um documento de regras, e a que mais importa é a que manda perguntar: se o token não existe, não aproxime.
Só ler não bastava. Componente feito em cima da hora, fora do fluxo, chegava sem seguir o sistema e sem documentação. Por isso a porta também revisa: uma skill confere o código contra o sistema e escreve o rascunho da especificação. O que é regra virou script, igual toda vez: valor cru no lugar de token, primitivo no lugar do semântico, token que não existe. O que é julgamento fica com a IA: variação inventada, estado faltando, acessibilidade.
A especificação entra como rascunho, com uma lista do que o código decidiu sem o Figma, para o Design revisar e promover. A skill nunca inventa token. Ficou skill, e não agente, porque skill é só texto e a mesma roda no Claude Code, no Claude.ai e no Cursor. A primeira passada achou três erros em código que já existia, e nenhum nos componentes de referência.
O que não foi para produção
Um componente para cada padrão do produto
Alguns padrões aparecem numa tela só e nunca vão se repetir. Sistematizar isso adiciona custo de manutenção e não compra nada. Um sistema que cobre todos os casos acaba difícil demais de mudar.
O caminho de volta, do código para o Figma
A ida existe: um arquivo de tokens vira as quatro saídas com um comando. A volta não. Mudar uma cor no Figma não move o arquivo sozinho, e continua sendo uma pessoa que transcreve o valor. A divergência entre os dois lados é registrada e revisada em vez de fingida, mas segue como a dívida mais cara do sistema. E o próximo passo não é automatizar essa transcrição: é deixar de precisar dela. Não está decidido, e não é decisão só minha, mas é para esse dia que venho construindo. Com os valores num arquivo versionado e a especificação em texto, trocar quem decide vira uma mudança de origem em vez de um recomeço.
Um anel de foco que passasse em contraste
O anel do sistema é o azul da marca a 32% de opacidade. Medido contra o branco, dá cerca de 1,9:1, e a WCAG 2.2 pede 3:1 para indicador de foco. A matriz de botões desta página mostra o anel como ele é. Corrigir só aqui deixaria o case bonito e o produto igual, e é uma das primeiras coisas que eu levaria para a próxima revisão das fundações.
Refazer todas as telas legadas de uma vez
Reescrever um produto em produção inteiro para satisfazer o sistema é assim que sistema é abandonado. Trabalho novo usa; trabalho antigo migra quando for tocado por outro motivo, componente a componente, com o de/para da raiz Produção dizendo o que muda o pixel.
Um pacote testado só por dentro
O pacote do app tinha 119 testes passando e um catálogo rodando, e ninguém tinha instalado ele de fora. Quando um app mínimo fez isso pela primeira vez, os ícones saíram como caixinha em minutos: o Flutter só honra a flag de fontes do Material no projeto do app, não no do pacote. O plano dizia o contrário. Hoje o pacote vem com esse app de exemplo, e esse foi o primeiro aviso levado ao time do app.
Quem fez o quê
- Consolidação das decisões espalhadas num conjunto único de fundações
- Estrutura e formato da documentação, para responder dúvida mais rápido do que perguntar para alguém
- Estados de componente definidos como matriz, em vez de tela a tela
- As regras que vêm antes dos componentes: grid, ritmo vertical, hierarquia
- O Norte e o caminho que sai dele: uma especificação por componente como fonte, gerando a documentação, a vitrine do app e o pacote que ferramenta de IA lê, construído por mim em par com agente de código
- A raiz Produção: o de/para entre os tokens do app de hoje e os do sistema novo, fundamento por fundamento
- A skill que revisa componente contra o sistema e escreve o rascunho da especificação para o Design
- Biblioteca de componentes, construída com a designer do time, ainda em andamento
- Implementação e API dos componentes em código, com engenharia
- Revisão do texto de interface, com a parte do time que cuida de writing
Onde está agora
Os 11 fundamentos e as regras de montagem de tela estão resolvidos e em uso, e desde agosto de 2026 têm endereço: o Norte serve as quatro portas a partir da mesma fonte. A biblioteca de componentes é a parte em construção. Dos 33 especificados, 12 já estão no Norte com as diretrizes do Design transcritas: nove rodam em código no app e na web, e três são demarcação de espaço do sistema, sem código. Contado por variação, são 93 de 330, perto de 28%.
O Norte é interno, e vai continuar sendo: ele existe para o time que constrói o produto. Por isso este case mostra captura de tela em vez de link, e por isso as demos desta página foram reconstruídas com a especificação real, que é o mais perto que dá para chegar de abrir a ferramenta.
Reflexões
O que sobra quando o arquivo envelhece.
Todo artefato aqui (token, matriz, regra) é uma forma de guardar um acordo para não precisar chegar a ele de novo. O acordo é o que dá trabalho; o arquivo é onde ele fica.
A medida que eu usaria não tem nada a ver com número de componente. É quantas perguntas deixaram de ser feitas, e quantas telas passaram a ser construídas sem ninguém redecidir o que já estava decidido.