๐ Panduan Membuat Static Site dengan Layar Kosong
Selamat datang! Panduan ini akan membantumu membangun situs statis yang super cepat, ringan, dan otomatis ter-deploy ke Cloudflare Pages menggunakan repository Layar Kosong.
Konsepnya simpel: Kamu cukup fokus menulis di GitHub, dan biarkan GitHub Actions + Cloudflare Wrangler yang bekerja mengirimkan artikelmu ke internet secara instan.
โจ Fitur Unggulan:
- Direct Deploy: Menggunakan Wrangler untuk pengiriman kilat tanpa branch perantara.
- Search Engine: Client-side JavaScript super ngebut menggunakan data dari
artikel.json& Cloudflare D1. - Clean URLs: Mendukung URL tanpa
.htmluntuk navigasi yang lebih elegan dan rapi.
๐ง Arsitektur Otomatisasi (CI/CD)
Penasaran bagaimana "Layar Kosong" memproses draf kasarmu menjadi situs yang live? Berikut adalah alur kerja estafet otomatisnya:
Push (artikelx/*.html)
atau Manual"} Trig1 --> Check1["1๏ธโฃ Checkout Repo & Setup Bun.js"] Check1 --> S_HTML[/"2๏ธโฃ Edit Komponen HTML"/] S_HTML --> S_Clean[/"3๏ธโฃ Sterilize Schema"/] S_Clean --> S_Font[/"4๏ธโฃ Ganti Aset ke Lokal"/] S_Font --> S_SEO[/"5๏ธโฃ Injeksi SEO, Mirror, WebP"/] S_SEO --> Move["6๏ธโฃ Pindah file ke 'artikel/'"] Move --> Commit1["7๏ธโฃ Commit & Push Perubahan"] end subgraph WF2 ["โข๏ธ Workflow 2: Build & Generate Site Files (Pabrik Produksi)"] direction TB Trig2{"Trigger:
WF1 Sukses"} --> Build1{"Generate Data?"} Build1 -- Ya --> S_Gen[/"generator-pro.ts"/] --> Build2{"Generate Srcset?"} Build1 -- Tidak --> Build2 Build2 -- Ya --> S_Srcset[/"srcset-generator.ts"/] --> Build3{"Update Sitemap?"} Build2 -- Tidak --> Build3 Build3 -- Ya --> S_SiteTXT[/"koki.ts, dll"/] --> Build4{"Inject Schema?"} Build3 -- Tidak --> Build4 Build4 -- Ya --> S_Inject[/"inject-schema.ts"/] --> Build5{"Ubah Markdown?"} Build4 -- Tidak --> Build5 Build5 -- Ya --> S_MD[/"html-to-markdown.ts"/] --> Build6{"Minify File?"} Build5 -- Tidak --> Build6 Build6 -- Ya --> S_Min[/"Minify HTML/JSON/XML"/] --> Commit2["Commit, Pull --rebase & Push Data"] Build6 -- Tidak --> Commit2 end subgraph WF3 ["๐ Workflow 3: Cloudflare Deployer (Peluncuran Publik)"] direction TB Trig3{"Trigger:
WF2 Sukses"} --> Rsync["1๏ธโฃ Bersihkan Direktori (rsync)"] Rsync --> Config["2๏ธโฃ Injeksi Kredensial ke /tmp/wrangler.toml"] Config --> D1Build[/"3๏ธโฃ Eksekusi build-d1.ts"/] D1Build --> Deploy{"4๏ธโฃ Deploy ke Cloudflare Pages"} Deploy -- "Berhasil" --> Success(((Layar Kosong
Go Live! ๐))) end Commit1 --> Trig2 Commit2 --> Trig3
๐ ๏ธ Dapur Rahasia: Script Otomatisasi (Bun.js & TypeScript)
Tertarik melihat jeroan kode di balik arsitektur di atas? Silakan ngintip "resep rahasia" di bawah ini beserta kode utuh workflow YAML-nya:
1๏ธโฃ Script Tahap Persiapan (Proses ArtikelX)
File: .github/workflows/proses-artikelx.yml
- Edit-Komponen-HTML.ts โ Memodifikasi struktur HTML agar sesuai standar SEO.
- clean-schema.ts โ Membersihkan tag atau schema markup berlebih.
- gantifontshighlight.ts โ Menarik aset third-party menjadi aset lokal.
- seo-fixer.ts โ Injeksi meta SEO dan konversi gambar ke format WebP otomatis.
name: ๐ Proses ArtikelX
on:
push:
branches: ['main']
paths:
- 'artikelx/*.html'
workflow_dispatch:
permissions:
contents: write
jobs:
process_articles:
runs-on: ubuntu-latest
timeout-minutes: 1
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 1
persist-credentials: true
- name: '2. Setup Bun.js'
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: latest
- name: Install Node dependencies
run: bun install
- name: ๐ฐ Edit Komponen HTML (Bun.js)
run: bun run dapur/Edit-Komponen-HTML.ts
- name: ๐งน Sterilize Schema (Bun.js)
run: bun run dapur/clean-schema.ts artikelx/
- name: ๐ ๏ธ Ganti ke Rumah aja, fontaws dan highlight.js (Bun Mode)
run: |
set -euo pipefail
bun dapur/gantifontshighlight.ts --quiet --no-backup
# Menjalankan Mirroring & WebP Optimization di folder artikelx
- name: Inject SEO, Mirror Images & WebP (seo-fixer.ts)
run: |
set -euo pipefail
bun run dapur/seo-fixer.ts artikelx/
- name: Move to artikel/
run: |
set -euo pipefail
shopt -s nullglob
files=(artikelx/*.html)
if [[ ${#files[@]} -gt 0 ]]; then
mv -f "${files[@]}" artikel/
echo "Berhasil pindahkan ${#files[@]} file ke artikel/"
else
echo "Tidak ada file di artikelx/"
fi
- name: Commit & Push
run: |
set -euo pipefail
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
# PERBAIKAN: img/ ditambahkan agar gambar hasil mirroring ikut ter-upload
git add .
if git diff --staged --quiet; then
echo "Tidak ada perubahan."
exit 0
fi
git commit -m "Proses ArtikelX: Move, Mirror & WebP"
git push origin main
2๏ธโฃ Script Tahap Produksi (Build & Generate)
File: .github/workflows/generate-json-xml.yml
- generator-pro.ts โ Pembuat file
artikel.json, XML, dan RSS Feed. - srcset-generator.ts โ Mengoptimasi ukuran gambar untuk berbagai perangkat.
- Sitemap & Redirect: koki.ts, bikin-sitemap-txt.ts, generate_llms.ts, redirectmap.ts.
- inject-schema.ts โ Injeksi Schema.org.
- html-to-markdown.ts โ Konversi ke Markdown.
- Minifier: minify-html.ts dan minify-jsonxml.ts.
name: โข๏ธ Build and Generate Site Files
on:
workflow_run:
workflows: ["๐ Proses ArtikelX"]
types: [completed]
branches: ['main']
workflow_dispatch:
inputs:
run_generator:
description: 'Generator (JSON, RSS, Sitemap XML)'
type: boolean
default: true
run_sitemap_txt:
description: 'Update sitemap.txt'
type: boolean
default: true
run_schema:
description: 'Inject Schema.org'
type: boolean
default: true
run_minify_html:
description: 'HTML Minify'
type: boolean
default: true
run_minify_jsonxml:
description: 'JSONXML Minify'
type: boolean
default: true
run_convert_markdown:
description: 'Ubah ke format Markdown'
type: boolean
default: true
run_srcset:
description: 'Image Optimize & Srcset Generator'
type: boolean
default: true
env:
DO_GENERATOR: ${{ github.event.inputs.run_generator || 'true' }}
DO_SITEMAP_TXT: ${{ github.event.inputs.run_sitemap_txt || 'true' }}
DO_SCHEMA: ${{ github.event.inputs.run_schema || 'true' }}
DO_MINIFY_HTML: ${{ github.event.inputs.run_minify_html || 'true' }}
DO_MINIFY_JSONXML: ${{ github.event.inputs.run_minify_jsonxml || 'true' }}
DO_CONVERT_MARKDOWN: ${{ github.event.inputs.run_convert_markdown || 'true' }}
DO_SRCSET: ${{ github.event.inputs.run_srcset || 'true' }}
jobs:
build:
runs-on: ubuntu-latest
if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success'
permissions:
contents: write
steps:
- name: '1. Checkout Repository'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 1
persist-credentials: true
- name: '2. Setup Bun.js'
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6
with:
bun-version: latest
- name: '3. Install Dependencies'
run: bun install
- name: '4. Generate artikel.json, Sitemap XML & RSS'
if: env.DO_GENERATOR == 'true'
run: bun run dapur/generator-pro.ts
env:
RSS_LIMIT: 30
- name: '5. Optimize Images & Generate Srcset'
if: env.DO_SRCSET == 'true'
run: bun run dapur/srcset-generator.ts
- name: '6. Update sitemap.txt (Native Bun - Sorted by Date)'
if: env.DO_SITEMAP_TXT == 'true'
run: |
bun run dapur/koki.ts --once
bun run dapur/bikin-sitemap-txt.ts
bun run dapur/generate_llms.ts
bun run dapur/redirectmap.ts
- name: '7. Inject SEO Schema'
if: env.DO_SCHEMA == 'true'
run: bun run dapur/inject-schema.ts
- name: '8. Convert HTML to Markdown'
if: env.DO_CONVERT_MARKDOWN == 'true'
run: bun run dapur/html-to-markdown.ts
- name: '9. Minify HTML'
if: env.DO_MINIFY_HTML == 'true'
run: bun run dapur/minify-html.ts
- name: '10. Minify Data (JSON & XML)'
if: env.DO_MINIFY_JSONXML == 'true'
run: bun run dapur/minify-jsonxml.ts
- name: '11. Commit and Push'
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
# Add semua perubahan lainnya (JSON, XML, dan CACHE di folder mini/)
git add .
if git diff --staged --quiet; then
echo "โ
Tidak ada perubahan data."
else
git commit -m "beres: ๐ update data site [$(date +'%Y-%m-%d %H:%M')]"
git pull --rebase origin main
git push origin main
fi
3๏ธโฃ Script Tahap Deploy (Cloudflare)
File: .github/workflows/CloudflarePages.yml
- build-d1.ts โ Membangun indeks pencarian dan melemparnya ke Cloudflare D1 Database.
name: ๐ Cloudflare Deployer Filter & Direct
on:
workflow_run:
workflows: ["โข๏ธ Build and Generate Site Files"]
types: [completed]
push:
branches:
- main
paths:
# Daftar filter trigger tetap sama (untuk efisiensi trigger)
#- 'wrangler.toml' # Tambahkan ini biar kalau config berubah, dia auto-run
- '_redirects'
- '_headers'
workflow_dispatch:
permissions:
contents: read # Cukup READ saja, karena kita gak perlu push balik ke repo!
deployments: write
jobs:
deploy-direct:
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
steps:
# 1. Ambil source code dari main
- name: Checkout source branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
path: source
fetch-depth: 1
persist-credentials: true
- name: '1.5 Setup Node.js v22'
uses: actions/setup-node@v6
with:
node-version: 24.16.0
- name: '2. Setup Bun.js'
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
with:
bun-version: latest
- name: Install dependencies
run: bun install
working-directory: source
- name: ๐งน Prepare Clean Directory (rsync)
run: |
mkdir deploy_dir
# rsync tetap bersih karena wrangler.toml masih di /tmp/
rsync -a --delete \
--include='gaya-hidup/*' \
--include='jejak-sejarah/*' \
--include='lainnya/*' \
--include='olah-media/*' \
--include='opini-sosial/*' \
--include='sistem-terbuka/*' \
--include='warta-tekno/*' \
--include='functions/*' \
--include='search/*' \
--include='ext/*' \
--include='.well-known/*' \
--include='img/*' \
--include='artikel.json' \
--include='redirectmap.json' \
--include='llms.md' \
--include='_redirects' \
--include='_headers' \
--include='*.html' \
--include='*.xml' \
--include='*.xsl' \
--include='*.txt' \
--include='favicon.*' \
--include='icon.*' \
--include='logo.*' \
--include='thumbnail.*' \
--include='thumbnail-sm.*' \
--include='*.webmanifest' \
--exclude='*' \
source/ deploy_dir/
# ๐ 2. CREATE CONFIG (Tetap di /tmp agar aman)
- name: Create Temporary Wrangler Config
run: |
cat < /tmp/wrangler.toml
#:schema https://raw.githubusercontent.com/cloudflare/wrangler2/sys-types/pages/modules/config-schema.json
name = "layarkosong"
compatibility_date = "2025-12-01"
pages_build_output_dir = "deploy_dir"
[vars]
BUN_VERSION = "latest"
NODE_VERSION = "24"
[[d1_databases]]
binding = "DB"
database_name = "layarkosong-db"
database_id = "${{ secrets.CLOUDFLARE_ID_D1 }}"
[[kv_namespaces]]
binding = "COUNTS_KV"
id = "${{ secrets.CLOUDFLARE_ID_KV }}"
EOF
# ๐ณ 3. RUN DAPUR (Membaca deploy_dir)
- name: Run Dapur (Build D1)
run: bun run source/search/build-d1.ts
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
# ๐ 4. DEPLOY (Retry 3x)
- name: Deploy to Cloudflare Pages
run: |
# 1. Pastikan wrangler.toml ada di root untuk dibaca wrangler
cp /tmp/wrangler.toml ./wrangler.toml
# 2. PENTING: Copy folder functions dari source ke ROOT (.)
# agar sejajar dengan deploy_dir
cp -r source/functions ./functions
max_attempts=3
attempt=1
until [ $attempt -gt $max_attempts ]
do
echo "๐ Attempt $attempt to deploy..."
# 3. Jalankan deploy dari root (.) mengarah ke folder statis (deploy_dir)
# Wrangler otomatis akan mencari folder ./functions di root!
if bunx wrangler pages deploy deploy_dir --project-name=layarkosong --branch=main --commit-dirty=true; then
echo "โ
Deploy succeeded on attempt $attempt"
break
else
echo "โ ๏ธ Deploy failed on attempt $attempt"
attempt=$((attempt+1))
[ $attempt -le $max_attempts ] && sleep 15
fi
done
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
๐ ๏ธ Tahap 1: Persiapan Lingkungan (Git & Bun)
Langkah pertama: Pastikan Git dan Bun sudah terpasang di komputermu. Karena kita ingin performa super cepat, seluruh eksekusi script dan deployment akan menggunakan perintah bunx wrangler karena tidak menggunakan Node.js.
- Git: Download di sini.
- Bun: Panduan instalasi resmi (Runtime JavaScript berkecepatan kilat).
๐ช Windows
Unduh dan instal Git dari git-scm.com (atau gunakan winget install --id Git.Git -e --source winget). Setelah itu, instal Bun secara native melalui PowerShell:
powershell -c "irm bun.sh/install.ps1 | iex"
๐ macOS / ๐ง Linux
Buka terminal dan ketik perintah berikut untuk menginstal Bun:
curl -fsSL https://bun.sh/install | bash
Sedangkan untuk menginstal Git, sesuaikan dengan sistem operasimu:
# macOS (menggunakan Homebrew)
brew install git
# Debian/Ubuntu
sudo apt update && sudo apt install git
# Fedora/RHEL
sudo dnf install git
# Arch Linux
sudo pacman -S git
๐งฌ Tahap 2: Setup Repository (Fork & Cloudflare)
- Fork Repository: Lakukan Fork pada repository ini ke akunmu. Cukup centang branch
mainsaja.
๐ Klik di sini untuk Fork Repo
- Mendaftar Cloudflare Pages: Login ke dashboard Cloudflare. Pilih Workers & Pages > Create application > Pages > Upload assets. Beri nama proyekmu.
- Ambil API Token: Buka My Profile > API Tokens > Create Token. Gunakan template "Edit Cloudflare Workers". Simpan Account ID dan API Token kamu.
๐๏ธ Tahap 3: Otomatisasi (GitHub Secrets)
1. Bersihkan Konten Lama ๐งน
Hapus semua file contoh bawaan agar situsmu bersih: hapus isi folder artikel/ dan img/.
2. Pasang Kunci Rahasia
Agar GitHub bisa mengirim file ke Cloudflare secara otomatis:
- Buka tab Settings > Secrets and variables > Actions pada repository GitHub-mu.
- Klik New repository secret dan tambahkan:
CF_API_TOKEN: (Isi dengan token API Cloudflare-mu).CF_ACCOUNT_ID: (Isi dengan ID akun Cloudflare-mu).
โ๏ธ Tahap 4: Mulai Menulis dan Produksi
Di sinilah keajaiban terjadi. Ikuti alur "dapur" ini:
- Buat file HTML artikel barumu.
- Masukkan file tersebut ke dalam folder
artikelx/(perhatikan akhiran 'x'). - Lakukan
git commitdangit push. - Biarkan Action Bekerja: Sistem otomatis akan mendeteksi file baru, memprosesnya, dan memindahkannya ke etalase utama yang siap tayang!
๐ Selesai! Halaman pertamamu sudah terbit ke seluruh penjuru dunia.
๐จ Tahap 5: Personalisasi Identitas & Konfigurasi
Konfigurasi Inti (Wajib Diubah)
wrangler.toml: Gantiname = "layarkosong"menjadi nama proyek Cloudflare-mu.artikel.json: Nyawa mesin pencari blogmu, biarkan sistem yang mengupdatenya otomatis.- Folder
ext/: Sesuaikan URL dan nama domain pada seluruh file konfigurasi di dalamnya.
Halaman Root (Sesuaikan Identitasmu)
Edit file-file berikut yang ada di halaman utama (root): index.html, search.html, 404.html, robots.txt, sitemap.html, hingga favicon dan thumbnail bawaan.
๐ Checklist Pra-Peluncuran
- Ganti semua URL dari
dalam.web.idke domain kamu. - Update informasi kontak dan metadata.
- Sesuaikan warna, logo, dan branding.
- Test semua link internal.
๐ Tahap 6: Domain Custom (Opsional)
Jika kamu punya domain sendiri:
- Tambahkan file
CNAMEdi root repository. - Isi dengan nama domain kamu (contoh:
example.com). - Atur DNS di provider domain kamu (tambahkan record A ke IP GitHub Pages atau atur langsung via dashboard Cloudflare Pages).
๐ฌ Butuh Bantuan?
Jika workflow macet atau bingung set-up Cloudflare, langsung saja meluncur ke ruang diskusi.
๐ Diskusi di Repository LayarKosong
Keep coding and stay awesome! โ๏ธ