Static site sering dianggap sederhana karena halaman akhirnya hanya berupa HTML, CSS, JavaScript, gambar, dan beberapa file data. Namun, ketika jumlah artikel mulai bertambah, pekerjaan di belakang layar ikut berkembang: gambar perlu dioptimalkan, metadata harus konsisten, sitemap harus diperbarui, feed perlu dibuat, indeks pencarian harus disinkronkan, dan hasil akhirnya harus dikirim ke hosting.

Repository Layar Kosong menggunakan pendekatan yang mengotomatisasi rangkaian pekerjaan tersebut. Penulis cukup menyiapkan artikel pada direktori staging, melakukan commit dan push ke branch main, lalu GitHub Actions menjalankan proses produksi menggunakan Bun.js dan Cloudflare Wrangler.

Yang menarik bukan sekadar penggunaan layanan cloud, melainkan cara seluruh proses tersebut dirangkai. Artikel tidak langsung disalin mentah ke server. Ia melewati beberapa tahap transformasi sebelum menjadi bagian dari situs production.

Ilustrasi pipeline static site Layar Kosong dengan GitHub Actions, Bun.js, Cloudflare Pages, dan Cloudflare D1
Pipeline publikasi Layar Kosong menghubungkan staging artikel, proses build, indeks pencarian, dan deployment production.

Dari Artikel Staging Menjadi Situs Production

Alur utama Layar Kosong menggunakan satu workflow GitHub Actions bernama ๐Ÿ“ก Artikel Baru Kombo. Workflow tersebut berjalan dalam satu job dan membagi pekerjaan menjadi tiga fase berurutan: pemrosesan artikel, build dan generate site files, kemudian persiapan deployment, sinkronisasi D1, dan deployment Cloudflare Pages.

