12/06/2026 · 2 phút đọc · cập nhật 18/06/2026
Dựng blog markdown bằng Next.js App Router server-first
Một cấu trúc server-first cho blog markdown: content file, service normalize dữ liệu, page mỏng và route handler khi cần API.
Server-first nghĩa là gì
Với blog markdown, dữ liệu đã nằm trong repository nên không cần đẩy việc load bài viết xuống client. Server Component có thể đọc content qua service, render HTML có metadata đầy đủ và gửi xuống trình duyệt một payload gọn hơn.
Server-first không có nghĩa là không dùng Client Component. Nó chỉ có nghĩa là mặc định dữ liệu và HTML chính nên được xử lý ở server. Client chỉ xuất hiện cho phần thật sự cần browser API, ví dụ thanh tiến trình đọc bài.
Luồng dữ liệu nên dùng
Một luồng gọn cho blog markdown:
src/content/blog/*.md
-> blog-service.ts
-> app/blog/page.tsx hoặc app/blog/[slug]/page.tsx
-> reusable blog components
Service chịu trách nhiệm parse frontmatter, validate field, tính reading time, lọc draft và sort bài viết. Page chỉ gọi service và compose UI.
Vì sao không fetch API nội bộ trong page
Route Handler hữu ích khi cần consumer HTTP thật, nhưng page server không cần gọi chính API của mình để lấy markdown local. Gọi service trực tiếp giảm overhead, tránh serialize không cần thiết và giữ kiểu dữ liệu sát hơn.
API vẫn có thể tồn tại:
export async function GET(_: Request, { params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params
const post = await getBlogPost(slug)
return post
? Response.json({ ok: true, data: post })
: Response.json({ ok: false }, { status: 404 })
}
Điểm chính là API dùng cùng service với page, không tạo logic đọc markdown thứ hai.
Metadata và sitemap
Mỗi bài blog nên có generateMetadata riêng để set title, description, canonical, Open Graph type article, published time, updated time và tags. Sitemap cần lấy cùng danh sách published posts để draft không bị index.
Category page cũng nên có canonical riêng. Khi category có route tường minh, Google và người đọc đều hiểu blog đang có taxonomy rõ ràng.
Kết luận
Một blog markdown tốt không cần CMS ngay từ đầu. Chỉ cần content files có schema rõ, service normalize dữ liệu, routes mỏng và SEO được sinh từ cùng một nguồn dữ liệu. Cấu trúc này đủ đơn giản để cập nhật bằng tay nhưng vẫn đủ sạch để scale.