Langsung ke konten
AFM Studio
  • Halaman

    AFM Studio
  • Karya
  • Lab
  • Tentang
  • CV
  • Kontak
  • Proyek

    AksaraPerpustakaan pengetahuan Otorita IKN yang bisa dicari, dengan server memeriksa akses setiap pembaca di tiga tingkat
  • Daily TaqwaSistem presensi salat anti-manipulasi untuk ~2.000 pegawai OIKN di Masjid Negara IKN
  • Lantara v2Mesin perizinan Otorita IKN tempat administrator menambah jenis izin baru dari layar, tanpa developer
  • eKiosk IKNDua ruang kendali untuk Nusantara: konten kios dan pelacakan bus live dengan estimasi kedatangan yang menilai dirinya sendiri
  • E-Monev IKNPlatform pemantauan pembangunan Nusantara selama 23 tahun, melacak progres triwulan setiap unit terhadap 24 KPI
  • JDIH OIKNPortal dokumen hukum publik OIKN, dengan alur penerbitan terkendali dan ringkasan AI yang tidak pernah keluar dari server
  • Jejak PenanamanAplikasi absen acara penanaman pohon IKN yang membuktikan peserta hadir di lokasi lewat selfie ber-geofence
  • Dashboard SAKTIPipeline malam dan dashboard yang menggantikan unduhan anggaran manual di keenam satker OIKN
  • DoseRxKalkulator dosis untuk 127 obat yang membulatkan dosis ke tablet dan sirup yang dijual apotek Indonesia
  • CubiqPelatih speedcubing dengan timer setara kompetisi dan solver buatan sendiri untuk 8 puzzle utama
  • ScimotionPerpustakaan sains interaktif berisi 86 artikel, masing-masing dijelaskan bersama animasi yang bisa dikendalikan pembaca
  • WA Daily Scrum BotBot WhatsApp yang menagih laporan standup tim 14 orang dan menandai tugas yang macet berhari-hari

↑ ↓ untuk berpindah · Enter untuk membuka · Esc untuk menutup

GempaWatch

Situs risiko gempa yang menunjukkan seberapa aktif daerah Anda, dari 70.271 gempa yang tercatat

Tangkapan layar
gempa gabungan dari BMKG dan USGS
70.271
tahun riwayat gempa, sejak 1970
57
wilayah dengan profil risiko terbuka
52
bencana bersejarah pilihan, Aceh 2004 hingga Cianjur 2022
20
Di halaman ini

Masalahnya

Indonesia adalah negara paling aktif secara seismik di dunia, dan banyak aplikasi yang menampilkan daftar gempa terbaru. Tapi daftar menjawab pertanyaan yang keliru. Yang sebenarnya ditanyakan orang bersifat pribadi: apakah kota saya berbahaya, perlukah saya khawatir, apakah di sini lebih rawan daripada Jakarta?

Dua celah membuat pertanyaan itu sulit dijawab. BMKG, lembaga resmi Indonesia, hanya menerbitkan 15 kejadian terakhir per feed, tanpa riwayat yang bisa ditelusuri. USGS menyimpan arsip lengkap, tapi cakupannya global, berbahasa Inggris, dan berupa data peta mentah. Saya membangun GempaWatch untuk warga yang ingin mengecek daerahnya, keluarga di pesisir yang memikirkan tsunami, pelajar, dan jurnalis yang butuh fakta cepat saat gempa baru terjadi.

Yang saya bangun

Saya menggabungkan feed nasional dengan arsip global, lalu memberinya skor

USGS memberi kedalaman riwayat. BMKG memberi otoritas lokal dan gempa kecil yang terasa, yang tidak pernah dicatat USGS. Kalau keduanya melaporkan gempa yang sama, dalam selisih lima menit dan 50 km, saya menyimpan satu catatan dan mempertahankan versi BMKG. BMKG lebih akurat untuk gempa di Indonesia. Tidak ada yang bisa membaca "217 gempa di atas magnitudo 4, 14 di atas 5, 2 di atas 6". Jadi saya menggabungkannya menjadi satu skor dari 100: frekuensi bernilai 40 poin, magnitudo terbesar yang tercatat 30, porsi gempa dangkal 15, dan kedekatan dengan sesar 15. Halaman metodologi mencantumkan setiap bobot, dan situs ini hanya menggambarkan riwayat, menyatakan dengan jelas bahwa ia bukan sistem peringatan dini tsunami, serta menautkan peringatan resmi BMKG.

