Desenvolvimento Astro com Claude Code: Collections, SSG e validação
Guia prático para criar sites Astro com Claude Code: setup, posts, tags, hidratação e comandos de build.
Por que Claude Code combina com Astro
Astro é uma ótima escolha para blogs, documentação, portfólios, páginas de produto e sites em que a maior parte do conteúdo é lida. Você pode usar componentes React, Vue ou Svelte, mas o Astro não transforma todas as páginas em uma aplicação pesada no cliente. A arquitetura de ilhas mantém conteúdo estático como estático e hidrata no navegador apenas as partes interativas, como busca, filtros ou botões.
Claude Code ajuda mais quando você pede para ele entender o projeto antes de editar. Em Astro, uma página depende de astro.config.mjs, src/content.config.ts, src/pages/, src/components/, imagens, rotas e comandos de build. Se Claude Code lê esses arquivos primeiro e explica o plano, as alterações ficam menores e dependências desnecessárias aparecem mais cedo.
Este guia usa o padrão atual de Content Collections do Astro: src/content.config.ts, astro/loaders e astro/zod. Confira as fontes oficiais antes de aplicar em produção: Claude Code Quickstart, Astro Content Collections, Astro template directives e Astro routing reference. Para decisões de arquitetura, veja também a comparação SSR/SSG e o guia de SEO.
Comece com um escopo claro
Um prompt como “crie um blog Astro” é amplo demais. Claude Code pode mudar design, rotas, modelo de conteúdo e dependências de uma vez. Defina o alvo: site estático de conteúdo, MDX, sitemap, frontmatter tipado, lista de posts, páginas de tags e validação por build.
npm create astro@latest my-astro-site
cd my-astro-site
npx astro add mdx sitemap tailwind
npm run dev
Depois, peça uma leitura antes da edição:
claude "Revise este projeto Astro como um site de conteúdo. Leia astro.config.mjs, src/content.config.ts, src/pages e src/components. Antes de editar, explique o plano de implementação e os comandos de verificação."
A configuração inicial pode ser pequena:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import sitemap from '@astrojs/sitemap';
import tailwind from '@astrojs/tailwind';
export default defineConfig({
site: 'https://example.com',
output: 'static',
integrations: [mdx(), sitemap(), tailwind()],
markdown: {
shikiConfig: {
theme: 'github-dark',
},
},
});
Troque site pelo domínio real antes de publicar. Sitemap, URLs canônicas e parte do SEO dependem desse valor.
Defina Content Collections com a API atual
Content Collections transforma arquivos Markdown e MDX em dados com formato conhecido. Em vez de confiar que todo artigo terá o mesmo frontmatter, você define um schema e o Astro mostra erros antes do deploy. Isso é muito útil em sites multilíngues, onde uma tradução pode alterar por engano um campo fixo.
// src/content.config.ts
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const blog = defineCollection({
loader: glob({
base: './src/content/blog',
pattern: '**/*.{md,mdx}',
}),
schema: z.object({
title: z.string().max(80),
description: z.string().max(120),
pubDate: z.coerce.date(),
updatedDate: z.coerce.date().optional(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
heroImage: z.string().optional(),
}),
});
export const collections = { blog };
Um pedido de revisão específico funciona melhor:
claude "Revise src/content.config.ts para Astro 5. Verifique API atual de Content Collections, tamanho de description, filtro de draft, updatedDate opcional e mistura com APIs antigas."
Esse schema vira um contrato de publicação. Data inválida, descrição longa demais ou tags quebrado aparece antes do site ir ao ar.
Caso 1: lista de posts com paginação
O primeiro caso prático é o índice do blog. Não dependa da ordem retornada por getCollection(). Filtre rascunhos, ordene por data e passe as entradas para um componente de card.
---
// src/pages/blog/[...page].astro
import { getCollection } from 'astro:content';
import PostCard from '../../components/PostCard.astro';
export async function getStaticPaths({ paginate }) {
const posts = (await getCollection('blog', ({ data }) => data.draft !== true))
.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
return paginate(posts, { pageSize: 12 });
}
const { page } = Astro.props;
---
<section class="mx-auto max-w-5xl px-4 py-10">
<h1 class="text-3xl font-bold">Blog</h1>
<div class="mt-8 grid gap-6 md:grid-cols-2">
{page.data.map((post) => <PostCard post={post} />)}
</div>
<nav class="mt-10 flex justify-between">
{page.url.prev ? <a href={page.url.prev}>Previous</a> : <span />}
{page.url.next ? <a href={page.url.next}>Next</a> : <span />}
</nav>
</section>
O card pode ser direto:
---
// src/components/PostCard.astro
import type { CollectionEntry } from 'astro:content';
type Props = {
post: CollectionEntry<'blog'>;
lang?: string;
};
const { post, lang = 'pt' } = Astro.props;
const href = lang === 'ja' ? `/blog/${post.id}/` : `/${lang}/blog/${post.id}/`;
const date = post.data.updatedDate ?? post.data.pubDate;
---
<article class="rounded border border-slate-200 p-5">
<p class="text-sm text-slate-500">
<time datetime={date.toISOString()}>{date.toLocaleDateString('pt-BR')}</time>
</p>
<h2 class="mt-2 text-xl font-semibold">
<a href={href}>{post.data.title}</a>
</h2>
<p class="mt-3 text-slate-700">{post.data.description}</p>
<ul class="mt-4 flex flex-wrap gap-2">
{post.data.tags.map((tag) => <li class="rounded bg-slate-100 px-2 py-1 text-xs">{tag}</li>)}
</ul>
</article>
Esse padrão serve para três cenários comuns: blog técnico pessoal, base de conhecimento interna e changelog de produto. Nos três, preserve metadados antes de mexer no visual.
Caso 2: páginas de tags e hidratação seletiva
O segundo caso é o arquivo por tag. O erro comum é usar o nome do tag diretamente na URL. Espaços, maiúsculas e caracteres não latinos podem criar rotas frágeis. Separe slug de URL e label de exibição.
---
// src/pages/tags/[tag]/[...page].astro
import { getCollection } from 'astro:content';
import PostCard from '../../../components/PostCard.astro';
const tagSlug = (tag) =>
encodeURIComponent(tag.toLowerCase().trim().replace(/\s+/g, '-'));
export async function getStaticPaths({ paginate }) {
const posts = await getCollection('blog', ({ data }) => data.draft !== true);
const groups = new Map();
for (const post of posts) {
for (const label of post.data.tags) {
const slug = tagSlug(label);
const group = groups.get(slug) ?? { slug, label, posts: [] };
group.posts.push(post);
groups.set(slug, group);
}
}
return [...groups.values()].flatMap((group) =>
paginate(group.posts, {
params: { tag: group.slug },
props: { tag: group.label },
pageSize: 10,
}),
);
}
const { page, tag } = Astro.props;
---
<section class="mx-auto max-w-5xl px-4 py-10">
<h1 class="text-3xl font-bold">Tag: {tag}</h1>
<div class="mt-8 grid gap-6 md:grid-cols-2">
{page.data.map((post) => <PostCard post={post} />)}
</div>
</section>
O terceiro caso é uma busca. Não transforme a página inteira em aplicação cliente por causa de um componente:
---
// src/pages/index.astro
import Hero from '../components/Hero.astro';
import SearchBox from '../components/SearchBox.tsx';
import LatestPosts from '../components/LatestPosts.astro';
---
<Hero />
<SearchBox client:visible />
<LatestPosts />
client:load é para interação imediata. client:visible é melhor quando o componente pode esperar até entrar na tela.
Erros comuns e verificação
O primeiro erro é copiar tutoriais antigos de Content Collections. O segundo é pedir para melhorar o site inteiro de uma vez. O terceiro é esquecer heroImage, description e Open Graph. O quarto é achar que build verde basta para publicar. Confira também paginação, links internos, links externos, mobile e CTA.
npm run build
npx astro check
npm run preview
Se o build falhar, peça classificação antes de corrigir:
claude "Leia a falha de npm run build. Classifique como sintaxe Astro, schema de Content Collections, code fence de MDX, geração de rotas ou problema de links. Depois proponha o menor ajuste."
CTA e resultado testado
Quem está começando pode usar a folha de consulta gratuita. Quem precisa de modelos pode ver produtos. Para equipes que querem organizar um site Astro, regras de revisão e adoção do Claude Code, o caminho natural é treinamento e consultoria.
Na prática, Claude Code foi rápido para gerar arquivos .astro e conectar páginas às collections. Ainda assim, precisei revisar API atual do Astro, codificação segura de tags na URL, uso excessivo de client:load e execução real do build. O fluxo mais estável foi ler o projeto, limitar a mudança, comparar com a documentação oficial, rodar build e revisar o preview.
Artigos relacionados
Desenvolvimento Svelte e SvelteKit com Claude Code
Guia pratico para usar Claude Code com Svelte/SvelteKit: setup, runes, rotas, form actions, testes e mudancas seguras.
React com Claude Code em produção: componentes, Hooks, testes e revisão
Use Claude Code no React com componentes tipados, Hooks, testes, acessibilidade, performance e revisão.
Desenvolvimento com Storybook e Claude Code: UI, testes e CI
Configure Storybook com Claude Code: stories tipadas, interaction tests, CI e revisão visual com Chromatic.
PDF grátis: cheatsheet do Claude Code
Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.
Cuidamos dos seus dados e não enviamos spam.
Sobre o autor
Masa
Engenheiro focado em workflows práticos com Claude Code.