Skip to content
Tools & Utilities Programming

Offline Docs Site Builder

By Romi Fadli, S.Kom. 7 min read Tooling & Automation
On this page
A stack of Markdown documents and an orange arrow leading to a browser page with a side menu, a heading, paragraphs, a dark code panel, and a table of contents with its active entry highlighted

Offline Docs Site Builder adalah satu script yang mengubah dokumentasi Markdown milik satu project menjadi situs statis kecil: menu berisi setiap halaman, daftar isi yang mengikuti pembaca, tabel yang tak pernah memotong isi selnya, dan blok kode dengan tombol salin. Situsnya langsung terbuka dari folder-nya — tanpa web server, tanpa koneksi internet — dan tampil seperti produk yang didokumentasikannya.

Dokumentasi Markdown enak ditulis tapi canggung dibaca: di server tanpa penampil yang ramah browser, tim hanya mendapat teks mentah, tabel panjang yang terlipat jadi berantakan, dan tautan yang menunjuk ke file .md. Builder ini mempertahankan Markdown sebagai satu-satunya sumber dan memberi tim halaman yang benar-benar dibaca.

Sekilas

BentukSatu script command-line, beserta template halaman dan script browser kecil
BahasaPython 3 dengan markdown-it-py; Tailwind CSS yang dikompilasi lokal; JavaScript biasa di halaman
StatusStabil, dipakai
Kode sumberPrivat
Apa tool ini, dibangun dengan apa, dan keadaannya.

Yang dikerjakannya

A. Membangun situs yang terbuka tanpa server

Setiap halaman disusun saat build dari satu template: menu, daftar isi, isi, dan footer. Font dan stylesheet disimpan di samping halaman-halamannya, jadi membuka index.html dari folder salinan atau flashdisk menampilkan situs yang sama seperti lewat web server. README project menjadi beranda, dan setiap file bernomor seperti 01-architecture.md menjadi satu halaman, berjudul heading pertamanya.

B. Menjaga Markdown sebagai satu-satunya sumber

HTML-nya hasil keluaran, tak pernah disunting dengan tangan. Setiap run membangun ulang setiap halaman, jadi tak ada halaman yang bisa tertinggal dari Markdown-nya, dan opsi --list menampilkan halaman yang ditemukannya beserta keadaan masing-masing.

C. Membuat tabel dan kode enak dipakai

Tabel ditaruh di panel yang bisa digulir, dengan lebar kolom mengikuti isinya dan sel yang tak pernah dipotong, karena satu sel di dokumentasi operasional bisa sepanjang 190 karakter dan menyembunyikannya merugikan pembaca. Setiap kolom kecuali yang terakhir bisa dilebarkan dengan menyeret tepinya, sampai batas lebar minimum, tanpa ikut menyorot teks di sepanjang jalan. Blok kode mendapat panel bertuliskan bahasanya dan tombol Salin yang menyalin teksnya persis, termasuk indentasinya, bahkan ketika halamannya dibuka dari file.

D. Menjaga setiap tautan tetap berfungsi

Heading mendapat anchor yang sama dengan yang akan diberikan GitHub, jadi tautan yang sudah tertulis di Markdown tetap mendarat di tempat yang benar. Tautan antar-file Markdown ditulis ulang ke halaman HTML pasangannya, termasuk tautan dari README dan tautan yang ditulis dengan awalan folder. Tautan ke halaman yang sumbernya hilang diubah menjadi teks biasa yang nonaktif, bukan tautan mati, dan menu menampilkan halaman itu dalam warna redup.

E. Mengikuti pembaca di halaman panjang

Daftar isi disusun dari heading tingkat dua dan tiga, lalu menyorot bagian yang sedang tampil di layar selagi pembaca menggulir. Entrinya disimpan sebagai teks polos sampai langkah terakhir, jadi heading yang memuat tanda & tak ter-escape dua kali.

Cara saya memakainya

bash
build-docs-html                # rebuild every page from docs/*.md
build-docs-html --list         # pages found and their status
tailwindcss -c docs/html/src/tailwind.config.js \
  -i docs/html/src/tailwind.input.css \
  -o docs/html/assets/tailwind.css --minify     # only when new classes appear
