Documentação
Criando um layout
Guia para quem cria ou mantém um layout do Rubrica. Vale para os layouts novos (esquema de cores completo) e, onde indicado, para os 5 originais.
O que é um layout
Um layout é uma pasta em templates/layouts/<id>/ registrada em cli/src/layouts.ts. Ao criar ou reconfigurar um projeto, o CLI (applyLayout) copia:
| Do template | Para o projeto |
|---|---|
os arquivos da raiz listados em copy (ex.: Layout.tsx, a navegação, um <Nome>Shared.tsx) |
src/components/ |
pages/Home.tsx, Resume.tsx, Portfolio.tsx, About.tsx, Blog.tsx |
src/pages/ |
Por isso, dentro do template:
Layout.tsxexportafunction Layout({ children, className }), como os layouts atuais. O app envolve todas as páginas públicas com ele.- Arquivos da raiz se importam entre si por caminho relativo (
./ZineNav). As páginas importam os arquivos da raiz por@/components/<Arquivo>(é onde eles vão estar no projeto). - Os nomes de arquivo são os do registro. Não crie arquivos fora dessa lista: eles não seriam copiados.
As páginas que nenhum layout substitui (post do blog /blog/:slug, estudo de caso /portfolio/:slug, depoimentos, propostas, checkout) são do app e seguem o esquema de cores sozinhas. O Layout.tsx dá a moldura e a margem para elas: veja TEMPLATE_PAGES no Layout.tsx do Bento.
Cores: o esquema completo
O CLI grava o esquema escolhido em src/index.css: o modo claro em :root e o escuro em .dark. Cada modo tem 11 papéis (cli/src/themes/schemes.ts):
| Variável | Papel |
|---|---|
--bg |
fundo das páginas |
--surface |
cartões, painéis, barras |
--subtle |
fundos sutis, faixas, hover |
--text |
texto principal |
--text-muted |
texto secundário, legendas |
--line |
bordas e divisórias |
--primary |
identidade: botões, links, blocos de destaque |
--on-primary |
texto sobre a primária |
--accent |
segunda cor de marca |
--on-accent |
texto sobre o acento |
--accent-2 |
terceira cor (só nos layouts novos) |
Também existe --text-strong (títulos, derivado de --text).
Regras (verificadas por tests/app/colorContract.test.ts):
- Layouts novos usam só essas variáveis:
var(--surface),color-mix(in srgb, var(--text) 20%, transparent)etc. Nenhuma cor literal: nada de#hex,rgb(),hsl()nem classes de cor fixa do Tailwind (text-white,bg-gray-100,bg-red-500…). Sombras também:color-mix(in srgb, var(--text) 18%, transparent). - Variáveis próprias do layout são permitidas se começarem com
--<id>-e forem derivadas do esquema (ex.:--zine-tape: color-mix(in srgb, var(--accent-2) 60%, transparent)). - Texto sobre a primária usa
--on-primary; sobre o acento,--on-accent. Nunca presuma que o fundo é claro ou escuro. - Layouts originais (
legacy: true) continuam só com--bg,--text,--primarye--accent.
O layout precisa funcionar com qualquer esquema, nos dois modos. Teste pelo menos: o recomendado do layout, alto-contraste, neon e um esquema de modo oposto ao recomendado.
Modo claro/escuro e textura
- O modo vem da classe
darkno<html>. O layout não decide o modo: só usa as variáveis. - Quando a pessoa liga a alternância (
rubrica config→ Aparência), quem visita pode trocar o modo. Todo layout coloca o<ColorModeToggle />(@/components/ColorModeToggle) na navegação. Ele não renderiza nada com a alternância desligada e herda a cor do texto. Estilize peloclassName/stylee posicione onde fizer sentido no layout. Para um controle próprio, useuseTheme()de@/contexts/ThemeContext(theme,toggleTheme,switchable). - A textura (grão, papel, scanlines) é uma camada global aplicada pelo
index.css(data-textureno<html>). O layout não implementa textura e não deve criar camadas fixas opacas por cima da página inteira.
Fontes
- Use
var(--font-sans)(principal) evar(--font-mono). O CLI carrega as duas do Google Fonts. As recomendadas de cada layout estão no registro. - Uma fonte de assinatura extra (ex.: a letra à mão do Zine) é permitida. O próprio
Layout.tsxa carrega com<Helmet>dereact-helmet-async(<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Caveat:wght@500;700&display=swap" />) e sempre declara uma fonte de reserva.
Conteúdo: o que cada página precisa mostrar
Os layouts mudam a forma, não o conteúdo. Toda página cobre o mesmo que as dos layouts atuais, lendo os mesmos hooks. Leia por inteiro as páginas de um layout existente (templates/layouts/swiss/pages/*.tsx e templates/layouts/bento/pages/*.tsx) e a doc dele (docs/templates/bento.md) antes de começar. Em resumo:
- Início (
useHome,useHomeMetrics,usePortfolio+selectFeaturedCases,useContactWizard,usePlugin): disponibilidade (quando ligada), nome, frase de valor (home.hero.headline), cargo, botões "Ver cases" e "Fale comigo" (abre o formulário), números de destaque (até 4, a faixa some sem números), 3 cases em destaque com a primeira métrica e link para/portfolio/<slug>, sobre, "O que eu faço" (serviços), depoimentos (com "ver todos" e "deixar meu depoimento" conforme os plugins) e a chamada final "Tem um projeto em mente?" com "Tenho um projeto" e "Tenho uma vaga". - Currículo (
useResume,groupSkills,splitExperiences,useDownloadCV): resumo, botão de baixar o CV em PDF, números de destaque, experiências recentes com as antigas atrás de "ver anteriores", habilidades agrupadas por grupo (sem níveis numéricos), soft skills, idiomas, formação, cursos, certificações e voluntariado (cada bloco some quando vazio). - Portfólio (
usePortfolio,listCategories,filterByCategory,hasCaseStudy): filtro por categoria (some sem categorias), destaque para os primeiros, a primeira métrica do case em cada projeto e uma ação só: o case quando existe, senão o link do projeto. - Sobre (
useAbout,useWorkPrinciples,splitParagraphs,highlightNumbers): "Como eu trabalho" (princípios) abrindo a página, resumo profissional, texto pessoal, dia a dia, interesses e FAQ. - Blog (
useBlogPosts): lista de posts com o destaque primeiro, links para/blog/<slug>, data e tempo de leitura, tags e indicação de RSS.
Respeite os plugins (usePlugin("portfolio"), "blog", "resume", "about", "testimonials", "testimonials-intake", "contact-wizard"): o que estiver desligado some da página e da navegação.
Todo link interno aponta para uma rota de src/App.tsx (teste tests/app/templates/routes-contract.test.ts).
Textos e idiomas
- Use as chaves de
src/i18n/translations/pt-BR.tscomt()(useTranslation). Não edite os arquivos de tradução. - Textos próprios do layout (rótulos decorativos como "Folha 02" ou "Caixa de entrada") ficam no
<Nome>Shared.tsxdo layout, em pt-BR e en-US, escolhidos poruseI18n().locale. - Nada de dados pessoais fixos no código: nome, e-mail e projetos vêm dos hooks.
Celular
Tudo funciona a partir de 360px de largura, sem rolagem horizontal. Use classes responsivas do Tailwind, media queries no próprio componente ou os atributos de MobileLayoutStyles (rb-mobile, data-m-cols, data-m-hide…). Elementos decorativos que não cabem somem no celular; conteúdo nunca.
Ver o layout funcionando
# monta um projeto temporário com o layout aplicado pelo CLI, checa tipos, faz o build e sobe o preview
npx tsx scripts/preview-layout.ts --layout <id> --port <porta> [--scheme <esquema>] [--texture <textura>]
# só checar os tipos
npx tsx scripts/preview-layout.ts --layout <id> --port <porta> --check-only
# fotografa as 5 páginas nos dois modos, em 1440px e 390px, e avisa rolagem horizontal e erros no console
node scripts/shot-layout.mjs --port <porta> --out /tmp/rubrica-shots/<id>
# parar o preview
npx tsx scripts/preview-layout.ts --stop --port <porta>
O preview usa os dados de exemplo de public/data/ (perfil fictício "Alex Rocha") e sai com a alternância de modo ligada.
Testes que cobrem layouts:
npx vitest run tests/app/colorContract.test.ts tests/app/templates