Trigger otomatisnya sengaja dibuat spesifik. Push ke branch main hanya memicu workflow ketika ada perubahan pada pola artikelx/*.html. Dengan demikian, artikelx berfungsi sebagai staging area untuk artikel baru sebelum diproses.

on:
 push:
 branches:
 - main
 paths:
 - "artikelx/*.html"

Selain trigger otomatis, workflow menyediakan workflow_dispatch. Mekanisme manual ini memungkinkan proses tertentu dijalankan kembali tanpa harus memasukkan artikel baru, misalnya ketika hanya perlu melakukan rebuild data, membuat ulang srcset gambar, melakukan injeksi Schema.org, atau menjalankan deployment tertentu.

Fase 1: Memproses Artikel di artikelx/

Fase pertama berfokus pada bahan mentah yang masuk melalui direktori artikelx/. Beberapa script Bun.js bekerja secara berurutan untuk mengubah struktur HTML, menyesuaikan aset, memperbaiki metadata SEO, melakukan mirror gambar, dan menghasilkan format WebP.

Struktur HTML dan aset

Edit-Komponen-HTML.ts menangani modifikasi struktur dasar HTML. Setelah itu gantifontshighlight.ts mengelola aset font dan kebutuhan highlight yang digunakan oleh situs.

Langkah berikutnya dijalankan oleh seo-fixer.ts. Script tersebut menangani pemrosesan metadata SEO, mirror gambar, serta konversi gambar ke WebP sehingga artikel yang masuk staging dapat mengikuti standar produksi repository.

Perpindahan ke direktori production

Setelah berhasil diproses, file HTML yang berada di artikelx/ dipindahkan ke artikel/. Perubahan fase ini kemudian dibuat menjadi local commit oleh GitHub Actions.

Intinya:artikelx/ bukan direktori production. Ia adalah pintu masuk pipeline. Setelah artikel diproses, file tersebut keluar dari staging dan diteruskan ke tahap build berikutnya.

Fase 2: Build, Generate, dan Optimasi

Fase kedua bertugas membangun berbagai data pendukung situs. Di sinilah artikel yang telah diproses diubah menjadi bagian dari ekosistem static site yang lebih lengkap: indeks artikel, sitemap, RSS, routing, structured data, dan aset gambar yang lebih adaptif.

Klik untuk melihat detail script pada Fase 2

Generator data

generator-pro.ts menghasilkan artikel.json, XML, dan RSS Feed. Data tersebut menjadi bagian penting dari sistem publikasi dan pencarian situs.

Optimasi gambar

srcset-generator.ts menghasilkan varian gambar untuk berbagai resolusi layar. Pendekatan ini membantu browser memilih aset yang lebih sesuai dengan kondisi perangkat dan ukuran tampilan.

Sitemap dan routing

Toolchain yang terdiri dari koki.ts, bikin-sitemap-txt.ts, generate_llms.ts, dan redirectmap.ts memperbarui data sitemap, informasi yang digunakan sistem AI, serta peta redirect.

Structured data dan minifikasi

inject-schema.ts menginjeksi structured data Schema.org. Setelah itu minify-html.ts dan minify-jsonxml.ts melakukan minifikasi terhadap HTML, JSON, dan XML.

Setelah seluruh proses selesai, perubahan hasil build dibuat menjadi local commit kedua. Push ke repository baru dilakukan pada langkah final pipeline, sehingga seluruh transformasi dapat dikumpulkan sebelum perubahan dikirim kembali ke branch main.

Sinkronisasi Cloudflare D1 Menggunakan Diff

Mesin pencarian Layar Kosong menggunakan data artikel.json dan indeks pada Cloudflare D1. Pipeline tidak harus membangun ulang seluruh indeks remote pada setiap deployment. Sebaliknya, ia menggunakan pendekatan state โ†’ diff โ†’ patch.

Pipeline terlebih dahulu mengambil state indeks yang sedang berada di D1. Query yang digunakan mengambil id, date, dan code dari articles_fts, kemudian menyimpannya sebagai current_d1_state.json.

Cloudflare D1 saat ini
 โ”‚
 โ–ผ
SELECT id, date, code FROM articles_fts
 โ”‚
 โ–ผ
current_d1_state.json
 โ”‚
 โ–ผ
sync-d1-diff.ts
 โ”‚
 โ–ผ
d1-patch.sql
 โ”‚
 โ–ผ
Cloudflare D1 --remote

Script sync-d1-diff.ts membandingkan state tersebut dengan data repository dan menghasilkan d1-patch.sql. Patch hanya dieksekusi ketika memang terdapat perubahan, sehingga pipeline tidak perlu melakukan operasi database yang tidak diperlukan.

Pola ini penting: database remote diperlakukan sebagai state yang perlu dibandingkan, bukan sesuatu yang selalu harus dibangun ulang dari nol pada setiap deployment.

deploy_dir sebagai Batas Deployment

Sebelum Cloudflare Pages menerima hasil build, workflow membuat direktori deploy_dir/. Direktori ini menjadi deployment boundary, yaitu batas yang menentukan file mana yang boleh masuk ke deployment production.

Pipeline menggunakan rsync untuk menyalin aset yang memang diperlukan. Direktori pengembangan seperti .git/, .github/, node_modules/, dapur/, mini/, artikelx/, dan artikel/ tidak ikut dikirim sebagai direktori mentah.

Sebaliknya, direktori production seperti kategori artikel, img/, ext/, search/, serta .well-known/ dan berbagai aset HTML, XML, TXT, maupun media yang dibutuhkan akan dimasukkan ke dalam deploy_dir/.

rsync -a --delete \
 --exclude='.git/***' \
 --exclude='.github/***' \
 --exclude='node_modules/***' \
 --exclude='dapur/***' \
 --exclude='artikelx/***' \
 --exclude='artikel/***' \
 ./ deploy_dir/

Pemisahan tersebut memberikan satu keuntungan praktis: deployment tidak bergantung pada seluruh isi repository. Hanya hasil yang telah dipilih oleh aturan pipeline yang diteruskan ke Cloudflare Pages.

Wrangler Configuration Dibuat Saat Pipeline Berjalan

Workflow tidak bergantung pada wrangler.toml yang disimpan secara manual sebagai konfigurasi utama deployment. Sebelum deployment, file tersebut dihapus jika ada dan pipeline membuat wrangler.jsonc secara dinamis.

Konfigurasi tersebut menentukan nama project, compatibility date, lokasi output Pages, variable environment, dan binding database D1. Nilai database_id berasal dari GitHub Secret sehingga tidak perlu ditulis secara langsung ke repository.

{
 "$schema": "./node_modules/wrangler/config-schema.json",
 "name": "layarkosong",
 "compatibility_date": "2026-09-16",
 "pages_build_output_dir": "deploy_dir",
 "vars": {
 "BUN_VERSION": "latest",
 "NODE_VERSION": "24"
 },
 "d1_databases": [
 {
 "binding": "DB",
 "database_name": "layarkosong-db",
 "database_id": "..."
 }
 ]
}

Pendekatan tersebut juga membuat konfigurasi deployment lebih mudah disesuaikan ketika repository dijadikan dasar untuk situs lain. Nama project, compatibility date, dan binding database dapat diubah mengikuti kebutuhan deployment baru.

Deployment Langsung ke Cloudflare Pages

Setelah deploy_dir/ siap dan kebutuhan D1 diproses, pipeline melakukan deployment langsung menggunakan Wrangler. Tidak ada branch site sebagai perantara dalam arsitektur saat ini.

Deployment memiliki mekanisme retry maksimal tiga kali. Jika percobaan pertama gagal, workflow menunggu sebelum mencoba kembali. Apabila seluruh percobaan gagal, job dinyatakan gagal sehingga kegagalan deployment tidak diam-diam dianggap sukses.

max_attempts=3
attempt=1
while [ "$attempt" -le "$max_attempts" ]; do
 if bunx wrangler@latest pages deploy deploy_dir \
 --project-name=layarkosong \
 --branch=main \
 --commit-dirty=true; then
 exit 0
 fi
 if [ "$attempt" -lt "$max_attempts" ]; then
 sleep 15
 fi
 attempt=$((attempt + 1))
done
exit 1

Setelah deployment berhasil, workflow dapat menjalankan purge cache katalog dan membersihkan deployment Cloudflare lama melalui script pemeliharaan repository.

GitHub Secrets Menjaga Kredensial Tetap Terpisah

Karena pipeline berinteraksi dengan Cloudflare, beberapa kredensial harus tersedia di lingkungan GitHub Actions. Nilai tersebut disimpan sebagai repository secrets, bukan sebagai teks biasa di source code.

SecretFungsi
CF_API_TOKENAutentikasi API untuk Wrangler dan Cloudflare API.
CF_ACCOUNT_IDCloudflare Account ID.
CLOUDFLARE_ID_D1ID database D1 yang digunakan oleh binding DB.
CF_ZONE_IDZone ID domain Cloudflare untuk kebutuhan purge cache.
CF_PROJECT_NAMENama project Cloudflare untuk proses pemeliharaan deployment dan cache.

Prinsip dasarnya sederhana: repository boleh berisi konfigurasi dan kode, tetapi kredensial akses tetap berada di secret store GitHub. Dengan cara ini, konfigurasi deployment dapat dibaca dan dikelola tanpa mengekspos token maupun identifier sensitif.

Menyiapkan Environment Lokal

Untuk bekerja dengan repository, kebutuhan dasarnya adalah Git dan Bun. Git digunakan untuk mengambil repository dan mengirim perubahan, sedangkan Bun merupakan JavaScript runtime yang digunakan oleh build system dan script TypeScript di direktori dapur/.

Windows

winget install --id Git.Git -e --source winget

Linux

Pada Debian atau Ubuntu, Git dapat dipasang menggunakan:

sudo apt update
sudo apt install git

Untuk Fedora dan distribusi yang menggunakan DNF:

sudo dnf install git

Arch Linux, CachyOS, Manjaro, dan EndeavourOS dapat menggunakan:

sudo pacman -S git

Instruksi instalasi Bun mengikuti dokumentasi resmi Bun sesuai sistem operasi yang digunakan.

Menyiapkan Repository dan Cloudflare Pages

Langkah awal penggunaan repository adalah melakukan fork repository Layar Kosong ke akun GitHub sendiri dan tetap menggunakan branch main. Branch site tidak menjadi bagian dari arsitektur deployment saat ini.

Setelah repository siap, buat project Cloudflare Pages dan sesuaikan nama project dengan nilai yang digunakan workflow. Untuk basis repository ini, nama project yang digunakan adalah layarkosong.

Berikutnya buat API Token Cloudflare dengan permission yang diperlukan untuk Pages dan D1. Simpan Account ID, API Token, dan D1 Database ID secara aman, lalu masukkan nilai yang diperlukan ke GitHub Repository Secrets.

Klik untuk melihat checklist konfigurasi awal
  1. Fork repository ke akun GitHub.
  2. Gunakan branch main.
  3. Buat project Cloudflare Pages.
  4. Siapkan API Token Cloudflare dengan permission yang diperlukan.
  5. Siapkan Account ID dan D1 Database ID.
  6. Tambahkan seluruh secret ke pengaturan GitHub Actions.
  7. Hapus sample content dari artikel/ dan gambar contoh dari img/ jika repository digunakan sebagai basis situs baru.
  8. Sesuaikan domain, branding, dan konfigurasi pada file root serta direktori ext/.

Menulis Artikel dengan Production Pipeline

Alur kerja penulis sebenarnya cukup singkat. Buat artikel HTML, simpan di artikelx/, commit perubahan, kemudian push ke main. Perubahan tersebut akan dikenali oleh filter path workflow dan memulai proses otomatis.

  1. Buat file HTML artikel baru.
  2. Letakkan file di artikelx/.
  3. Lakukan git commit.
  4. Push ke branch main.
  5. Workflow memproses HTML, SEO, gambar, dan WebP.
  6. Artikel dipindahkan dari artikelx/ ke artikel/.
  7. Generator memperbarui data site, sitemap, RSS, routing, Schema.org, dan aset.
  8. Pipeline menyiapkan deploy_dir/.
  9. State indeks D1 dibandingkan dan patch diterapkan bila diperlukan.
  10. Cloudflare Pages menerima hasil production.

Dengan demikian, pekerjaan manual tidak perlu berulang setiap kali artikel diterbitkan. Penulis berinteraksi terutama dengan Git dan direktori staging, sementara pekerjaan transformasi dan deployment ditangani pipeline.

Menjalankan Pipeline Secara Manual

workflow_dispatch memberikan kontrol tambahan ketika kebutuhan tidak selalu berupa artikel baru. Beberapa proses dapat dijalankan secara terpisah menggunakan toggle yang tersedia pada halaman GitHub Actions.

InputFungsi
run_proses_artikelMenjalankan pemrosesan artikel pada Fase 1.
run_build_generatorMenjalankan generator data, sitemap, LLMs, dan redirect map.
run_srcsetMembuat varian gambar untuk kebutuhan srcset.
run_schemaMenjalankan injeksi Schema.org.
run_minifyMenjalankan minifikasi HTML, JSON, dan XML.
deploy_modeMenentukan mode deployment: full, update-only, atau skip.

Mode deployment

Mode full menjalankan persiapan deployment, sinkronisasi D1, deployment Pages, serta purge cache. Mode update-only menyiapkan deploy_dir/ dan melakukan deployment Pages tanpa sinkronisasi D1 dan purge cache.

Sementara itu, skip melewati deployment Cloudflare Pages. Namun, langkah final commit dan push tetap merupakan bagian dari workflow sehingga hasil perubahan script masih dapat di-commit dan dikirim ke repository.

run_build_generator = true
deploy_mode = update-only

Branding dan File yang Perlu Disesuaikan

Setelah deployment awal berhasil, repository dapat disesuaikan dengan identitas situs yang akan dibangun. Bagian yang perlu diperhatikan meliputi domain, warna, logo, informasi kontak, metadata, dan konfigurasi pada direktori ext/.

Beberapa file root juga memiliki fungsi khusus, seperti index.html untuk halaman utama, search.html untuk pencarian, 404.html untuk halaman not-found, robots.txt, sitemap HTML, favicon, halaman disclaimer, serta halaman privasi dan penghapusan data.

artikel.json merupakan indeks utama yang digunakan mesin pencari situs. File tersebut sebaiknya dibiarkan diperbarui oleh pipeline agar hasil generator tidak tertimpa perubahan manual.

Klik untuk melihat checklist pra-launch
  • Ganti seluruh URL dalam.web.id dengan domain situs sendiri.
  • Perbarui informasi kontak dan metadata.
  • Sesuaikan warna, logo, dan branding.
  • Validasi seluruh internal link.
  • Verifikasi sitemap dan robots.txt.
  • Pastikan secret Cloudflare sudah benar.
  • Pastikan binding D1 mengarah ke database yang benar.
  • Pastikan deployment Cloudflare Pages berhasil.
  • Verifikasi situs production melalui HTTPS.

Custom Domain di Cloudflare Pages

Jika situs akan menggunakan domain sendiri, konfigurasi dilakukan melalui bagian Custom Domains pada project Cloudflare Pages. Domain ditambahkan melalui dashboard Cloudflare, kemudian DNS dikonfigurasi mengikuti instruksi yang diberikan platform.

Dalam arsitektur ini, file CNAME tidak digunakan sebagai mekanisme utama deployment. File tersebut lebih umum ditemukan pada pola deployment GitHub Pages, sedangkan Cloudflare Pages memiliki mekanisme domain tersendiri.

Kenapa Pendekatan Ini Cocok untuk Static Site?

Kekuatan utama arsitektur Layar Kosong terletak pada pembagian tanggung jawab yang jelas. Repository menjadi sumber data dan kode, GitHub Actions menjadi orchestrator, Bun.js menjalankan toolchain transformasi, Cloudflare D1 menyimpan indeks pencarian remote, sedangkan Cloudflare Pages menjadi tujuan deployment.

Pemisahan tersebut membuat proses publikasi dapat diprediksi. Artikel masuk melalui staging, diproses menjadi aset production, indeks dibandingkan dengan state database, lalu hanya output yang diperlukan yang dikirim ke hosting.

Model seperti ini juga mengurangi pekerjaan repetitif. Ketika pipeline sudah stabil, aktivitas penerbitan artikel berubah menjadi proses sederhana: menulis, menyimpan di artikelx/, commit, dan push.

Penutup

Membangun static site bukan hanya persoalan menghasilkan HTML yang cepat. Ketika situs sudah memiliki banyak artikel, kualitas workflow di belakangnya ikut menentukan seberapa mudah situs tersebut dirawat dan dikembangkan.

Layar Kosong memilih pendekatan satu pipeline dengan tiga fase: memproses artikel, menghasilkan seluruh aset pendukung, lalu menyiapkan dan melakukan deployment. Bun.js menyediakan runtime untuk toolchain TypeScript, GitHub Actions menjadi mesin otomatisasi, Cloudflare D1 menangani indeks pencarian, dan Cloudflare Pages menjadi tujuan publikasi.

Hasil akhirnya adalah alur kerja yang cukup sederhana dari sudut pandang penulis, tetapi memiliki rangkaian otomasi yang lengkap di belakangnya. Selama struktur staging, secrets, generator, database, dan deployment tetap konsisten, proses publikasi dapat berjalan berulang dengan pola yang sama.