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.
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.
Artigos relacionados
Workflow Obsidian para CLAUDE.md com Claude Code
Transforme notas de trabalho do Obsidian em notas operacionais CLAUDE.md para preservar contexto.
Claude Code Revenue CTA Routing: artigos para PDF, Gumroad e consultoria
Um fluxo com Claude Code para levar leitores ao PDF grátis, Gumroad ou consultoria conforme intenção.
Regras de handoff para equipes com Claude Code: evidências, permissões, rollback e receita
Formato prático para entregar trabalho do Claude Code com prova, permissões, rollback, PDF grátis, Gumroad e consultoria.