Enam bulan membangun Bookverse, sendirian
Ada versi romantis dari membangun perangkat lunak sendirian, di mana kamu memiliki meja yang rapi, sebuah espresso, dan kamu merilis sesuatu yang dicintai orang sebelum jam makan siang. Versi yang benar-benar saya jalani selama enam bulan terakhir lebih mirip “menulis konfigurasi Nginx yang sama sebanyak empat kali karena edge case ketujuh baru saja menggigitmu.”
Ini adalah sebuah refleksi — bukan daftar centang hal-hal yang sudah dirilis, bukan tutorial. Hanya catatan dari enam bulan perjalanan.
Mengapa saya memulai
Saya sudah memakai aplikasi belajar bahasa secara tidak menentu selama bertahun-tahun dan menyadari sesuatu yang spesifik: saya bisa menyelesaikan streak 30 hari di aplikasi gamifikasi populer namun tetap tidak bisa membaca satu paragraf teks asli. Loop umpan baliknya rapat, gamifikasinya mulus, tetapi satuan kemajuannya adalah sebuah kalimat, kadang sebuah kata. Dan membaca bahasa — benar-benar membacanya — terjadi pada level halaman.
Saya menginginkan aplikasi yang memperlakukan buku teks seperti buku teks. Buka bab satu. Baca. Dengarkan. Ucapkan kembali. Pelajari apa yang melekat. Besok, bab dua.
Bentuk produk itu sudah jelas sejak hari pertama. Jebakannya adalah “bentuk jelas sejak hari pertama” hanya bertanggung jawab atas mungkin 5% dari membangun perangkat lunak. 95% sisanya adalah bagian tengah yang tidak glamor.
Bagian tengah yang tidak glamor
Daftar tak lengkap dari hal-hal yang saya lakukan kuartal ini yang tidak ada di catatan rilis mana pun:
- Mengganti nama seluruh pohon jalur monorepo dari
app_v54_01menjadibookverse(dan mengganti namanya lagi ketika saya ingin garis bawah di nama unit systemd). - Menulis empat versi konfigurasi Terraform untuk vhost Nginx sebelum
menemukan bahwa trigger
null_resourceperlu menyertakan hash dari template yang sudah dirender, bukan hanya variabel input. - Menghabiskan seminggu melacak mengapa sebuah nilai env
EXPO_PUBLIC_*ter-resolve menjadi string kosong di bundle web tetapi berjalan baik di iOS. (preset-expomilik Babel melewati inlining untuknode_modules. Fungsi factory, bukan variabel env, di paket yang sudah dipublikasikan.) - Merefaktor 17 pemanggil sebuah helper URL API karena saya salah memusatkannya pada percobaan pertama.
Tidak satu pun dari ini akan masuk ke postingan pemasaran tentang aplikasi itu. Semuanya adalah pekerjaan yang sesungguhnya.
Hal yang tidak diperingatkan siapa pun tentang pengembangan solo adalah tidak ada orang yang menyerap separuh yang membosankan. Kamu tidak bisa bilang “tim platform menangani deploy” karena kamulah tim platform itu. Kamu memakai setiap topi dengan buruk sampai kamu memakainya cukup lama untuk memakainya dengan baik.
Lubang kelinci pengenalan suara
Episode paling instruktif dalam enam bulan terakhir adalah membuat latihan berbicara berfungsi di ponsel di Tiongkok.
Rencananya: ketuk sebuah baris, dengar penutur asli mengucapkannya, ketuk
lagi, rekam dirimu sendiri, lihat seberapa dekat hasilmu. Pengenalan suara
seluler standar — expo-speech-recognition di iOS, layanan sistem di
Android, selesai.
Kenyataannya: sebagian besar audiens target memakai ponsel Lenovo Motorola
dengan varian OS versi Tiongkok (overlay gmsconfig.china), yang membuang
Google Mobile Services sepenuhnya. Tidak ada speech-to-text sistem. Aplikasi
berjalan sempurna di emulator. Di sebuah Moto XT2507 di Beijing, ia crash
tanpa suara.
Perbaikannya memakan waktu sekitar tiga minggu:
- Membangun pola adapter agar aplikasi bisa menukar backend suara per platform — pengenalan sistem di mana tersedia, transkripsi cloud sebagai fallback.
- Menambahkan backend cloud bergaya Whisper (
qwen3-asr-flashdari Alibaba via DashScope, karena perangkat versi Tiongkok bisa menjangkaunya tanpa VPN). - Menyetel deteksi aktivitas suara agar rekaman berhenti otomatis ketika kamu selesai bicara. (Ambang -25 dBFS, jendela hening 600ms, dihaluskan atas lima sampel — setiap kombinasi lain entah memotongmu di tengah kata atau tidak pernah berhenti sama sekali.)
- Beralih dari unggahan
FormDataReact Native keuploadAsyncmilikexpo-file-system, karenaFormDataRN tidak stabil dengan blob audio di perangkat yang sama.
Separuh dari empat poin itu adalah lebih banyak kode daripada yang saya tulis dalam seminggu biasa. Tidak satu pun adalah “sebuah fitur.” Semuanya perlu agar fitur itu ada bagi orang-orang yang membutuhkannya.
Pelajarannya — terulang kira-kira setiap dua minggu — adalah bahwa bagian yang sulit jarang merupakan bagian yang kamu kira akan sulit. Saya menganggarkan satu hari untuk pengenalan suara. Butuh dua puluh hari.
Disiplin menyelesaikan
Godaan ketika membangun sendirian adalah mengejar yang baru dan berkilau. Fitur baru itu menarik. Penyesuaian ke-47 pada alur yang sudah ada tidak. Jadi kamu menumpuk fitur, yang tidak satu pun benar-benar selesai, dan produk terasa seperti kuburan bangunan setengah jadi.
Disiplin yang terus saya pelajari ulang: selesaikan satu hal dengan benar sebelum memulai yang berikutnya. Mandarin dulu. Buat Mandarin benar-benar bagus. Lalu Korea. Lalu Inggris. Platform ini dibangun untuk menyampaikan kursus terstruktur — tetapi kursus pertama harus menjadi yang unggulan, yang benar-benar bisa diselesaikan oleh seorang pembelajar.
Kursus Korea yang direncanakan dan baru 5% jadi tidak membantu siapa pun. Kursus Mandarin yang selesai, yang bisa dibaca seseorang dari awal sampai akhir, adalah produk yang nyata.
Begitu pula dengan fitur. Latihan berbicara ada di roadmap selama tiga bulan sebelum dirilis. Ia dirilis terlambat, tetapi dirilis dengan benar — menangani kasus wilayah Tiongkok adalah elemen penyangga agar ia dapat digunakan, bukan detail pemolesan yang bisa ditunda.
Apa yang akan saya katakan pada diri saya di bulan November
Tiga hal, andai saya bisa mengirim kartu pos kembali ke versi diri saya yang memulai ini.
Berhenti mengganti nama. Nama adalah hal yang wajar salah di hari pertama. Mengganti nama lagi lebih banyak menguras daripada manfaatnya dalam sebagian besar kasus. (Saya sudah melakukan ini tepat empat kali sekarang.)
Beli buku terstruktur. Saya menghabiskan berminggu-minggu memantul di antara daftar kosakata dari forum. Standar HSK 3.0 adalah dokumen terbit yang nyata. Membeli buku terstruktur dan mengikutinya lebih cepat daripada merekayasa balik apa yang mereka cakup.
Audiensnya sabar. Saya terus berpikir saya harus merilis cepat atau orang akan kehilangan minat. Sebaliknyalah yang benar: pembelajar bahasa menurut definisinya sabar — mereka sudah berkomitmen pada satu tahun latihan. Mereka tidak butuh demo di hari ketiga. Mereka butuh sesuatu yang berfungsi di hari ketiga ratus.
Apa selanjutnya
Mandarin terus tumbuh — Band 1 dan Band 2 sudah aktif, Band 3 sedang diaudit sekarang. Penyusunan konten kursus Korea dimulai setelah Mandarin Band 3 dirilis. Sisi platform lebih tenang dibanding enam bulan lalu, yang berarti lebih banyak waktu masuk ke konten pembelajaran yang sebenarnya — yang memang seharusnya menjadi tempatnya.
Jika kamu memakai Bookverse: terima kasih. Jika belum: bukalah sebuah bab suatu saat. Yang pertama gratis.