Saat server ditiadakan, proses build menjadi pipeline data

Rancangan awalnya adalah server yang mengecek gempa baru setiap lima menit. Sekitar sebulan kemudian, saya memindahkan situs publiknya ke GitHub Pages, tanpa backend. Kini sebuah job terjadwal mengambil kejadian baru, membangun ulang profil, lalu menerbitkan situsnya. Untuk "membekukan" API, saya menjalankan kode API yang asli dan menyimpan jawabannya sebagai berkas yang mengikuti URL live. Datanya tidak bisa melenceng dari jawaban server.

Browser menjalankan hitungan risiko yang sama, dicek di 39 titik

Tanpa server, pengecekan "apakah saya di zona rawan?" harus berjalan di ponsel. Saya memindahkan mesin risikonya dari Python ke TypeScript. Dua salinan rumus lama-lama akan berbeda, jadi saya mengunci jawaban server di 39 titik uji. Deploy berhenti kalau versi browser berbeda di salah satunya. Supaya sekitar 70 ribu kejadian bisa dimuat di ponsel, saya mengemasnya dalam array angka yang ringkas, sekitar 1,1 MB.

Riwayat gempa dicadangkan dua kali

BMKG hanya menampilkan 15 kejadian terakhir, jadi setiap catatan BMKG yang lebih lama ada karena pernah disimpan oleh proses sebelumnya. Di antara proses, database-nya tersimpan di cache build yang bisa terhapus kapan saja. Saya mencadangkannya setiap hari, dan menyimpan snapshot permanen setiap bulan. Kalau pencadangan gagal, penerbitan tetap jalan. Data gempa baru lebih penting daripada cadangannya.

Saya membangun ulang beranda dan palet warna di sekitar alat pengecek risiko

Audit desain yang saya lakukan sendiri menemukan bahwa beranda yang sudah terbit lebih mengutamakan peta live dan daftar kejadian, sementara tujuan sebenarnya aplikasi ini, sebuah jawaban risiko dari data puluhan tahun, tersembunyi satu klik di balik tautan navigasi. Saya menurunkan feed live menjadi ticker, melebur tampilan perbandingan dan eksplorasi ke dalam halaman wilayah sebagai konteks inline, dan menjadikan seismogram riwayat gempa suatu wilayah sebagai objek visual utama halaman. Palet gelap yang lama memakai satu warna untuk tombol, tautan, judul, dan pita kedalaman, tepat di sebelah warna merah tingkat risiko, sehingga hasil HIGH tidak membawa makna warna tersendiri. Kini chrome-nya hanya tinta, dan warna disediakan khusus untuk kedalaman dan tingkat risiko.

Hasilnya

GempaWatch sudah live sejak Agustus 2026, dengan 70.271 gempa dari 1970 sampai 2026, gabungan BMKG dan USGS. Target di rencana awalnya lebih dari 10.000. Situs ini punya laporan risiko lokasi, profil 52 wilayah lengkap dengan grafik, papan peringkat wilayah dengan perbandingan yang sudah dilebur ke dalamnya, peta sesar dan bahaya, kartu risiko yang bisa dibagikan, dan ticker gempa live. Versi server lengkapnya, dengan peringatan email, sudah selesai dan berjalan lewat Docker Compose, tapi belum di-hosting. Saya membangunnya sendiri selama sekitar tiga bulan, dalam tiga tahap antara Juli dan September 2026.

