- Introdução ao WordPress Headless
- REST API do WordPress: Visão Geral
- Configurando o WordPress como Backend Headless
- Frontend com Next.js: Setup e Integração Inicial
- Listagem de Posts e Roteamento Dinâmico no Next.js
Aqui é o Asllan de novo, trazendo mais um passo dessa nossa trilha WordPress Headless + APIs. Hoje, além de listar os posts, vamos implementar a rota dinâmica /posts/[slug]
, onde cada post terá sua página exclusiva.
Eu, com meus 25 anos de experiência, posso te dizer: essa é uma das partes mais legais do App Router do Next.js, pois permite criar rotas dinâmicas sem complicação, com total controle e performance.
🏗️ Atualizando src/lib/api.ts
Vamos garantir que as funções para buscar os posts e buscar um post pelo slug estejam exportadas e funcionando:
const API_URL = 'https://seudominio.com/wp-json/wp/v2';
export interface WPPost {
id: number;
title: { rendered: string };
excerpt: { rendered: string };
slug: string;
content: { rendered: string };
}
export async function fetchPosts(): Promise<WPPost[]> {
const res = await fetch(`${API_URL}/posts?_embed`);
if (!res.ok) throw new Error('Erro ao buscar posts');
return res.json();
}
export async function fetchPostBySlug(slug: string): Promise<WPPost | null> {
const res = await fetch(`${API_URL}/posts?slug=${slug}&_embed`);
if (!res.ok) return null;
const posts = await res.json();
return posts.length > 0 ? posts[0] : null;
}
🗂️ Exibindo a listagem – src/app/page.tsx
import { fetchPosts, WPPost } from '../lib/api';
import Link from 'next/link';
export default async function Home() {
const posts: WPPost[] = await fetchPosts();
return (
<main className="max-w-4xl mx-auto p-8">
<h1 className="text-4xl font-bold mb-6">Últimos Posts</h1>
<ul className="space-y-4">
{posts.map(post => (
<li key={post.id} className="p-4 bg-white rounded shadow">
<h2 className="text-2xl font-semibold">
<Link href={`/posts/${post.slug}`} className="hover:underline">
{post.title.rendered}
</Link>
</h2>
<div
className="text-gray-600"
dangerouslySetInnerHTML={{ __html: post.excerpt.rendered }}
/>
</li>
))}
</ul>
</main>
);
}
🌐 Criando a rota dinâmica /posts/[slug]
Agora o segredo para mostrar cada post! Vamos criar o arquivo:
src/app/posts/[slug]/page.tsx
import { fetchPostBySlug, WPPost } from '../../../lib/api';
import { notFound } from 'next/navigation';
export default async function PostPage({ params }: { params: { slug: string } }) {
const post: WPPost | null = await fetchPostBySlug(params.slug);
if (!post) {
notFound(); // Mostra página 404 se o post não existir
}
return (
<main className="max-w-3xl mx-auto p-8">
<h1 className="text-4xl font-bold mb-4">{post.title.rendered}</h1>
<article
className="prose"
dangerouslySetInnerHTML={{ __html: post.content.rendered }}
/>
</main>
);
}
🔹 O Next.js App Router usa params.slug
para buscar o post correspondente.
🔹 A função fetchPostBySlug
traz o post com base no slug (ex: ola-mundo
).
🔹 Se o slug não for encontrado, mostramos uma página 404.
🧠 Dicas valiosas
💡 Use o App Router para aproveitar Server Components e ter dados carregados no servidor, melhorando performance.
💡 Use dangerouslySetInnerHTML
com cuidado, para evitar XSS (certifique-se de que o conteúdo da API é seguro).
💡 Aproveite Tailwind CSS para dar estilo às páginas.
🚀 Agora sim!
Acesse:
http://localhost:3000/
✅ Veja a listagem dos posts.
✅ Clique em um post e abra a página:
http://localhost:3000/posts/ola-mundo
✅ O conteúdo completo do post aparecerá lindamente.