Catálogo vivo das seções e componentes que já rodaram em produção nos meus sites. Existe para responder rápido a duas perguntas:
- "Já fiz isso antes?" →
CATALOGO.md - "Como era mesmo?" → a ficha do componente, com código, padrão editorial e as armadilhas.
Cada componente entra aqui normalizado: mesmos tokens, mesmos prefixos, mesmos ganchos de movimento. É o que permite juntar um hero de um projeto com um leque de outro e um rodapé de um terceiro sem conflito de CSS.
No ar: https://biblioteca-sites.pages.dev
Como navegar
| Onde | Para quê |
|---|---|
index.html |
o showroom — tudo rodando lado a lado, com busca, favoritos e copiar |
CATALOGO.md |
índice por categoria e fila |
catalogo.json |
o mesmo índice, para busca automática |
CLAUDE.md |
o contrato — as regras duras: token, grid, prefixo, movimento, JS |
MANUAL.md |
o porquê de cada regra, e os casos que custaram uma noite |
core/ |
o que todo site herda: tokens, base, movimento, primitivas, temas |
_modelo/ |
esqueleto para catalogar um componente novo |
projetos/ |
o que saiu de cada site de origem, os clones de referência e os autorais |
No repo, leia os .md. No site publicado, cada .md tem um .html irmão, gerado, com os links já reescritos entre si.
O que a vitrine faz além de mostrar
| Buscar | filtra o DOM por id, nome, resumo, prefixo e tags, sem acento e sem fetch — por isso funciona por duplo-clique. / leva o foco para a busca de onde você estiver; Esc limpa. |
| Filtrar | os chips de status, complexidade e JavaScript combinam entre si e com a busca. A categoria é o próprio menu: clicar nela filtra, clicar de novo limpa. O número ao lado de cada categoria conta ignorando o recorte de categoria — ele responde "quantos eu acharia ali", que é a pergunta de quem está prestes a clicar. |
| Favoritar | a estrela do card marca o componente, que ganha linha na cor de marca e sobe para o topo da própria categoria. O chip Favoritos da barra mostra quantos são e filtra por eles. |
| Copiar | põe na área de transferência as duas linhas de inclusão do componente (só a folha, quando não há script) — é o que se cola num site novo. |
| Trocar o tema | Liberta, Kirvano ou Neutro (os defaults do core, antes de qualquer marca), aplicado dentro de todos os previews sem recarregar nenhum. É a promessa do contrato §3 — o mesmo componente em outra marca sem tocar no arquivo dele — feita visível. Os botões saem de core/temas/: tema novo aparece sozinho. |
A ficha de cada componente
Abre com o componente rodando, num palco que troca a largura da tela (desktop 1440, tablet 768, celular 390) e o tema, e tem Rever a entrada para assistir o reveal de novo. Logo abaixo, o código em abas — o que incluir, markup.html, estilo.css e script.js —, com realce de sintaxe e um botão que copia o arquivo exato. O realce é feito na geração, em Python (bin/realce.py); a página servida continua sem biblioteca de terceiro. Depois vem o texto da ficha: quando usar, padrão editorial, gotchas, histórico.
O tema escolhido na vitrine segue para a ficha, e vice-versa — mesma chave no localStorage.
Os favoritos moram no localStorage do navegador, não no repositório: o like é de quem está olhando, e não faz sentido versionar preferência. Isso tem duas consequências que valem saber. Rodar python bin/indice.py reescreve o index.html inteiro e os favoritos sobrevivem, porque nunca estiveram lá. E eles são por navegador e por máquina: limpar os dados do site esquece tudo, e o botão esquecer da barra lateral faz o mesmo de propósito.
Consumir por HTTP
O site é estático e o rastreamento é liberado, então uma sessão de IA sem o repo na máquina resolve tudo por URL:
https://biblioteca-sites.pages.dev/catalogo.json
https://biblioteca-sites.pages.dev/CLAUDE.html
https://biblioteca-sites.pages.dev/componentes/hero/full-bleed-media/ficha.html
O site não é indexado por buscador — isso vem do X-Robots-Tag no _headers, não de um bloqueio no robots.txt. O motivo dessa escolha está comentado nos dois arquivos.
Usar num site novo
1. copie core/tokens.css + core/base.css + core/motion.css + core/motion.js
2. duplique core/temas/_modelo.css → core/temas/<cliente>.css e preencha cores e fontes
3. escolha as seções no CATALOGO.md
4. cole markup.html + estilo.css + script.js de cada uma
5. troque fotos e textos seguindo o "padrão editorial" da ficha
A ordem das folhas importa: tokens → tema → base → motion → componentes.
Regra que sustenta tudo: o componente nunca é editado para caber no cliente. Quem muda é o tema. Se o tema não resolve, o componente ganha uma variação documentada na ficha — não um remendo local.
O conteúdo dos markup.html é fictício de propósito, dimensionado para o layout. Nenhum deles traz dado de cliente real.
Catalogar algo novo
Copie _modelo/ para componentes/<categoria>/<nome>/, preencha, e rode os dois geradores:
python bin/indice.py # catalogo.json + CATALOGO.md + showroom + as fichas em HTML
bash bin/previews.sh # preview.html de cada componente, a partir do markup.html
python bin/valida.py # confere que nenhum caminho relativo aponta para o vazio
O que é gerado e nunca se escreve à mão: catalogo.json, as tabelas do catálogo, os cards e os filtros do showroom, os preview.html e todos os .html de ficha. A fonte é o componente.json, o markup.html e o .md. O que se escreve à mão é a ficha e o código.
Fluxo completo em MANUAL.md §9.
Dependência de geração
bin/indice.py precisa de uma biblioteca para converter as fichas em HTML:
python -m pip install markdown
É a única dependência de geração, e ela existe só na sua máquina, na hora de gerar. Nada disso vai para o ar: o que é servido continua sendo HTML, CSS e JS sem dependência externa — e o Content-Security-Policy do _headers transforma isso em regra do servidor.
Dependência de verificação (opcional)
O painel de navegador embutido do Claude Code congela requestAnimationFrame, transições e a pintura de <img> — carrossel e esteira parecem parados, e screenshot mente. Para medir um componente de verdade há o bin/medir.js, que dirige o Chrome já instalado na máquina, em headless, e devolve números: transform antes e depois de um arrasto, classe ativa depois de uma tecla, overflow horizontal, erros de console.
cd bin && npm install # instala playwright-core em bin/node_modules (ignorado pelo git)
node bin/medir.js componentes/midia/carrossel-anel-3d/preview.html --drag=".ring-card:-300" --js=medida.js
E há a régua passada na biblioteca inteira, o bin/varredura.js: abre os oitenta previews em quatro cenários — desktop, celular, JavaScript desligado e movimento reduzido — e reprova erro de console, requisição que falhou, estouro horizontal e texto que nunca aparece. Leva uns três minutos e sai com código 1 se algo quebrou:
node bin/varredura.js # todos
node bin/varredura.js midia/ # só uma categoria
Na primeira passada ele achou o que nenhum validador de código via: a página de dados/cards-cotacoes com 547px de estouro no celular, o único botão do hero/centrado-prova-social sumindo sem JavaScript, e a conversa do hero/duas-colunas-produto desaparecendo inteira no mesmo caso.
Nada disso vai para o ar; é ferramenta de bancada, como o conformidade.py.
Publicar
O site é o próprio repositório: sem build, sem passo de deploy. O Cloudflare Pages está ligado ao GitHub e publica sozinho a cada git push na main.
python bin/indice.py && bash bin/previews.sh && python bin/valida.py
git add -A && git commit -m "..." && git push
O deploy leva menos de um minuto. Se você mexeu num .md, num componente.json ou num markup.html e não rodou os geradores, o que vai ao ar fica velho — o Pages não roda build, o que está no repo é o que é servido.
| Projeto Pages | biblioteca-sites |
| Repositório | bielera/biblioteca-sites (privado) |
| Branch de produção | main |
| Build command | nenhum |
| Output directory | / (a raiz) |
O conteúdo é público; o repositório continua privado.
Se o site parar de acompanhar os commits
Sintoma: você faz push, o GitHub mostra o check Cloudflare Pages · Deploy successful, e mesmo assim biblioteca-sites.pages.dev continua no estado antigo.
Não é falha de build. É a branch de produção do projeto não estar em main: os deploys saem como preview, cada um numa URL própria (<hash>.biblioteca-sites.pages.dev), e a produção fica congelada no primeiro.
Como confirmar em dez segundos:
python bin/valida-ar.py
Ele compara o que está no ar com o disco por conteúdo. Se acusar dezenas de divergentes e ausentes logo depois de um push bem-sucedido, é isto.
O conserto é no painel, em Settings → Builds & deployments → Production branch → main. Não há como fazer pela CLI: wrangler não configura a integração Git de um projeto Pages.
Por que o bin/valida-ar.py olha conteúdo, e não o código de status
O site responde 200 para qualquer endereço, servindo o index.html no lugar (SPA fallback). Um teste que só olhasse o status passaria com 100% mesmo com o deploy inteiro faltando — foi exatamente o que aconteceu aqui antes de a ferramenta existir.
Há um 404.html na raiz para o Pages servir um erro de verdade. Se mesmo assim uma URL inexistente devolver o showroom com 200, o projeto está em modo SPA (not_found_handling) e só o painel resolve.
Ver rodando local
python -m http.server 4380
E abra http://localhost:4380/. Há um .claude/launch.json com o nome biblioteca para o preview do Claude Code.
Os previews abrem com duplo-clique também, sem servidor — inclusive a busca do showroom, que filtra o DOM em vez de buscar o catalogo.json justamente para isso.
Fonte licenciada dando 404 é esperado. O .gitignore cobre core/temas/fontes/ e o @font-face do tema aponta para lá. Os previews caem no fallback da pilha e continuam legíveis. Não conserte subindo as fontes.
Stack
HTML estático, CSS puro com custom properties, JS vanilla em IIFE. Sem framework, sem build, sem dependência externa em produção. O alvo é um snippet que cola igual em página estática, em .astro ou em bloco HTML do Elementor.
Estado
| Componentes catalogados | 102 — 102 estáveis |
| Categorias com conteúdo | 11 de 11 |
| Tags da vitrine | 18 |
| Sem JavaScript | 27 de 102 |
| Prontos para produção | 102 de 102 |
| Dependências em produção | 0 |
A biblioteca cresce por referência externa — um site no ar, uma seção dele, e um clone reescrito do zero dentro do contrato, nunca uma cópia de código — ou por componente autoral: um padrão de interação de domínio comum construído aqui do zero. O processo está no fim do CATALOGO.md; o registro de cada clone em projetos/referencias-externas.md e o de cada autoral em projetos/autorais.md.