Quản lý nội dung quy mô lớn với Astro Content Collections
Astro Content Collections là 'vũ khí bí mật' giúp bạn quản lý hàng trăm bài viết Markdown với Type Safety tuyệt đối. Hướng dẫn setup chuẩn production.
Nếu bạn đã từng quản lý một blog Markdown/Jekyll ngày xưa, chắc chắn bạn đã gặp cảnh này: Code chạy ngon lành ở máy mình, nhưng deploy lên thì “bùm” - lỗi 500 chỉ vì mộ bài viết nào đó quên mất trường date hoặc gõ nhầm draft: "true" (string) thay vì true (boolean).
Astro sinh ra Content Collections để giải quyết triệt để vấn đề này. Nó mang lại sức mạnh của TypeScript và Validation (dùng Zod) vào ngay trong cấu trúc thư mục nội dung của bạn. Với tôi, đây là tính năng “ăn tiền” nhất của Astro so với các SSG khác.
Content Collections là gì?
Đơn giản thôi, thay vì vứt file markdown lung tung trong pages/, bạn gom chúng vào src/content/. Astro sẽ tự động scan, validate và cung cấp Type cho data của bạn.
Cấu trúc thư mục chuẩn:
src/content/
config.ts <-- Nơi định nghĩa Schema
blog/ <-- Collection tên là "blog"
post-1.md
post-2.md
Thiết lập Schema (The “Type-Safe” Magic)
Đây là bước quan trọng nhất. Trong src/content/config.ts, bạn định nghĩa “luật chơi” cho nội dung.
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
type: 'content', // v2.5+ hỗ trợ cả 'data' (JSON/YAML)
schema: z.object({
title: z.string().max(60, "Tiêu đề dài quá, SEO không thích đâu!"),
description: z.string(),
pubDate: z.date(),
isDraft: z.boolean().default(false),
tags: z.array(z.string()).optional(),
// Relation (mới): Link tới author trong collection khác
author: z.string().default('Anonymous'),
}),
});
export const collections = {
'blog': blogCollection,
};
Nhìn đoạn code trên xem, tôi cực thích cách dùng z.string().max(60). Nếu tôi lỡ tay viết title dài 70 ký tự? Build sẽ thất bại ngay lập tức và báo lỗi rõ ràng. Không còn chuyện lỗi runtime ngớ ngẩn trên production nữa.
Query dữ liệu siêu dễ dàng
Ngày xưa dùng Next.js (bản cũ) đọc markdown tôi phải cài gray-matter, fs đọc file, rồi parse tay. Với Astro, nó là native API.
---
// src/pages/blog/index.astro
import { getCollection } from 'astro:content';
// Lấy tất cả bài viết không phải nháp, sắp xếp mới nhất
const posts = await getCollection('blog', ({ data }) => {
return data.isDraft !== true;
});
const sortedPosts = posts.sort((a, b) =>
b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
);
---
<ul>
{sortedPosts.map(post => (
<li>
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
<p>{post.data.description}</p>
</li>
))}
</ul>
Mọi thứ đều được TypeScript gợi ý (IntelliSense). Gõ post.data. là nó hiện ra title, pubDate… Cảm giác code rất yên tâm.
Mẹo thực tế cho dự án lớn (Pro Tips)
-
Dùng
referencecho Author/Category: Astro mới cập nhật tính năngreference. Bạn có thể tạo collectionauthorsvà trongblogschema dùngz.reference('authors'). Nó giống như Foreign Key trong SQL vậy, đảm bảo bạn không bao giờ điền tên author không tồn tại. -
Validate ảnh cover: Dùng
image()helper của Astro trong schema để validate ảnh local.schema: ({ image }) => z.object({ cover: image().refine((img) => img.width >= 1080, { message: "Ảnh cover phải HD (>= 1080px) nhé!", }), })
Kết luận
Astro Content Collections biến việc quản lý Markdown từ “lỏng lẻo” thành “chặt chẽ”. Nếu bạn đang làm blog, portfolio hay documentation site, đừng bao giờ bỏ qua tính năng này. Nó giúp bạn ngủ ngon hơn vì biết chắc chắn rằng cấu trúc dữ liệu của mình luôn đúng chuẩn trước khi đến tay người dùng.
Lợi ích lớn nhất của Content Collections trong Astro là gì?
Thử Thách Kiến Thức Lịch Sử?
Khám phá hàng trăm câu hỏi trắc nghiệm lịch sử thú vị tại HistoQuiz. Vừa học vừa chơi, nâng cao kiến thức ngay hôm nay!