Episode ini membahas pengelolaan konten di Astro: menulis dengan Markdown dan MDX, content collections dengan schema yang tervalidasi, frontmatter dan metadata, serta cara menampilkan konten dinamis di halaman statis.

Astro adalah framework untuk situs berbasis konten, dan episode 5 ini berada di jantungnya: bagaimana kalian menulis, mengelola, dan menampilkan konten. Di sinilah kekuatan Astro yang paling terasa — konten Markdown diubah menjadi halaman yang cepat dengan validasi yang ketat.
Kalian akan belajar tiga hal besar: menulis konten dengan Markdown dan MDX, mendefinisikan content collections dengan schema yang tervalidasi di build time, dan menyusun frontmatter sebagai metadata terstruktur untuk setiap konten.
Di akhir episode, kalian bisa membangun blog atau dokumentasi dengan Astro — konten ditulis oleh siapa pun, dan halaman tersusun secara otomatis.
File .md di src/pages otomatis menjadi halaman. Buat src/pages/blog/satu.md:
---
title: "Artikel Pertama"
description: "Contoh artikel markdown"
published: "2026-08-10"
---
## Pendahuluan
Ini adalah konten yang ditulis dengan **Markdown**. Astro merender
file ini menjadi halaman HTML statis saat build.
- Daftar item satu
- Daftar item duaFrontmatter di antara --- menjadi metadata halaman, dan isi file menjadi body. Yang perlu diperhatikan: penulisan published: "2026-08-10" di frontmatter adalah deklarasi metadata — belum ada validasi apa pun sampai kita mendefinisikan collection.
Jika konten butuh komponen interaktif, gunakan MDX. Aktifkan dulu integrasinya:
npx astro add mdxSetelah itu file .mdx bisa memakai komponen langsung di dalam konten. Perbedaan kunci: Markdown hanya teks terstruktur, sedangkan MDX memungkinkan JSX dan komponen di dalam konten.
Content collections mengubah Markdown dari "kumpulan file" menjadi "data tervalidasi". Definisi collection diletakkan di src/content.config.ts (Astro 5) atau src/content/config.ts (versi sebelumnya):
import { defineCollection, z } from "astro:content";
const blog = defineCollection({
type: "content",
schema: z.object({
title: z.string(),
description: z.string().optional(),
published: z.date(),
tags: z.array(z.string()),
}),
});
export const collections = { blog };Schema di atas menggunakan z.object dari Zod. Saat build, Astro memvalidasi seluruh frontmatter terhadap schema — jika title hilang atau published bukan tanggal, build akan gagal dengan pesan yang jelas.
File konten untuk collection blog diletakkan di src/content/blog. Kalian bisa menyortir konten dengan order() atau menandai draft dengan .draft(). Metadata lengkap seperti published dan tags memungkinkan halaman melakukan filtering, sorting, dan grouping.
Untuk membuat halaman daftar blog, query collection dengan getCollection:
---
import { getCollection } from "astro:content";
const posts = (await getCollection("blog")).sort(
(a, b) => b.data.published.valueOf() - a.data.published.valueOf(),
);
---
<h1>Daftar Artikel</h1>
<ul>
{posts.map((post) => (
<li>
<a href={`/blog/${post.id}`}>
{post.data.title} — {post.data.published.toISOString().slice(0, 10)}
</a>
</li>
))}
</ul>getCollection("blog") mengembalikan semua entry yang valid, dan setiap post.data berisi metadata tervalidasi dari schema. List ini dirender menjadi HTML statis — pengunjung tidak perlu menunggu JavaScript apa pun.
Untuk halaman artikel per-slug, kombinasikan collection dengan getStaticPaths:
---
import { getCollection } from "astro:content";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.id },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await render(post);
---
<article>
<h1>{post.data.title}</h1>
<Content />
</article>render(post) menghasilkan komponen konten siap render, dan seluruh halaman dibangun sekali saat build.
Warning
Jangan pernah menaruh file Markdown sembarangan di src/content. Hanya file yang cocok dengan collection yang didefinisikan di content.config.ts yang akan diproses — yang lain akan memicu error build.
Manfaat terbesar content collections adalah konsistensi. Karena setiap field tervalidasi, kontributor tidak mungkin lupa menulis description atau memakai tanggal dengan format salah. Untuk konten yang jumlahnya banyak, gunakan z.enum untuk kategori dan z.url untuk tautan agar nilai selalu valid.
Karena data collection tersedia sebagai struktur data biasa, kalian bisa menghitung jumlah artikel per tag, membuat indeks, atau membangun daftar "postingan terkait" tanpa query tambahan. Semua komputasi berjalan di build time, sehingga halaman tetap statis dan cepat.
Episode 5 membuka kekuatan pengelolaan konten Astro: menulis dengan Markdown dan MDX, mendefinisikan content collections dengan schema Zod, menggunakan frontmatter sebagai metadata terstruktur, dan menampilkan konten dinamis di halaman statis melalui getCollection dan render.
Inti yang harus dibawa pulang:
.md dan .mdx di src/pages otomatis menjadi halaman.src/content.config.ts.getCollection("nama") mengambil semua entry yang valid.getStaticPaths membangun halaman detail untuk setiap entry.render(post) mengubah entry menjadi komponen konten.Di episode 6 selanjutnya kita akan membahas data fetching dan server-side rendering: mengambil data saat build time, mengintegrasi API eksternal, mode SSR dengan adapter, serta progressive dan partial hydration. Konten kalian akan mulai terhubung dengan dunia luar.