Di MarkdownDi halaman
Headinganchor yang sama dengan milik GitHub, dan entri di daftar isi
Tabelpanel bergulir dengan sel utuh dan kolom yang bisa dilebarkan
Blok kode berpagarpanel bertuliskan bahasanya dan tombol Salin
Tautan ke file .md laintautan ke halaman HTML-nya, atau teks nonaktif bila sumbernya hilang
READMEberanda
Jadi apa tiap elemen Markdown.

Keputusan rancangan

Situsnya harus bisa dibuka dari folder, jadi ia dihasilkan saat build, bukan dirakit di browser. HTML statis tak punya include, dan halaman yang dibuka dari file tak diizinkan mengambil file lain, jadi header dan menu bersama hanya bisa ada bila ditulis ke setiap halaman saat build. Font dan stylesheet hasil kompilasi tinggal di samping halaman karena alasan yang sama, dan build-nya memakai library Markdown yang sudah terpasang — CommonMark dengan tabel dan coretan mencakup setiap elemen yang dipakai dokumentasi — jadi tool ini tak menambah dependency baru. Ketika perubahan template memunculkan class gaya baru, build mencetak satu perintah untuk mengompilasi ulang stylesheet-nya.

Markdown tetap satu-satunya sumber, dan build parsial sudah tak ada. Dokumentasi ditulis dan ditinjau sebagai Markdown, di samping kodenya; HTML hanyalah tampilannya. Versi awal hanya membangun sebagian halaman selagi desainnya dinilai, dan itu membuat halaman lain basi tanpa suara, jadi kini setiap run membangun ulang semuanya.

Kenyamanan membaca datang dari detail tema, bukan dari plugin. Antarmuka tempat dokumentasi ini berasal tak memakai plugin tipografi, jadi builder sendiri yang memberi class pada tiap elemen, dan halaman-halamannya berbagi warna, font, dan permukaan gelap milik produknya. Paragraf dibuat rata kiri-kanan dengan pemenggalan kata otomatis yang terikat pada bahasa Indonesia halaman itu, karena istilah teknis panjang yang tak bisa dipenggal menyisakan celah lebar antar-kata. Tabel tak pernah memotong isinya, kolom bisa dilebarkan, kode bisa disalin dengan indentasi utuh, dan daftar isi menjaga pembaca tetap tahu posisinya di halaman panjang.

Tautan wajib selamat melewati konversi. Anchor mengikuti aturan GitHub persis, termasuk dua detail yang pernah memutusnya: entitas HTML di-decode lebih dulu sebelum heading menjadi anchor, jadi tanda & tak berubah menjadi huruf-huruf entitasnya, dan tanda baca dibuang, bukan diganti, jadi tanda pisah di antara dua spasi menyisakan hyphen ganda persis seperti GitHub. Tautan ke file Markdown menjadi tautan ke halamannya, dan tautan yang tak menuju ke mana pun dinonaktifkan, bukan menghasilkan 404.

Kesalahan render yang diam ditangkap saat build, bukan oleh pembaca. Library Markdown menulis garis pemisah sebagai tag self-closing dan sel tabel berpenjajaran dengan atribut style, dan keduanya akan lolos dari pemberian gaya lalu tampil dengan gaya bawaan browser — garis terang melintang di halaman gelap, sel tanpa padding — jadi keduanya ditangani secara eksplisit. Garis pemisah di akhir, yang di Markdown hanya memisahkan blok penutup, dibuang, dan heading pertama di halaman tak membawa margin atas di dalam kartunya. Library atau template yang hilang menghentikan build sambil menyebut perintah untuk membetulkannya, bukan traceback.

Spesifikasi

MasukanREADME project dan file Markdown bernomor di folder dokumentasi
KeluaranSatu halaman HTML per sumber, dengan menu, daftar isi, dan template bersama; ditulis ke folder HTML dokumentasi
TemplatePlaceholder untuk judul, menu, daftar isi, isi, dan tahun
Jalan offlineYa: font, stylesheet, dan script tersimpan lokal, dan halaman terbuka dari file system
PrasyaratPython 3 dengan markdown-it-py; tool command-line Tailwind hanya bila gayanya berubah
Masukan, keluaran, dan prasyarat tool ini.

