3
Skema Content Collection tools
Setiap berkas Markdown di src/content/tools/ adalah satu entry untuk collection tools. Bentuk entry itu ditentukan satu schema Zod yang dideklarasikan dengan defineCollection dan z.object, lalu diekspor sebagai key 'tools' pada objek collections di src/content/config.ts:16-181. Semua halaman yang menampilkan tool membaca entry.data hasil validasi schema ini, sehingga penambahan field harus dimulai dari src/content/config.ts:3-142.
Field yang divalidasi
Tabel berikut memetakan setiap field ke tipe Zod-nya, status wajib, dan contoh nilai yang benar-benar ada di repository.
| Field | Tipe Zod | Wajib | Contoh / perilaku | Rujukan |
|---|---|---|---|---|
title | z.string() | ya | Supabase; ditampilkan sebagai judul kartu | src/content/config.ts:53 |
snippet | z.string() | ya | deskripsi singkat di bawah nama tool | src/content/config.ts:64 |
link | z.string() | ya | https://supabase.io/; dipakai tombol Visit | src/content/config.ts:75 |
tags | z.array(z.string()) | ya | ["database", "storage", "authentication", "real-time", "postgres-service"] | src/content/config.ts:86 |
thumbnail | z.string().optional() | tidak | URL gambar logo, dirender 80x80 | src/content/config.ts:97 |
createdAt | z.date() | ya | 2021-06-17T02:56:44.222Z | src/content/config.ts:108 |
updatedAt | z.date().optional() | tidak | tidak dibaca halaman mana pun | src/content/config.ts:119 |
isPaid | z.boolean().optional() | tidak | true menampilkan badge Paid Tool | src/content/config.ts:1210 |
Contoh entry lengkap terlihat pada src/content/tools/supabase.md:1-1111. Frontmatter di berkas itu mengisi enam field wajib ditambah thumbnail, sementara isi setelah --- menjadi tool.body dan ditampilkan sebagai daftar fitur gratis. Perhatikan bahwa snippet di sana memakai blok YAML >- sehingga satu kalimat panjang boleh terlipat ke beberapa baris.
Relasi tool dan tag
Satu entry menyimpan tags sebagai array string, bukan tabel relasi. Karena satu tag dapat dipakai banyak tool dan satu tool memuat banyak tag, hubungannya many-to-many yang direkonstruksi saat build.
erDiagram
TOOL {
string title
string snippet
string link
string tags "z.array z.string"
string thumbnail "optional"
date createdAt
date updatedAt "optional"
boolean isPaid "optional"
}
TAG {
string name
}
TOOL }o--o{ TAG : "tags"
%% fig: Relasi entitas tool dan tag
%% desc: Satu entry tool menyimpan array tags, satu tag dipakai banyak tool, sehingga relasinya many-to-many yang dihitung ulang dari frontmatter saat build.Daftar tag tidak disimpan di berkas terpisah. AllTags.astro mengambil seluruh collection, memecah data.tags dengan flatMap, lalu menormalkan setiap tag memakai trim().toLowerCase() sebelum menghitung jumlah pemakaian di src/components/AllTags.astro:7-1312. Halaman tag melakukan hal yang sama pada sisi pencarian, yaitu mencocokkan data.tags.includes(tag.trim().toLowerCase()) di src/pages/tags/[slug].astro:26-28. Detail pembentukan halaman tag dibahas di Indeks Tag dan Halaman Tag.
Siapa yang membaca setiap field
graph LR
MD["src/content/tools/*.md"] --> CFG["schema z.object"]
CFG --> DATA["entry.data"]
DATA --> CARD["Card.astro"]
DATA --> RECENT["recent.astro"]
DATA --> TAGS["AllTags.astro"]
DATA --> TAGPAGE["tags/[slug].astro"]
DATA --> SUBMIT["submit.astro"]
style MD fill:#336791,color:#fff
style CFG fill:#f59e0b,color:#000
style DATA fill:#8b5cf6,color:#fff
style CARD fill:#2d7d46,color:#fff
style RECENT fill:#2d7d46,color:#fff
style TAGS fill:#8b5cf6,color:#fff
style TAGPAGE fill:#2d7d46,color:#fff
style SUBMIT fill:#f59e0b,color:#000
%% fig: Jalur field schema ke komponen pembaca
%% desc: Berkas markdown divalidasi schema, lalu entry.data dibaca Card, halaman recent, agregasi tag, halaman tag, dan form submit yang membuat frontmatter baru.Card.astro adalah pembaca terbanyak: data.title, data.snippet, dan data.tags.join(', ') dirender berurutan di src/components/Card.astro:39-4213, sedangkan data.link dipakai pada tautan Visit yang menambahkan parameter utm_source=freestuffdev di src/components/Card.astro:6714. Field isPaid mengendalikan badge Paid Tool di src/components/Card.astro:19-2515.
createdAt dipakai untuk urutan, bukan untuk tampilan tanggal. Halaman recent mengurutkan entry dengan new Date(a.data.createdAt) dan new Date(b.data.createdAt) di src/pages/recent.astro:13-1716; rincian pengurutan ada di Halaman Recent dan Pengurutan.
isPaid juga bertindak sebagai filter. Beranda mengambil collection dengan predikat data.isPaid !== true di src/pages/index.astro:9-1117, sehingga entry bertanda true tidak pernah muncul di sana. Kebijakan penandaan diatur di README: tool yang hanya memberi trial 7 hari atau tanpa penawaran gratis harus ditulis isPaid: true di frontMatter, dan penawaran gratis yang diterima minimal berlaku 1 tahun, seperti pada src/content/config.ts:3-142 dan README.md:13-1518.
Jebakan yang perlu diingat
⚠️
updatedAtsudah ada di schema tetapi tidak dipakai. Satu-satunya kemunculannya sebagai field adalah src/content/config.ts:119; nilaiupdatedAtlain di repository hanya bagian query string pada URL thumbnail. Menambahkan field tanggal ini ke frontmatter tidak mengubah tampilan apa pun.
⚠️
thumbnailopsional, tetapiCard.astrotetap merender<img src={tool.data.thumbnail}>dan hanya menyiapkanonerror="removeMe(this)"sebagai jaring pengaman di src/components/Card.astro:29-3619. Entry tanpathumbnailakan memicu permintaan gambar yang gagal. README meminta gambar berukuran wajar karena setiap gambar diperkecil ke 80x80 dan favicon 16x16 sebaiknya dihindari, sesuai README.md:51-5520.
Beberapa hal lain yang perlu dijaga saat menambah entry.
isPaidbelum pernah disettruepada commit ini. Tidak ada berkas disrc/content/tools/yang memuat field itu, jadi seluruh entry lolos filterdata.isPaid !== true.tagsditulis huruf kecil dan dipisah koma di dalam array. Pencocokan di src/pages/tags/[slug].astro:26-28 menurunkan kedua sisi ke huruf kecil, sedangkan halaman alternatif mencocokkan tag setelahtrim()tanpa menurunkan huruf, sehingga penulisan tag yang tidak konsisten memecah hasil pencarian. Aturan penulisan tag dan isi berkas dijelaskan di Format Berkas dan Aturan Kontribusi.- Form submit menghasilkan frontmatter dengan enam field saja, yaitu
title,link,thumbnail,snippet,tags, dancreatedAt, di src/pages/submit.astro:121-12921. Karena ituupdatedAtdanisPaidtidak pernah terisi lewat form. Alur lengkapnya ada di Alur Form Submit ke Pull Request.
Schema ini juga menjadi kontrak build. astro build memvalidasi setiap berkas terhadap schema, dan pelanggaran tipe menghentikan proses; langkah pemeriksaan itu dibahas di Build, Pemeriksaan Tipe, dan Deploy.