Riwayat Chat Tersimpan di Lokal
Pencarian AI di blog ini sekarang ingat pertanyaan kemarin. Triknya: localStorage, cap 30 turn, dan try/catch yang diam-diam menyerah saat browser menolak.
Buka dialog search, lihat baris angka kecil di bagian bawah popup: 1, 2, 3, 4, 5. Klik angka 5. Jawaban kemarin sore langsung muncul di popup, lengkap dengan sumbernya. Riwayatnya ke-save sendiri ke browser.
Sebelum commit ini, history chat nggak persist. Tutup tab, semua hilang. Gue dulu pikir itu "cukup" — toh ini cuma tool pencarian, bukan sistem chat yang butuh audit trail. Tapi ternyata yang bikin tool ini berguna justru kemampuan balik ke pertanyaan kemarin. Pas nemu sumber yang relevan tapi belum sempat baca habis, harus mulai dari nol lagi. Frustrating banget.
Kenapa localStorage, bukan yang lain
Opsi paling gampang: sessionStorage. Tapi sessionStorage mati seiring session halaman — tutup tab, data hilang. Persis masalah yang mau diselesaikan. Opsi lain: backend sendiri. Overkill untuk tool yang cuma nyimpen riwayat pencarian satu user di satu browser.
localStorage persisten, ada di semua browser modern, dan gratis. Tapi ada jebakan: browser mode private bisa kasih quota kosong dari awal. Dan kalau user udah banyak nyimpen data lain di storage yang sama, setItem bisa melempar QuotaExceededError. Ini bukan edge case yang jarang — ini terjadi di production [7] source 7 [8] source 8.
Solusinya: feature detect + try/catch.
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(data))
} catch {
// QuotaExceededError di mode private browsing — gagal tanpa pesan
}
Yang bikin pengalaman ini beda dari sekadar nyimpen data biasa: format data di-version. Kalau besok gue ubah struktur JSON-nya, misalnya nambahin field mode atau fallback, versi lama yang tersimpan di browser nggak bikin aplikasi crash — cuma di-skip. Gue nulis versi payload sebagai angka, misalnya version: 1, dan kalau nanti gue bump ke version: 2, semua data versi 1 yang masih tertinggal di localStorage diabaikan secara diam-diam. Pembaca yang familiar dengan concept versioning di database pasti langsung ngerti pola ini — localStorage cuma tempat penyimpanannya yang beda.
Data disimpan sebagai JSON yang di-version. Kalau besok gue ubah formatnya, versi lama nggak nge-crash, cuma di-skip. Batas 30 turn itu juga pilihan yang disengaja. localStorage bisa handle lebih, bahkan ratusan turn tanpa masalah. Tapi tool pencarian ini nggak perlu simpen 200 pertanyaan lama. Yang terpenting adalah beberapa jawaban terakhir yang relevan saat pengunjung balik lagi. Kapasitas kecil juga bikin payload JSON tetap ringan — tidak ada risiko browser menolak ukuran data yang terlalu besar.
History di-cap 30 turn — angka yang sengaja gue pilih kecil. localStorage bisa handle lebih, tapi tool ini nggak perlu simpen 200 pertanyaan.
Angka-angka kecil yang nge-change everything
Gue tambahin paginasi sederhana: satu nomor per turn Q&A. Nomer aktif otomatis mengikuti turn yang lagi dibuka. Klik angka N, popup scroll dan fokus ke turn itu, sumbernya juga keliatan. Pertanyaan baru otomatis pindah ke nomor terbaru.
Nggak ada infinite scroll, nggak ada lazy load — cuma tombol angka yang bisa diklik.
Popup-nya juga render beda tergantung mode turn aktif: grid untuk about, list untuk search. Ini terlepas dari toggle yang lagi aktif di UI. Kedengarannya remeh, tapi kalau nggak di-handle, user klik nomor 3 pas lagi di mode about, tiba-tiba tampilannya berubah format tanpa peringatan.
Ada juga tombol clear-history dengan konfirmasi inline — bukan modal, bukan alert, tapi teks kecil yang muncul di tempat tombol itu, minta konfirmasi sekali lagi sebelum beneran hapus. Sengaja nggak pakai dialog browser. User harus sadar apa yang dia hapus, tapi nggak sampai terganggu alur kerjanya.
Desain untuk gagal mulus
Satu hal yang gue pelajari: fitur yang kelihatan sederhana — nyimpen data ke localStorage — punya banyak titik kegagalan yang real. Private browsing, quota penuh, browser lama yang nggak support, script blocker yang nonaktifkan storage.
Kalau gue nggak pake try/catch, satu user dengan browser yang aneh bakal lihat console error setiap kali buka tool. Itu bukan sekadar masalah UX — itu masalah kepercayaan. Kalau tool kasih error di halaman pertama, user nggak akan balik.
Jadi persistensi sisi klien yang murah harus didesain untuk gagal mulus. Kalau localStorage nggak bisa, tool tetap berfungsi tanpa riwayat. Untuk aplikasi semacam ini, localStorage yang persisten lebih tepat dari sessionStorage, dan feature detect + try/catch adalah satu-satunya pertahanan realistis terhadap kegagalan kuota [7] source 7 [8] source 8.
Kalau kamu lagi bikin fitur serupa, cek dulu jawaban AI streaming di blog lewat fetch biasa — karena ada kalanya persistensi sisi klien nggak cukup dan kamu butuh sesuatu yang lebih permanen di server.