Terkait

Script ini mengikuti bentuk yang saya berikan pada setiap tool kecil: satu file, satu tugas, dan urutan seksi yang sama setiap kali.

Kenapa dokumentasi ditulis untuk pembaca berikutnya, dan tinggal di samping kode yang dijelaskannya.

Gagasan yang sama dari sumber berbeda: mengubah teks yang ditulis untuk tools menjadi halaman yang dibaca orang.

Istilah

Situs statis
Kumpulan halaman HTML siap pakai yang tak butuh program berjalan di server untuk ditampilkan.
Markdown
Format teks polos yang markup ringannya, seperti # untuk heading, berubah menjadi teks berformat.
CommonMark
Spesifikasi Markdown yang presisi, sehingga tools berbeda bisa merendernya dengan cara yang sama.
Anchor
Identifier pada heading yang bisa dituju tautan, ditulis sesudah # di alamatnya.
Pemenggalan kata
Memecah kata panjang ke dua baris di titik yang sah, supaya teks rata kiri-kanan tak menyisakan celah lebar.

Technologies covered

  • Python

About the author

Photo of Romi Fadli

Romi Fadli, S.Kom.

Solution Architect · Backend Engineer · Embedded Systems

In my day job I work as a solution architect. I design the system, lead the team that builds it — quality assurance, backend developers, a UI developer, DevOps and DevSecOps — and write the most critical modules myself, such as a certificate authority, a long-term PDF signer, and the core API of a personnel system.

I work across the whole stack that a running system actually needs. On the hardware side that means PCB design, microcontrollers, and embedded firmware — including RISC-V boards running FreeRTOS and Embassy, speaking MQTT over mutually authenticated TLS on a microcontroller with 64 KB of SRAM.

Most of my day-to-day work is software: Rust backends and API modules built on Clean Architecture, an OAuth2/OpenID Connect authorization server written from scratch, PAdES document signing, and certificate authorities — root CAs, timestamping authorities, and OCSP responders. I also build the frontends that sit on top of them.

Running all of that means infrastructure: Docker Compose stacks, networking, Mikrotik and RADIUS, observability with OpenTelemetry, and a steady habit of writing command-line tools and utilities for Linux when the existing ones do not fit.

Share

Enjoyed this?

Get an email when a new article is published.

Referenced by

A purple root circle linked to a blue and an orange intermediate circle, which lead to a signed document with a green seal and to a clock.

Aurograf

DevOps

Platform tanda tangan digital Pemerintah Kota Tangerang Selatan: penanda tangan membuktikan identitasnya, menandatangani PDF hingga PAdES B-LTA dengan sertifikat dari otoritas milik platform sendiri, dan siapa pun bisa memverifikasinya — versi 2, yang saya rancang, bangun, dan operasikan.

10 min read Read more →

Related Articles

An old layout with a grey banner and a new structure with a green banner, each holding a blue database, a purple document store, and an orange telemetry store; three coloured paths pass through one export package marked with a green check

Empat perintah yang memindahkan stack dari layout lama ke struktur baru melintasi versi mayor: export tanpa mengubah data sumber, import tiap store sesuai cara yang diizinkan versinya, verifikasi apa yang benar-benar tiba, dan rename modul sambil memindahkan datanya.

11 min read Read more →
Three image layer stacks, each with a version tag of its own colour, blue, orange, and green, each leading to an archive file banded in the same colour

Perintah yang memberi versi tersendiri pada tiap modul stack, mem-build image-nya di bawah tag yang berarti tepat satu build, menolak memakai ulang versi atau menelan compile yang gagal, dan mengarsipkan image menurut nama dan tag supaya versi tak saling menimpa.

7 min read Read more →
Four identical grey keys on the left each become a key of its own colour on the right, every new key marked with a green check; below, a purple key stays behind a red bar

Satu perintah yang merotasi kredensial internal satu environment kunci demi kunci: dry run sebagai default, backup lebih dulu, nilai unik untuk tiap kunci, login sungguhan untuk membuktikan tiap kredensial yang bisa dipakai login, dan rollback bagi yang gagal.

8 min read Read more →