Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .changesets/2026-09-05-bun-naik-ke-1-4-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
bump: patch
tipe: dependency
dampak: internal
---

# Bun naik dari `1.3.14` ke `1.4.2`, dan `bun.lock` ikut berganti format

Pin Bun repo ini naik di kelima nilai sekaligus — `packageManager` dan
`engines.bun` di `package.json`, `bun-version` di kedua job
`.github/workflows/ci.yml`, dan tag `oven/bun` beserta digestnya di kedua
stage `Dockerfile` — mengikuti aturan lima-nilai-plus-digest yang
`tests/versi-toolchain.test.mjs` gerbangi. `bun.lock` diregenerasi penuh
(`rm -rf node_modules bun.lock && bun install`), bukan disunting sebagian,
sesuai aturan repo.

Regenerasi itu bukan sekadar isi lockfile yang berubah — **formatnya sendiri
berubah**: Bun 1.4 menulis `bun.lock` sebagai `lockfileVersion: 2`, sementara
setiap `bun.lock` yang lebih tua di repo ini adalah `lockfileVersion: 1`. Bun
yang hanya memenuhi `engines.bun` LAMA (`>=1.3.0`) tidak bisa mengurai
`lockfileVersion: 2` sama sekali — `bun install --frozen-lockfile` gagal
dengan `error: Unknown lockfile version at bun.lock:2:22`, sebuah pesan yang
menyebut nama berkas dan bukan versi Bun sama sekali. `engines.bun` karena itu
juga naik ke `>=1.4.0`: batas lama menerima versi yang justru tidak bisa
menginstal repo ini sejak `bun.lock` berformat baru.

