4
Format Berkas dan Aturan Kontribusi
Satu layanan di FreeStuffDev disimpan sebagai satu berkas Markdown di src/content/tools. README meminta kontributor membuat berkas baru berekstensi .md di direktori itu, misalnya myservice.md, lalu mengisi frontmatter dan isi sesuai template yang disediakan (README.md:30-351). Halaman ini membahas bentuk berkas dan syarat yang harus lolos sebelum berkas diterima. Arti setiap field di schema dibahas terpisah di Skema Content Collection tools.
Alur pemeriksaan sebelum berkas diterima
Sebuah berkas tidak langsung tampil di beranda. Ia melewati lima pemeriksaan berurutan: lokasi berkas, ekstensi, validasi schema, kelayakan layanan, dan bentuk isi.
graph TD
A["Berkas baru: src/content/tools/nama-baru.md"] --> B{"Ekstensi .md dan lokasi benar?"}
B -- "tidak" --> X["Ditolak: berkas tidak terbaca collection"]
B -- "ya" --> C["slug = nama berkas tanpa .md"]
C --> D{"Lolos toolCollection di config.ts?"}
D -- "field wajib kosong, createdAt bukan date" --> Y["Ditolak: error validasi schema"]
D -- "ya" --> E{"Gratis atau free trial minimal 1 tahun?"}
E -- "trial 7 hari atau tanpa free plan" --> F["Isi isPaid: true"]
E -- "ya" --> G["Tanpa isPaid"]
F --> H{"Bukan library, framework-specific, atau tautan docs?"}
G --> H
H -- "salah satu terpenuhi" --> Z["Ditolak: di luar cakupan README"]
H -- "ya" --> I["Body: satu fitur gratis per baris"]
I --> J["Diterima: tampil di Card"]
style A fill:#f59e0b,color:#000
style B fill:#f59e0b,color:#000
style C fill:#8b5cf6,color:#fff
style D fill:#f59e0b,color:#000
style E fill:#f59e0b,color:#000
style F fill:#f59e0b,color:#000
style G fill:#2d7d46,color:#fff
style H fill:#f59e0b,color:#000
style I fill:#8b5cf6,color:#fff
style J fill:#2d7d46,color:#fff
style X fill:#dc2626,color:#fff
style Y fill:#dc2626,color:#fff
style Z fill:#dc2626,color:#fff
%% fig: Alur pemeriksaan berkas sebelum diterima
%% desc: Berkas baru melewati pemeriksaan lokasi, ekstensi, schema, kelayakan layanan, dan bentuk isi sebelum tampil di Card.Node pertama bukan formalitas: hanya berkas di src/content/tools yang masuk collection tools, dan collection itu memakai objek z.object dari config.ts sebagai gerbang kedua (src/content/config.ts:3-142). Dua kegagalan di kiri diagram bersifat memblokir, sedangkan cabang isPaid tidak memblokir apa pun.
Template frontmatter
Template resmi dari README berisi tujuh field dan contoh isi body tiga baris (README.md:37-493):
---
title: "Your service name"
link: "https://link.to.service"
thumbnail: "https://any.logo.of/service"
snippet: "Service description, which will be shown under service name"
tags: ["Tag1","Tag2","TagN"]
createdAt: 2021-06-21T18:55:27+03:00
---
free feature 1
free feature 2
free feature 3
Field yang sama divalidasi oleh schema collection (src/content/config.ts:3-142):
| Field | Tipe di config.ts | Wajib | Catatan |
|---|---|---|---|
title | z.string() | ya | nama layanan yang tampil di kartu |
snippet | z.string() | ya | deskripsi pendek di bawah nama |
link | z.string() | ya | URL layanan |
tags | z.array(z.string()) | ya | minimal satu tag |
thumbnail | z.string().optional() | tidak | boleh dihilangkan |
createdAt | z.date() | ya | diisi timestamp, bukan string bebas |
updatedAt | z.date().optional() | tidak | tidak dipakai satu pun berkas di src/content/tools |
isPaid | z.boolean().optional() | tidak | penanda layanan berbayar |
Urutan field tidak mengikat. Berkas supabase.md menaruh snippet bentuk folded >- lalu tags satu baris berisi lima entri (src/content/tools/supabase.md:1-104), sedangkan firebase.md memakai pola yang sama dengan tag lebih banyak (src/content/tools/firebase.md:1-105). Berkas planetscale.md menaruh isPaid: true sebelum createdAt, dan urutan itu tetap valid (src/content/tools/planetscale.md:8-96).
thumbnail layak dihilangkan karena kartu merender <img src={tool.data.thumbnail}> dengan width="80" dan onerror="removeMe(this)", sehingga gambar yang gagal dimuat dibuang dari kartu (src/components/Card.astro:29-367). README meminta hindari favicon 16x16 karena gambar diperkecil ke 80x80 (README.md:53-558). Berkas free-asp-net-mvc-hosting.md bahkan menulis thumbnail : "" dengan spasi sebelum titik dua dan string kosong (src/content/tools/free-asp-net-mvc-hosting.md:49).
Konvensi nama berkas .md
Nama berkas tanpa ekstensi menjadi slug, dan slug dipakai untuk menyusun alamat. Tautan Edit di kartu dibentuk dari pola https://github.com/hilmanski/freeStuffDev/edit/main/src/content/tools/${tool.slug}.md, jadi mengganti nama berkas sama dengan mengganti identitas tool di semua tautan (src/components/Card.astro:6610).
Form submit menormalkan nama berkas lewat generateFileName: spasi dan titik diganti -, tanda kutip di-escape, lalu seluruhnya dijadikan huruf kecil (src/pages/submit.astro:137-14011). Berkas yang dihasilkan form juga memakai createdAt: ${new Date().toISOString()} sehingga timestamp selalu ISO (src/pages/submit.astro:121-12912). Alur form sampai pull request dijelaskan di Alur Form Submit ke Pull Request.
⚠️ Tautan cadangan di halaman submit masih memuat template dengan placeholder
YYYY-MM-DDT00:00:00+00:00dalam bentuk URL-encoded (src/pages/submit.astro:8413). Placeholder itu harus diganti timestamp nyata, sebabcreatedAtdivalidasi sebagaiz.date()(src/content/config.ts:3-142).
Isi body: satu fitur per baris
Body Markdown dirender di dalam blok berlabel "Free Offer" dengan class="whitespace-pre-line", jadi setiap baris baru dipertahankan apa adanya (src/components/Card.astro:46-5714). README meminta tiap fitur gratis ditulis satu per baris di akhir berkas (README.md:53-558). Berkas supabase.md mematuhi pola itu: satu kemampuan atau satu batas kuota per baris, seperti Database space (Up to 500MB) dan Storage Up to 1GB (src/content/tools/supabase.md:12-1915).
Body boleh kosong. heroku.md berhenti tepat di --- penutup tanpa satu baris pun isi (src/content/tools/heroku.md:1-1316), dan karena kondisi tool.body && tidak terpenuhi, blok "Free Offer" tidak dirender untuk tool itu (src/components/Card.astro:46-5714).
Tags tanpa spasi setelah koma
Form menggabungkan input tag hanya dengan replace(/,/g, '","'), tanpa memangkas spasi (src/pages/submit.astro:10417). Akibatnya entri seperti " baas" ikut tersimpan dengan spasi di depan, dan itu benar-benar ada di berkas aws-amplify.md (src/content/tools/aws-amplify.md:818). Dampaknya pada pengelompokan tag dibahas di Indeks Tag dan Halaman Tag.
Batas kelayakan layanan
README memberi empat batas yang menentukan berkas diterima atau ditolak (README.md:14-2019):
| Aturan | Isi | Rujukan |
|---|---|---|
| Batas bawah penawaran | layanan gratis atau free trial minimal 1 tahun | README.md:14-2019 |
| Penawaran di bawah batas | trial 7 hari saja, atau tanpa penawaran gratis, ditandai isPaid: true | README.md:14-2019 |
| Tool khusus bahasa atau framework | tidak diterima | README.md:14-2019 |
| Tautan "bagian dari tool tertentu" | misalnya tema untuk hugo, tidak diterima | README.md:14-2019 |
| Library bahasa atau framework | misalnya library JavaScript, tidak diterima | README.md:14-2019 |
| Dokumentasi atau forum sebuah tool | tidak diterima | README.md:14-2019 |
⚠️
isPaid: truebukan tombol hapus. Berkas tetap lolos build dan tetap ada di collection, tetapi beranda menyaringnya dengandata.isPaid !== true(src/pages/index.astro:8-1120). Konsekuensi penyaringan itu diuraikan di Beranda dan Pencarian Klien dan Halaman Recent dan Pengurutan.