Astro
O Astro é responsável pela estrutura estática: páginas, layouts e regiões puramente apresentacionais.
SolidJS ou React é responsável por toda a interatividade: todo componente que lida com entrada do usuário,
gerencia estado ou responde a eventos é uma ilha de framework — não um arquivo .astro.
CSS Modules são usados para toda a estilização de componentes — sempre em um arquivo
styles.module.css separado, nunca inline ou dentro do bloco <style> do Astro.
Quando Usar Esta Skill
- Estruturar um novo projeto Astro ou adicionar páginas e áreas de layout
- Construir páginas
.astro, layouts ou regiões estáticas apresentacionais - Decidir se algo pertence ao Astro ou a uma ilha SolidJS/React
- Escolher qual diretiva de hidratação usar para uma ilha
- Aplicar estilização com CSS Modules em arquivos
.astroou ilhas de framework - Trabalhar com coleções de conteúdo (
src/content/,src/content.config.ts) - Conectar dados da camada de serviço em páginas Astro renderizadas no servidor
- Usar ilhas de servidor (
server:defer) para regiões personalizadas adiadas - Configurar renderização sob demanda (SSR) com adaptadores e middlewares
- Definir e chamar Astro Actions para mutações seguras no servidor
Astro vs Ilhas — A Decisão Arquitetural Central
Esta é a decisão mais importante em qualquer projeto Astro.
| O que faz | Use |
|---|---|
| Renderiza HTML estático a partir de dados — sem interação do usuário | .astro |
| Estrutura de página, layout wrapper, estrutura de navegação | .astro |
| Seções de conteúdo, posts de blog, regiões de marketing | .astro |
Qualquer componente com onClick, onChange, estado de formulário ou dados reativos | Ilha SolidJS ou React |
| Componentes fundamentais de UI (Button, Input, Modal, Alert, etc.) | Ilha SolidJS ou React |
| Qualquer componente que leia ou escreva em um store ou hook de serviço | Ilha SolidJS ou React |
A regra em termos simples:
- O Astro renderiza estrutura e conteúdo. Ele não lida com interação do usuário.
- SolidJS ou React lida com toda a interatividade, todo estado de formulário e todos os primitivos de UI interativos fundamentais — até mesmo um botão simples que dispara um evento.
- Não construa UI interativa em arquivos
.astro. O Astro não tem reatividade. Tentar adicionar interatividade a um arquivo.astroproduz código frágil e não testável.
Qual framework — SolidJS ou React?
O projeto usa um consistentemente. Verifique astro.config.mjs para a integração configurada
(@astrojs/solid-js ou @astrojs/react) e use esse framework para todas as ilhas no projeto. Não misture ambos os frameworks no mesmo projeto.
Leia ./references/islands-and-hydration.md para o guia de decisão completo e referência de diretivas de hidratação.
Regras de Estilização — CSS Modules em Arquivos Separados
Esta é a regra mais crítica desta skill.
Todo componente Astro, página e layout usa CSS Modules para estilização com escopo.
O CSS reside em um arquivo separado — nunca dentro da tag <style> do Astro.
ComponentName/
├── index.astro ← lógica e marcação do componente
└── styles.module.css ← TODOS os estilos para este componente, sempre um arquivo separado
- Sempre crie
styles.module.cssjunto comindex.astro. - Nunca coloque estilos dentro do bloco
<style>do Astro. - Nunca use atributos
styleinline. - Importe o módulo no topo do fence de frontmatter:
import styles from './styles.module.css' - Aplique classes usando a diretiva
class:listou vinculação direta de classe:<div class={styles.container}><div class:list={[styles.container, isActive && styles.active]}>
- Use nomes de classe semânticos. Sem empilhamento de classes utilitárias.
- Use propriedades customizadas CSS para todos os tokens de design (cores, espaçamento, tipografia).
- Sem
!important. Sem seletores profundos. Sem seletores de ID para estilização.
Leia ./references/styling-and-css-modules.md para estratégia de tokens, variáveis de tema,
regras responsivas e orientação sobre animações.
Leia ./examples/button-component/ para um exemplo completo de Button com arquivo
CSS Module separado.
Estrutura do Projeto
src/
├── components/
│ ├── foundation/ # Primitivos de UI interativos — SolidJS ou React, NÃO .astro
│ │ ├── Button/
│ │ │ ├── index.tsx ← SolidJS (.tsx) ou React (.tsx)
│ │ │ └── styles.module.css
│ │ └── Input/
│ │ ├── index.tsx
│ │ └── styles.module.css
│ ├── layout/ # Estrutura de layout estática — .astro
│ │ ├── Header/
│ │ │ ├── index.astro
│ │ │ └── styles.module.css
│ │ └── Footer/
│ │ ├── index.astro
│ │ └── styles.module.css
│ └── features/ # Áreas de funcionalidade interativas — SolidJS ou React
│ └── SomeFeature/
│ ├── index.tsx ← componente ilha
│ └── styles.module.css
├── layouts/
│ └── BaseLayout/
│ ├── index.astro ← estrutura de layout é sempre .astro
│ └── styles.module.css
├── pages/
│ ├── index/
│ │ ├── index.astro ← página é sempre .astro
│ │ └── styles.module.css
│ └── [dynamic]/
│ ├── index.astro
│ └── styles.module.css
├── content/
│ ├── blog/
│ └── [nome-da-colecao]/
├── content.config.ts ← Esquemas e carregadores de coleção Astro 5
├── store/
│ ├── repository/
│ ├── service/
│ └── config.ts
├── styles/
│ ├── tokens/
│ │ ├── _colors.css
│ │ ├── _spacing.css
│ │ └── _typography.css
│ ├── global.css
│ └── themes/
│ ├── light.css
│ └── dark.css
└── utils/
Convenções de nomenclatura:
- Páginas e layouts
.astro: pastaPascalCase/comindex.astro - Componentes ilha de framework: pasta
PascalCase/comindex.tsx - Páginas: pasta
kebab-case/comindex.astroou[dynamic]/comindex.astro - Arquivos CSS Module: sempre
styles.module.css— um por diretório de componente - Utilitários:
kebab-case.ts
Leia ./references/project-structure.md para uma descrição completa das responsabilidades
dos diretórios e convenções de nomenclatura.
Forma do Componente Astro
Arquivos .astro são apenas para estrutura estática. Eles renderizam HTML a partir de props e
dados — eles não lidam com eventos nem gerenciam estado.
- Use props tipadas via
interface Propsno fence de frontmatter. - Acesse props com
Astro.props. - Mantenha os componentes pequenos e com propósito único.
- Prefira composição em vez de prop drilling.
- Mantenha expressões simples; mova lógica complexa para variáveis de frontmatter.
- Use elementos HTML semânticos —
<section>,<article>,<nav>,<main>,<header>— em vez de wrappers genéricos<div>quando o elemento tiver significado semântico.
---
import styles from './styles.module.css'
interface Props {
title: string
subtitle?: string
}
const { title, subtitle } = Astro.props
---
<section class={styles.hero} aria-label={title}>
<h1 class={styles.title}>{title}</h1>
{subtitle && <p class={styles.subtitle}>{subtitle}</p>}
<slot />
</section>
Leia ./references/component-patterns.md para convenções de frontmatter, uso de slots
e referência da API Astro.
Componentes Fundamentais — SolidJS ou React, Não Astro
Primitivos fundamentais de UI (Button, Input, Alert, Modal, Select, Toggle, etc.)
são sempre construídos como componentes SolidJS ou React. Eles nunca são arquivos .astro.
Por quê: Componentes fundamentais lidam com eventos do usuário, gerenciam foco, expõem
callbacks onClick e onChange e, às vezes, mantêm estado interno. Nada disso é
possível em um arquivo .astro. Construir um "botão" como .astro produz HTML estático
que não pode responder a cliques de forma tipada e reutilizável.
A regra de decisão:
- Primitivo existe — use-o.
- Primitivo está próximo, mas falta uma prop — estenda o primitivo existente.
- Primitivo não existe — crie-o como um componente SolidJS ou React em
components/foundation/antes de usá-lo. Nunca crie elementos interativos avulsos inline em componentes de página ou funcionalidade.
Todos os componentes fundamentais devem ser consistentes, acessíveis e fortemente tipados.
Consulte a skill solid.js ou react para as convenções de implementação que se aplicam
dentro de componentes ilha.
Ilhas e Hidratação
Todo componente interativo é uma ilha. Monte ilhas a partir de páginas .astro e
layouts usando uma diretiva client:*. Escolha a diretiva mínima que satisfaça
o requisito de interação.
| Diretiva | Quando usar |
|---|---|
client:load | Deve ser interativo imediatamente no carregamento da página |
client:idle | Pode esperar até o navegador ficar ocioso |
client:visible | Só precisa hidratar quando entra no viewport |
client:media="(query)" | Só interativo em um tamanho de viewport específico |
client:only="solid-js" ou client:only="react" | Requer APIs do navegador na renderização; pule SSR |
Padrão: use client:visible ou client:idle. Use client:load apenas para UI com a qual
o usuário interagirá imediatamente — formulários principais, dropdowns de navegação, páginas de autenticação.
Componentes ilha sempre têm seu próprio styles.module.css:
components/features/ContactForm/
├── index.tsx ← Ilha SolidJS ou React
└── styles.module.css ← CSS Module separado, mesma regra de todos os outros lugares
Montando uma ilha a partir de uma página Astro:
---
import styles from './styles.module.css'
import ContactForm from '../../components/features/ContactForm/index.tsx'
const { prefillEmail } = Astro.props
---
<section class={styles.section}>
<h2 class={styles.heading}>Contact Us</h2>
<ContactForm client:visible prefillEmail={prefillEmail} />
</section>
Leia ./references/islands-and-hydration.md para o guia de decisão completo,
notas específicas do framework e regras de passagem de dados.
Coleções de Conteúdo
Coleções de conteúdo são a forma canônica de gerenciar arquivos Markdown, MDX e dados estruturados com segurança total de tipos TypeScript.
Principais mudanças do Astro 5:
- Config vive em
src/content.config.ts(nãosrc/content/config.ts) - Coleções usam um
loader—glob()oufile()deastro/loaders render(entry)é uma função importada deastro:content(nãoentry.render())- Importe
zdeastro:content, não diretamente dezod
// src/content.config.ts
import { defineCollection, z, reference } from 'astro:content'
import { glob } from 'astro/loaders'
const blog = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/blog' }),
schema: z.object({
title: z.string(),
pubDate: z.coerce.date(),
draft: z.boolean().default(false),
}),
})
export const collections = { blog }
Renderizar em uma página:
---
import { getEntry, render } from 'astro:content'
const post = await getEntry('blog', Astro.params.slug)
const { Content } = await render(post)
---
<Content />
Leia ./references/content-collections.md para a API completa: loaders, referências
cruzadas entre coleções, loaders personalizados, coleções em tempo de execução e padrões
de rota dinâmica.
Ilhas de Servidor, SSR e Actions
Ilhas de Servidor (server:defer)
Adie um componente .astro personalizado ou dinâmico enquanto serve a estrutura da página
imediatamente. Requer um adaptador.
<UserCart server:defer>
<span slot="fallback">···</span>
</UserCart>
O componente adiado é executado no lado do servidor e transmitido em streaming. Use-o para UI específica do usuário (contagens de carrinho, notificações, saudações personalizadas) que, de outra forma, bloquearia a entrega de páginas estáticas.
Renderização Sob Demanda (SSR)
Opte por páginas para renderização no servidor com export const prerender = false (modo híbrido)
ou defina output: 'server' globalmente.
Páginas SSR têm acesso a Astro.cookies, Astro.request, Astro.redirect(),
e Astro.locals (preenchido pelo middleware).
Middleware
Defina lógica de interceptação de requisições em src/middleware.ts:
import { defineMiddleware } from 'astro:middleware'
export const onRequest = defineMiddleware(async (context, next) => {
context.locals.user = await getUser(context.cookies.get('session')?.value)
return next()
})
Astro Actions
Funções de servidor seguras por tipo definidas em src/actions/index.ts, chamáveis a partir de
ilhas ou formulários HTML:
// src/actions/index.ts
import { defineAction, ActionError } from 'astro:actions'
import { z } from 'astro:content'
export const server = {
newsletter: {
subscribe: defineAction({
input: z.object({ email: z.string().email() }),
handler: async ({ email }) => {
await addSubscriber(email)
return { success: true }
},
}),
},
}
Chame a partir de uma ilha:
import { actions } from 'astro:actions'
const { data, error } = await actions.newsletter.subscribe({ email })
Use isInputError(error) para distinguir erros de validação Zod de erros do handler.
Leia ./references/server-rendering.md para cobertura completa: modos de renderização,
configuração de adaptador, middleware, ilhas de servidor, APIs sob demanda, actions com formulários,
códigos de erro, env vars tipadas (astro:env) e transições de visualização.
Referência da API Astro
Astro.props— props tipadas do componenteAstro.params— parâmetros de rota dinâmica ([slug],[...path])Astro.request— objeto de requisição do lado do servidor (cabeçalhos, cookies, URL)Astro.url— URL da página atualgetStaticPaths()— enumera caminhos para geração de site estáticogetEntry()/getCollection()— consultas de coleção de conteúdo
Fluxo de Dados da Camada de Serviço
Páginas e layouts Astro são o local correto para chamar funções de serviço ou repositório no fence de frontmatter. Componentes devem receber dados como props.
- Busque dados no frontmatter da página, não dentro de componentes.
- Passe dados para baixo como props tipadas.
- Componentes não devem chamar repositórios ou APIs externas diretamente.
- Mantenha validação e lógica de negócios na camada de serviço.
Acessibilidade
- Use elementos HTML semânticos sempre que o elemento tiver significado.
- Adicione atributos ARIA onde eles adicionam informações semânticas reais.
- Garanta que todos os elementos interativos tenham nomes acessíveis.
- Mantenha estados de foco visíveis.
- Mantenha um tamanho mínimo de alvo de toque de 44px para elementos interativos.
- Respeite
prefers-reduced-motion. - Estruture cabeçalhos logicamente (
h1→h2→h3) dentro do conteúdo da página.
Leia ./references/accessibility-patterns.md para padrões ARIA, rótulos de formulário
e orientação de hierarquia de cabeçalhos.
Arquivos de Suporte
./references/styling-and-css-modules.mdRegras de CSS Modules
…
[truncado para tradução]