- Tidak ada perubahan output publik situs mana pun; ini murni kenaikan
toolchain.
- **Terasa oleh situs yang diturunkan dari template ini sebelum 5 September
2026, atau yang belum mengikuti kenaikan ini**: begitu `bun.lock` situs itu
sendiri diregenerasi oleh siapa pun dengan Bun ≥1.4 terpasang lokal — bukan
mesti oleh perubahan di template ini — instalasi `--frozen-lockfile`
berikutnya di CI atau `docker build` di sana gagal dengan pesan yang sama,
selama kelima nilai pin situs itu belum ikut naik. Gejala, sebab, dan
perbaikannya (lima nilai plus digest, sama seperti aturan repo ini) ditulis
di [`docs/deploy-coolify.md`](../docs/deploy-coolify.md#a-bun-install---frozen-lockfile-that-names-a-lockfile-not-a-bun-version)
dan [`docs/awcms-astro/checklist-repo-baru.md`](../docs/awcms-astro/checklist-repo-baru.md).
4 changes: 2 additions & 2 deletions CONTRIBUTING.id.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
🇮🇩 Bahasa Indonesia · 🇬🇧 [English (source)](CONTRIBUTING.md)

<!-- i18n-source-hash: sha256:487850e35d822c4eb6b10d452f3e2055997f3fd98e10ccf3fc6266ed65581c92 -->
<!-- i18n-source-hash: sha256:37777d47a73b5f0a03a593bbeaea4e09ad3d84cdcfc4e4fc8f47a620d16f75bc -->

# Panduan Kontribusi

Expand Down Expand Up @@ -35,7 +35,7 @@ Kontributor agen AI: baca [`AGENTS.md`](AGENTS.md) lebih dulu. Ia kontrak kerja
## Menyiapkan lingkungan

```bash
bun --version # >= 1.3.0, sesuai `engines.bun`
bun --version # >= 1.4.0, sesuai `engines.bun`
cp .env.example .env # isi AWCMS_API_URL, token, dan tenant
bun install
bun run dev # http://localhost:4321
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ AI agent contributors: read [`AGENTS.md`](AGENTS.md) first. It is the binding te
## Setting up

```bash
bun --version # >= 1.3.0, per `engines.bun`
bun --version # >= 1.4.0, per `engines.bun`
cp .env.example .env # fill in AWCMS_API_URL, the token, and the tenant
bun install
bun run dev # http://localhost:4321
Expand Down
4 changes: 3 additions & 1 deletion docs/awcms-astro/checklist-repo-baru.id.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
🇮🇩 Bahasa Indonesia · 🇬🇧 [English (source)](checklist-repo-baru.md)

<!-- i18n-source-hash: sha256:63616ed2e930e90b7c2cb2e96d08847ed0dc32dc4f113bbc5d2bccf69118cb76 -->
<!-- i18n-source-hash: sha256:650e87320ed4fe83f3bed1d8613e3487f15bb58a43611366c90b1db3060e0ab7 -->

# Memulai Situs Baru di Atas awcms-astro

Expand Down Expand Up @@ -44,6 +44,8 @@ Yang **tidak** perlu disentuh: `src/lib/`, `src/layouts/`, `src/components/`, `s
- [ ] `package.json` — `name`, `description`, `homepage`, `repository`, `engines`, dan seluruh skrip.
- [ ] Versi Bun konsisten di **lima nilai**, bukan tiga berkas — `packageManager`, `engines.bun`, `bun-version` di **dua** job CI, dan tag image (identik di kedua stage `Dockerfile`) — ditambah digest yang dipin di sebelah tag itu, sehingga ada enam hal yang bergerak bersama ([ADR-0030](../adr/0030-aturan-tertulis-mendapat-pemeriksanya.md) §Konsekuensi). Menghitung BERKAS alih-alih NILAI adalah kesalahan yang [ADR-0030](../adr/0030-aturan-tertulis-mendapat-pemeriksanya.md) ditulis untuk mengakhirinya: duplikat kedua di tiap berkas yang paling mungkin tertinggal, dan keduanya tetap hijau sendirian. `tests/versi-toolchain.test.mjs` membandingkan seluruhnya, dan ia juga menolak satu stage dipin ke digest sementara yang lain tidak — saat tag dan digest sama-sama ada, Docker mematuhi digest dan tag hanya menjadi komentar.

**Menaikkan pin-nya belakangan punya satu jebakan yang tidak bisa dilihat gerbang di atas, karena itu soal BINER Bun yang dijalankan seseorang, bukan nilai yang tertulis di repo ini.** Sejak Bun 1.4 menulis `bun.lock` sebagai `lockfileVersion: 2` — format yang sama sekali tidak bisa diurai Bun yang hanya memenuhi `>=1.3.0` — sebuah `bun.lock` yang diregenerasi oleh siapa pun dengan Bun lebih baru terpasang di mesinnya (kontributor, PR rekan tim, Dependabot) diam-diam menaikkan formatnya sementara kelima nilai pin situsmu sendiri bisa saja masih menyebut `1.3.x`. Kelimanya tetap konsisten satu sama lain dan gerbang di atas tetap hijau, tetapi `bun install --frozen-lockfile` berikutnya di CI atau `docker build` gagal dengan `error: Unknown lockfile version at bun.lock:2:22` — pesan yang menyebut nama lockfile, tidak pernah Bun. Gejala, sebab, dan perbaikannya tertulis di [`deploy-coolify.md`](../deploy-coolify.id.md#bun-install---frozen-lockfile-yang-menyebut-nama-lockfile-bukan-versi-bun).

Pertanyaan yang menentukan bentuk skema: **kesalahan apa yang paling merugikan pembaca situs ini, dan field mana yang membuat kesalahan itu sulit dilakukan?** Di repo rujukan jawabannya `cakupan` dan `biaya[].jenis` — keduanya memaksa keputusan yang kalau tidak dipaksa akan terlewat.

## 3. i18n
Expand Down
2 changes: 2 additions & 0 deletions docs/awcms-astro/checklist-repo-baru.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ What does **not** need touching: `src/lib/`, `src/layouts/`, `src/components/`,
- [ ] `package.json` — `name`, `description`, `homepage`, `repository`, `engines`, and every script.
- [ ] The Bun version consistent across **five values**, not three files — `packageManager`, `engines.bun`, `bun-version` in **two** CI jobs, and the image tag (identical in both `Dockerfile` stages) — plus the digest pinned beside those tags, making six things that move together ([ADR-0030](../adr/0030-aturan-tertulis-mendapat-pemeriksanya.md) §Consequences). Counting files rather than values is the mistake [ADR-0030](../adr/0030-aturan-tertulis-mendapat-pemeriksanya.md) was written to end: the second duplicate in each file is the one most likely to be left behind, and each stays green on its own. `tests/versi-toolchain.test.mjs` compares all of them, and it also refuses one stage being pinned to a digest while the other is not — when a tag and a digest are both present, Docker obeys the digest and the tag becomes a comment.

**Raising the pin later has one trap that gate cannot see, because it is about a Bun BINARY someone runs, not a value written in this repo.** Since Bun 1.4 writes `bun.lock` as `lockfileVersion: 2` — a format a Bun that only satisfies `>=1.3.0` cannot parse at all — a `bun.lock` regenerated by anyone with a newer Bun installed locally (a contributor, a teammate's PR, Dependabot) silently upgrades the format while your site's own five pinned values may still say `1.3.x`. The five stay internally consistent and the gate above stays green, yet the very next `bun install --frozen-lockfile` in CI or `docker build` fails with `error: Unknown lockfile version at bun.lock:2:22` — a message naming the lockfile, never Bun. The symptom, cause, and fix are written out in [`deploy-coolify.md`](../deploy-coolify.md#a-bun-install---frozen-lockfile-that-names-a-lockfile-not-a-bun-version).

The question that shapes your schema: **what mistake harms this site's readers most, and which field makes that mistake hard to make?** In the reference repo the answers were `cakupan` and `biaya[].jenis` — both force a decision that would otherwise be missed.

## 3. i18n
Expand Down
4 changes: 2 additions & 2 deletions docs/awcms-astro/standar-performa-dan-keamanan.id.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
🇮🇩 Bahasa Indonesia · 🇬🇧 [English (source)](standar-performa-dan-keamanan.md)

<!-- i18n-source-hash: sha256:628726c172dafaf5d4a14f53fa3d6a4347168b7a1300087b05bcaaec271a5440 -->
<!-- i18n-source-hash: sha256:793e6a1a6e047c99b8d32e9123455679d6c1fb45f1ec162896d14b53e95ea9f0 -->

# awcms-astro — Standar Performa dan Keamanan

Expand Down Expand Up @@ -215,7 +215,7 @@ situs yang butuh cakupan lebih menaikkannya di berkas itu.
| Tanpa webfont — `system-ui` sebagai `--font-sans` | Nol permintaan font, nol FOIT/FOUT, nol kontribusi ke CLS. Ia dicatat sebagai keputusan **privasi** di [`src/styles/global.css`](../../src/styles/global.css); ia juga keputusan performa | `src/styles/global.css` |
| Tanpa framework UI, tanpa framework CSS | JS terkirim mendekati nol pada sebagian besar halaman | [`standar-teknis.md`](standar-teknis.md#the-stack) |
| `compressHTML: true` | HTML lebih kecil sebelum kompresi transport | `astro.config.mjs` |
| Kompresi respons memakai pustaka matang | Bukan hanya gzip: `compression` v1.8 menegosiasikan **Brotli** (RFC 7932) saat browser memintanya, dan Brotli mengalahkan gzip sekitar 15–20% pada HTML | [`server/penyaji.mjs`](../../server/penyaji.mjs) |
| Kompresi respons memakai pustaka matang | Bukan hanya gzip: `compression` v1.8 menegosiasikan **Brotli** (RFC 7932) saat browser memintanya, dan Brotli mengalahkan gzip sekitar 15–20% pada HTML. Keberadaannya di `dependencies` adalah keputusan mempertahankan yang disengaja, bukan runtime Node.js yang menyelinap kembali — ia berjalan sepenuhnya di atas Bun, digerbangi dari sisi mempertahankan oleh [ADR-0050](../adr/0050-bun-is-this-repos-only-runtime-and-a-gate-finally-says-so.md) | [`server/penyaji.mjs`](../../server/penyaji.mjs) |
| `Cache-Control` dua aturan | Aset ber-hash `immutable` satu tahun; HTML `max-age=0, must-revalidate` sehingga rebuild langsung terlihat. Keduanya sesuai RFC 9111, dan keduanya **dibuktikan tes** — termasuk paritas GET/HEAD yang pernah membuat `curl -I` melaporkan nilai yang salah | [`tests/penyaji.test.mjs`](../../tests/penyaji.test.mjs) |
| Konten ditarik saat build | Nol panggilan ke CMS saat pembaca meminta halaman; situs tetap tayang saat `awcms` mati | [ADR-0018](../adr/0018-kontrak-build-token-mesin-dan-traversal-konten.md) |
| Media di-resolve **sekali per build** | Situs 300 artikel × 2 locale tidak berubah menjadi ratusan permintaan HTTP saat render | [`src/lib/content.ts`](../../src/lib/content.ts) |
Expand Down
2 changes: 1 addition & 1 deletion docs/awcms-astro/standar-performa-dan-keamanan.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ row 8.
| No webfonts — `system-ui` as `--font-sans` | Zero font requests, zero FOIT/FOUT, zero contribution to CLS. It is recorded as a **privacy** decision in [`src/styles/global.css`](../../src/styles/global.css); it is also a performance decision | `src/styles/global.css` |
| No UI framework, no CSS framework | JS shipped is near zero on most pages | [`standar-teknis.md`](standar-teknis.md#the-stack) |
| `compressHTML: true` | Smaller HTML before transport compression | `astro.config.mjs` |
| Response compression uses a mature library | Not only gzip: `compression` v1.8 negotiates **Brotli** (RFC 7932) when a browser asks for it, and Brotli beats gzip by roughly 15–20% on HTML | [`server/penyaji.mjs`](../../server/penyaji.mjs) |
| Response compression uses a mature library | Not only gzip: `compression` v1.8 negotiates **Brotli** (RFC 7932) when a browser asks for it, and Brotli beats gzip by roughly 15–20% on HTML. Its presence in `dependencies` is a deliberate keep, not the Node.js runtime creeping back in — it runs entirely under Bun, gated from the keep side by [ADR-0050](../adr/0050-bun-is-this-repos-only-runtime-and-a-gate-finally-says-so.md) | [`server/penyaji.mjs`](../../server/penyaji.mjs) |
| `Cache-Control` in two rules | Hashed assets `immutable` for a year; HTML `max-age=0, must-revalidate` so a rebuild is immediately visible. Both per RFC 9111, and both **proven by tests** — including the GET/HEAD parity that once made `curl -I` report the wrong value | [`tests/penyaji.test.mjs`](../../tests/penyaji.test.mjs) |
| Content pulled at build time | Zero calls to the CMS when a reader asks for a page; the site stays live when `awcms` is down | [ADR-0018](../adr/0018-kontrak-build-token-mesin-dan-traversal-konten.md) |
| Media resolved **once per build** | A 300-article × 2-locale site does not turn into hundreds of HTTP requests at render time | [`src/lib/content.ts`](../../src/lib/content.ts) |
Expand Down
6 changes: 3 additions & 3 deletions docs/awcms-astro/standar-teknis.id.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
🇮🇩 Bahasa Indonesia · 🇬🇧 [English (source)](standar-teknis.md)

<!-- i18n-source-hash: sha256:443754b41579a6f6444ca0dd833f689698f5ac54709ad1d4f7d1227657c4e3ba -->
<!-- i18n-source-hash: sha256:fe3a6f44f5a59fda850b7ab4cfd1f719503a06859b685964301a96222d66b0ba -->

# awcms-astro — Standar Teknis

Expand All @@ -13,7 +13,7 @@ Kata **wajib** di dokumen ini berarti pelanggarannya menggagalkan gerbang mutu,
| Aspek | Keputusan | Alasan |
| --- | --- | --- |
| Framework | Astro 7, `output: 'static'` | Nol JavaScript pengiriman default; halaman tetap terbaca penuh tanpa JS |
| Runtime | Bun `>=1.3.0`, ditegakkan `engines.bun` + `packageManager` | Satu runtime untuk seluruh keluarga AWCMS (ADR-0015); `bun.lock` satu-satunya lockfile |
| Runtime | Bun `>=1.4.0`, ditegakkan `engines.bun` + `packageManager` | Satu runtime untuk seluruh keluarga AWCMS (ADR-0015); `bun.lock` satu-satunya lockfile. Batas bawahnya naik dari `>=1.3.0` pada 5 September 2026: Bun 1.4 menulis `bun.lock` sebagai `lockfileVersion: 2`, yang tidak bisa diurai sama sekali oleh Bun yang hanya memenuhi `>=1.3.0` — jadi batas lama menerima versi yang justru tidak bisa menginstal repo ini |
| Framework UI | **Tidak ada** | Interaktivitas ditulis DOM vanilla. Tidak ada React/Vue/Svelte |
| Styling | Satu berkas CSS global + design token | Tanpa framework CSS; token di `:root`, tema gelap lewat `data-theme` |
| Konten | **Ditarik dari `awcms` saat build** (ADR-0018); standar keluarga menyebut markdown per koleksi per locale | Kontraknya `LocalizedArticle` di `src/lib/content.ts`, bukan frontmatter |
Expand Down Expand Up @@ -190,7 +190,7 @@ Cara mencapainya — dan ini yang mengikat:
- **Tidak ada webfont.** `--font-sans` adalah `system-ui`: nol permintaan font, nol FOIT/FOUT, nol kontribusi ke CLS. Ia dicatat sebagai keputusan privasi di `src/styles/global.css`; ia juga keputusan performa, dan sebuah situs yang menambahkan font wajib men-self-host-nya di `public/` alih-alih menambah origin ke jalur render kritis.
- Gambar layar pertama `loading="eager"` + `fetchpriority="high"`; sisanya `loading="lazy"`. Keduanya dibutuhkan dan tidak saling menggantikan: `eager` hanya berarti "jangan tunda", sementara prioritas bawaan sebuah `<img>` tetap **Low** sampai layout membuktikan ia di viewport. Ditegakkan `bun run audit:konten` atas keluaran, jadi `<img>` yang tidak lewat `src/components/Ilustrasi.astro` ikut tertangkap.
- **Tema dipasang berkas eksternal `public/tema.js` yang dimuat `<script src>` klasik**, bukan skrip inline. Sejak [ADR-0019](../adr/0019-csp-ketat-dikirim-penyaji.md) penyaji mengirim `script-src 'self'` tanpa `'unsafe-inline'`, jadi skrip inline bukan "kurang rapi" — ia mati di browser pembaca. Bundel Astro selalu `type="module"` dan modul selalu ditunda, jadi ia bukan pengganti untuk kasus sebelum-paint.
- Kompresi respons bukan hanya gzip: `compression` menegosiasikan **Brotli** (RFC 7932) saat browser memintanya, dan Brotli mengalahkan gzip sekitar 15–20% pada HTML.
- Kompresi respons bukan hanya gzip: `compression` menegosiasikan **Brotli** (RFC 7932) saat browser memintanya, dan Brotli mengalahkan gzip sekitar 15–20% pada HTML. Mempertahankan `compression` di `dependencies` adalah keputusan yang disengaja, bukan runtime Node.js yang menyelinap kembali — ia berjalan sepenuhnya di atas Bun, dan [ADR-0050](../adr/0050-bun-is-this-repos-only-runtime-and-a-gate-finally-says-so.md) menggerbangi keberadaannya dari sisi mempertahankan.
- `Cache-Control` dua aturan sesuai RFC 9111: aset ber-hash `immutable` satu tahun, HTML `max-age=0, must-revalidate` sehingga rebuild langsung terlihat pembaca.
- Anggaran yang terbukti di repo rujukan: **beranda ≤ 250 KB gambar, halaman konten ≤ 100 KB.** Sejak 4 Agustus 2026 ia **diukur** `bun run audit:konten` atas `dist/client`, per halaman. Yang ditimbang hanya gambar yang benar-benar diterbitkan build ini — media `awcms` tidak ada di sana, jadi angka ini menjaga seni lokal dan bukan seluruh berat halaman.
- **Byte skrip dan stylesheet punya plafonnya sendiri**, diperiksa `bun run audit:aset`: 13.000 B skrip dan 40.000 B total per halaman, ditambah 8.000 B untuk satu berkas skrip terbit. Semuanya pengukuran berikut ruang di atasnya, bukan angka bulat, dan pengukurannya dicatat di `scripts/audit-aset.mjs` di sebelah masing-masing angka. Pelanggarannya menyebut berkas mana yang membesar, dan itu seluruh alasan ia berdiri di sebelah Lighthouse alih-alih di dalamnya — skor lab tidak bisa menyebut berkas mana yang harus dilihat. **Di mana sebuah aturan TINGGAL adalah bagian dari anggaran ini**: `src/styles/global.css` dimuat setiap halaman, jadi aturan yang hanya dipakai satu komponen adalah byte yang dibayar setiap halaman lain.
Expand Down
Loading