Agentes de código
Cada página deste site também é Markdown puro, e o conjunto todo cabe num arquivo só, para que um assistente leia a documentação em vez de adivinhá-la.
Um assistente que não leu a documentação escreve o que lembra de alguma outra biblioteca: classes utilitárias por cima dos componentes, uma folha de estilos brigando com o tema, imports de ícones que não existem. Nada disso é um problema difícil — é um problema de leitura. Por isso o build escreve este site duas vezes: uma como as páginas que você está vendo, e outra como Markdown, no formato que o llms.txt descreve.
O que é publicado
/vitral/llms.txt the index: every page, with a line on what it covers
/vitral/llms-full.txt all of it in one file
/vitral/docs/theming.md any page, with .md instead of the trailing slash
/vitral/components/select.mdllms.txt é o índice: os guias, cada componente e cada template, cada um com a linha que o descreve, apontando para o Markdown e não para a página. llms-full.txt é tudo, concatenado, para um modelo com contexto suficiente para comportá-lo. E qualquer página responde com .md no lugar da barra final, que é a coisa mais barata a entregar a um agente que só precisa de um componente.
O Markdown é gerado a partir da página renderizada, então traz a prosa, os títulos e as tabelas de API — que, por sua vez, são lidas do types.ts de cada componente em tempo de build. A página de um componente também recebe, no final, o código dos seus exemplos, porque no site eles ficam atrás de um botão, e um agente não tem como apertá-lo.
Aponte um agente para cá
Tudo cabe numa linha de prompt:
Read https://vitralui.github.io/vitral/components/datagrid.md
and write me a table of invoices with sorting, filtering and paging.Num projeto em que você trabalha todo dia, ponha as regras onde o agente as lê — AGENTS.md, CLAUDE.md, .cursor/rules, ou como quer que a sua ferramenta chame isso. Esta é a versão curta que vale colar, e ela trata das coisas que um modelo erra por hábito, e não por ignorância:
# Vitral
Docs: https://vitralui.github.io/vitral/llms.txt
- Import components from `@vitral/vue`: `import { Button, Select } from '@vitral/vue'`.
In Nuxt they are global (`<VtButton>`) through `@vitral/nuxt`.
- Do not write utility classes and do not hand-write CSS to restyle a component.
The look is tokens: `dt('button.background')`, a preset, or the `dt` prop.
- To change one instance's markup or classes, use pass-through (`pt`), not a wrapper.
- `unstyled` drops every class and keeps the behaviour and the ARIA.
- Icons are names resolved from `@vitral/icons`: `<Button icon="search" />`.
Anything outside the base set has to be registered first.
- Fields are real controls: `<label for>`, `name` and `aria-describedby` reach
them without extra props.Por que essas regras
- Tokens, não CSS. A aparência de cada componente são custom properties, que um preset define e a prop
dtsobrescreve numa instância. Uma folha de estilos escrita ao lado funciona até o esquema de cores mudar. - Pass-through para a marcação. Todo elemento interno pode ser endereçado pelo nome, então um agente nunca precisa envolver um componente para alcançar o que há dentro dele.
- Ícones são nomes registrados. Os componentes resolvem sozinhos o conjunto que usam; qualquer outro é um import nomeado, ou uma chamada a
registerIcons. Um nome inventado vira uma classe, em silêncio. - A acessibilidade já está lá. Cada componente segue o seu padrão WAI-ARIA APG e é testado contra ele, então acrescentar atributos
roleearia-*costuma quebrá-lo em vez de ajudar.
Mantendo tudo honesto
Nada aqui é escrito à mão, e essa é a ideia: o Markdown é o site, as tabelas de API são o código-fonte, e os dois são reconstruídos a cada push. Uma página que fica desatualizada fica desatualizada num lugar só.