Di balik layarDetail teknis untuk engineer
  • Backend: Django dengan GeoDjango dan PostGIS, 7 app dan 6 model (EarthquakeEvent, AdminRegion, RegionRiskProfile, FaultLine, HistoricalDisaster, LocationWatch), djangorestframework-gis untuk GeoJSON yang langsung dipakai Leaflet. Pada deployment statis yang terbit, profil wilayah dihitung ulang setiap siklus terbit ~30 menit oleh manage.py refresh_for_export, bukan setiap malam; jadwal Celery malam hari hanya berlaku untuk rancangan mode live, dan tidak ada server live yang terkonfirmasi berjalan. Pengecekan satu titik adalah satu-satunya perhitungan live.
  • Deduplikasi: kejadian dalam selisih 5 menit dan 50 km dianggap satu catatan; laporan BMKG menimpa catatan USGS yang sudah tersimpan.
  • Bobot skor: frekuensi 40, magnitudo maksimum 30, porsi gempa dangkal 15, kedekatan sesar 15. Atribusi BMKG wajib secara hukum, ditampilkan oleh komponen SourceAttribution di setiap tampilan yang memakai datanya.
  • manage.py export_static menjalankan view DRF yang asli dan menulis pohon JSON yang cocok dengan URL live. api.live.ts dan api.static.ts berbagi satu antarmuka, dipilih lewat konstanta saat build sehingga klien yang tidak dipakai ikut dibuang dari bundle.
  • manage.py export_risk_fixtures mengunci keluaran Django di 39 titik. Suite Vitest memastikan port TypeScript cocok di setiap titik, terhadap fixture yang dibuat ulang di workflow deploy. Konvensinya: ubah Python dulu, buat ulang fixture, baru sesuaikan port-nya.
  • Tes frontend (Vitest): 163 tes di 6 berkas — mesin skor (33), pencarian provinsi (1), fungsi bantu pulau/geografi (18), penyusunan data seismogram (16), integritas struktur API statis di setiap wilayah yang diterbitkan (16), dan suite kecocokan Django dengan 79 tes. Tidak ada test suite backend.
  • Kejadian disimpan dalam typed array paralel, sekitar 1,1 MB. Tetap Float64 karena Float32 tidak bisa menyimpan magnitudo seperti 6,6 secara tepat, dan itu akan memunculkan lagi ketidakcocokan yang ingin ditangkap fixture.
  • Database dibawa antarproses CI lewat cache GitHub Actions (terhapus setelah 7 hari tidak dipakai). Cadangan: artifact workflow harian yang disimpan 90 hari, plus snapshot bulanan sebagai release asset. Dipilih release asset karena meng-commit ~8 MB per bulan ke git akan menambah ukuran setiap clone ~100 MB per tahun. Kedua langkah memakai continue-on-error. Kalau cache hilang, database dipulihkan dari bootstrap USGS penuh, tanpa gempa terasa dari BMKG.
  • Cron diatur 30 menit; kesegaran yang teramati 70–90 menit. Gambar OpenGraph per wilayah kembali ke kartu situs, karena Next 14 tidak bisa prerender route gambar metadata dengan output: export. Route yang butuh backend diberi nama *.live.tsx dan hanya didaftarkan untuk build live.
  • Basemap peta diganti di tengah proyek: PRD menyebut tile CartoDB/OpenStreetMap berkunci, tapi kini yang terbit adalah ekstrak Protomaps yang di-hosting sendiri dari public/tiles/ milik frontend, tanpa dependensi eksternal atau kunci saat runtime.
  • Palet gelap "Fault Line" dari PRD digantikan sistem "Kertas & Tinta" yang light-default, memakai Plus Jakarta Sans dan JetBrains Mono. Warna teks redup terukur sekitar 3,4:1 terhadap kartu, di bawah WCAG AA, jadi semua token teks disetel ulang. Warna hex juga diam-diam merusak modifier opacity Tailwind; kini setiap warna dideklarasikan sekali sebagai kanal RGB yang dipisah spasi.
  • Data referensi: 6 fitur sesar, 52 batas wilayah administratif, 20 catatan bencana historis (Aceh 2004 sampai Cianjur 2022, naik dari 6 sebelumnya). Di luar PRD: persentil, papan peringkat wilayah, perbandingan yang dilebur ke halaman wilayah, daftar periksa kesiapsiagaan "Siap Gempa", dan langganan email pantauan lokasi.
  • Semua grafik memakai Recharts; daftar "Recharts + D3.js" di PRD sudah tidak akurat, D3 tidak ada di kodenya.
  • 4 viewset DRF (gempa, wilayah, sesar, bencana), 3 endpoint mandiri (pengecekan risiko, zona pesisir tsunami, meta) dan 2 endpoint peringatan; 10 route frontend statis plus 2 yang khusus live; sekitar 56 komponen; workflow CI/CD 320 baris. 119 commit dari 1 Juli sampai 27 September 2026, dalam tiga tahap; sekitar 2.800 baris Python backend dan 7.800 baris kode frontend.

Tangkapan layar

Beranda
Beranda (2)
Wilayah
Peta
Wilayah Detail
Wilayah Detail (2)

Sedang merekrut, atau membangun hal serupa?

Saya terbuka untuk posisi full-time dan proyek freelance tertentu.