O Astro fornece as páginas, layouts, componentes e renderização do servidor para um site EmDash. Este guia abrange os conceitos do Astro usados pelos templates atuais do EmDash. Pressupõe-se que você já compreende os temas do WordPress e os templates PHP.
Para funcionalidades do framework que não são específicas do EmDash, use a documentação do Astro.
Estrutura do projeto
Um site Astro atribui a cada tipo de arquivo um diretório explícito. Os templates atuais do EmDash usam esta estrutura:
| WordPress | Astro | Propósito |
|---|---|---|
index.php, single.php, page.php | src/pages/ | Rotas de URL |
template-parts/ | src/components/ | Markup reutilizável |
header.php e footer.php | src/layouts/ | Estruturas de página compartilhadas |
style.css | src/styles/ | Estilos do site |
| Configuração de plugins e banco de dados | astro.config.mjs | Integrações e adaptador de servidor |
| Dados de configuração do tema | seed/seed.json | Coleções, menus e conteúdo de exemplo |
O template do blog usa diretórios de rotas que correspondem às suas URLs públicas:
src/
├── components/
│ └── PostCard.astro
├── layouts/
│ └── Base.astro
├── pages/
│ ├── index.astro
│ ├── pages/
│ │ └── [slug].astro
│ └── posts/
│ ├── index.astro
│ └── [slug].astro
└── live.config.ts
Componentes Astro
Um componente .astro combina TypeScript do lado do servidor com um template HTML. O código entre os delimitadores --- é executado no servidor. O markup abaixo do segundo delimitador se torna o HTML de resposta.
O seguinte componente declara props no seu frontmatter e os renderiza no seu template:
---
interface Props {
title: string;
excerpt?: string;
href: string;
}
const { title, excerpt, href } = Astro.props;
---
<article>
<h2><a href={href}>{title}</a></h2>
{excerpt && <p>{excerpt}</p>}
</article>
O Astro faz escape dos valores renderizados com {value}. Importações, consultas ao banco de dados e outras operações do servidor pertencem ao frontmatter.
Expressões de template
Os templates Astro usam chaves onde um template PHP mudaria para <?php ?>. Os padrões mais comuns nos templates EmDash são valores, condições e mapeamento de arrays:
| Objetivo | Sintaxe Astro |
|---|---|
| Imprimir um valor | {post.data.title} |
| Renderizar quando um valor existe | {post.data.excerpt && <p>{post.data.excerpt}</p>} |
| Escolher entre dois resultados | {posts.length === 0 ? <p>Nenhuma publicação ainda.</p> : <PostList />} |
| Renderizar uma lista | {posts.map((post) => <PostCard title={post.data.title} excerpt={post.data.excerpt} href={"/posts/" + post.id} />)} |
A expressão pode usar variáveis preparadas no frontmatter, valores de Astro.props ou dados retornados por uma consulta EmDash. O Astro faz escape de valores de string por padrão; use um renderizador como <PortableText /> para texto rico estruturado em vez de injetar HTML.
Props e slots
Props são comparáveis aos $args passados para get_template_part(). Eles tornam cada entrada explícita e podem ser verificados pelo TypeScript.
Slots permitem que um pai passe markup para um componente. Um slot padrão é útil para o conteúdo da página, enquanto slots nomeados fornecem pontos de inserção adicionais:
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
<article>
<h2>{title}</h2>
<slot />
<footer><slot name="footer" /></footer>
</article>
A seguinte página preenche ambos os slots:
---
import Card from "../components/Card.astro";
---
<Card title="Última publicação">
<p>O conteúdo principal do cartão.</p>
<a slot="footer" href="/posts/latest">Ler a publicação</a>
</Card>
Slots são locais à chamada do componente. Eles não se comportam como as ações do WordPress, que podem receber callbacks registrados em outro lugar.
Layouts
Um layout possui a estrutura de documento compartilhada que um tema WordPress frequentemente divide entre header.php e footer.php. As páginas importam o layout e passam seu conteúdo através do seu slot.
O seguinte layout fornece uma estrutura de documento:
---
interface Props {
title: string;
}
const { title } = Astro.props;
---
<!doctype html>
<html lang="pt">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{title}</title>
</head>
<body>
<header><a href="/">Meu site</a></header>
<main><slot /></main>
</body>
</html>
A seguinte página fornece o título e o conteúdo principal do layout:
---
import Base from "../layouts/Base.astro";
---
<Base title="Início">
<h1>Últimas publicações</h1>
</Base>
Roteamento baseado em arquivos
Arquivos em src/pages/ definem rotas. Nomes de arquivo entre colchetes criam segmentos dinâmicos.
| Arquivo | URL |
|---|---|
src/pages/index.astro | / |
src/pages/posts/index.astro | /posts |
src/pages/posts/[slug].astro | /posts/hello-world |
src/pages/pages/[slug].astro | /pages/about |
Dentro de src/pages/posts/[slug].astro, Astro.params.slug contém o valor da URL. Leia Roteamento Astro para parâmetros rest, redirecionamentos e outras funcionalidades de roteamento.
Renderização do servidor
Os templates atuais do EmDash usam output: "server" em astro.config.mjs. Uma página pode, portanto, consultar o banco de dados a cada requisição, de modo que o conteúdo publicado não depende de uma nova compilação estática.
Não adicione getStaticPaths() a uma rota de tema EmDash a menos que o site trate deliberadamente o EmDash como uma fonte de dados em tempo de compilação. Os temas fornecidos são renderizados no servidor.
Leia Renderização sob demanda do Astro para o comportamento no nível do framework.
Consultar conteúdo EmDash
O EmDash encapsula as coleções de conteúdo ao vivo do Astro com getEmDashCollection() e getEmDashEntry(). Os resultados de coleções contêm um array entries. Os resultados de uma única entrada contêm entry, que é null quando nenhuma entrada publicada corresponde.
O seguinte arquivo usa a mesma ordenação e identificadores do template de blog atual:
---
import { getEmDashCollection } from "emdash";
import Base from "../../layouts/Base.astro";
const { entries: posts, error } = await getEmDashCollection("posts", {
orderBy: { published_at: "desc" },
});
if (error) {
return new Response("Não foi possível carregar as publicações", { status: 500 });
}
---
<Base title="Publicações">
{posts.map((post) => (
<article>
<h2><a href={`/posts/${post.id}`}>{post.data.title}</a></h2>
{post.data.excerpt && <p>{post.data.excerpt}</p>}
</article>
))}
</Base>
post.id é o identificador de rota exposto pelo Astro e normalmente é o slug da entrada. post.data.id é o identificador do banco de dados. Use data.id quando uma API espera o ID de conteúdo armazenado, como funções auxiliares de taxonomia ou comentários.
A seguinte rota dinâmica procura uma publicação pelo slug na URL e renderiza seu campo Portable Text:
---
import { decodeSlug, getEmDashEntry } from "emdash";
import { PortableText } from "emdash/ui";
import Base from "../../layouts/Base.astro";
const slug = decodeSlug(Astro.params.slug);
if (!slug) return Astro.redirect("/404");
const { entry: post, error } = await getEmDashEntry("posts", slug);
if (error) return new Response("Não foi possível carregar a publicação", { status: 500 });
if (!post) return Astro.redirect("/404");
---
<Base title={post.data.title}>
<article>
<h1>{post.data.title}</h1>
<PortableText value={post.data.content} />
</article>
</Base>
Continuar com Astro
Os templates EmDash também usam estilos de componentes e pequenos scripts de navegador, mas essas são funcionalidades comuns do Astro e não conceitos do EmDash. Leia Estilos e CSS para estilos com escopo e globais, e Scripts e manipulação de eventos quando um componente precisa de comportamento do lado do navegador.