Lompat ke konten
dokumentasi.id
Commit 314576d
v1
Star2 rb

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

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-18. Semua halaman yang menampilkan tool membaca entry.data hasil validasi schema ini, sehingga penambahan field harus dimulai dari src/content/config.ts:3-14.

Field yang divalidasi

Tabel berikut memetakan setiap field ke tipe Zod-nya, status wajib, dan contoh nilai yang benar-benar ada di repository.

FieldTipe ZodWajibContoh / perilakuRujukan
titlez.string()yaSupabase; ditampilkan sebagai judul kartusrc/content/config.ts:5
snippetz.string()yadeskripsi singkat di bawah nama toolsrc/content/config.ts:6
linkz.string()yahttps://supabase.io/; dipakai tombol Visitsrc/content/config.ts:7
tagsz.array(z.string())ya["database", "storage", "authentication", "real-time", "postgres-service"]src/content/config.ts:8
thumbnailz.string().optional()tidakURL gambar logo, dirender 80x80src/content/config.ts:9
createdAtz.date()ya2021-06-17T02:56:44.222Zsrc/content/config.ts:10
updatedAtz.date().optional()tidaktidak dibaca halaman mana punsrc/content/config.ts:11
isPaidz.boolean().optional()tidaktrue menampilkan badge Paid Toolsrc/content/config.ts:12

Contoh entry lengkap terlihat pada src/content/tools/supabase.md:1-11. 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.
Fig. 1: Relasi entitas tool dan tagSatu 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-13. 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.
Fig. 2: Jalur field schema ke komponen pembacaBerkas 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-42, sedangkan data.link dipakai pada tautan Visit yang menambahkan parameter utm_source=freestuffdev di src/components/Card.astro:67. Field isPaid mengendalikan badge Paid Tool di src/components/Card.astro:19-25.

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-17; 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-11, 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-14 dan README.md:13-15.

Jebakan yang perlu diingat

⚠️ updatedAt sudah ada di schema tetapi tidak dipakai. Satu-satunya kemunculannya sebagai field adalah src/content/config.ts:11; nilai updatedAt lain di repository hanya bagian query string pada URL thumbnail. Menambahkan field tanggal ini ke frontmatter tidak mengubah tampilan apa pun.

⚠️ thumbnail opsional, tetapi Card.astro tetap merender <img src={tool.data.thumbnail}> dan hanya menyiapkan onerror="removeMe(this)" sebagai jaring pengaman di src/components/Card.astro:29-36. Entry tanpa thumbnail akan 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-55.

Beberapa hal lain yang perlu dijaga saat menambah entry.

  • isPaid belum pernah diset true pada commit ini. Tidak ada berkas di src/content/tools/ yang memuat field itu, jadi seluruh entry lolos filter data.isPaid !== true.
  • tags ditulis 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 setelah trim() 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, dan createdAt, di src/pages/submit.astro:121-129. Karena itu updatedAt dan isPaid tidak 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.