Lewati ke konten
Revianto
Kembali ke portofolio

Undangoo: membangun produk undangan pernikahan yang mengutamakan privasi, dari awal sampai akhir

Gambaran umum

Undangoo adalah produk undangan pernikahan digital yang saya rancang, bangun, dan luncurkan sendiri. Pasangan membuat undangan, mengirim tautan pribadi ke setiap tamu, lalu tamu membuka undangan dan mengisi RSVP. Saya satu-satunya engineer: keputusan produk, API Go, tiga aplikasi web, infrastruktur, dan rilis.

Masalahnya

Undangan digital di Indonesia biasanya berupa templat dan satu tautan yang dibagikan di grup WhatsApp. Itu berfungsi, tetapi punya tiga kelemahan yang ingin saya hilangkan lewat desain:

  • Privasi tamu. Satu tautan publik berarti siapa pun bisa membukanya, meneruskannya, atau menebak tautan lain. Nama tamu dan RSVP bisa terbaca oleh orang yang tidak pernah diundang.
  • Desain yang seragam. Kebanyakan templat terlihat mirip dan dibuat mengikuti selera pasangan, bukan sebagai pengalaman web penuh yang rapi di ponsel.
  • Tanpa kendali bagi pasangan. Pasangan tidak bisa melihat siapa yang sudah membuka tautan, siapa yang sudah membalas, atau siapa yang perlu diingatkan tanpa menghubungi satu per satu.

Batasan

  • Satu engineer, jadi setiap sistem harus cukup sederhana untuk dijalankan dan diperbaiki sendirian.
  • Tamu membuka undangan di ponsel kelas menengah lewat data seluler, jadi halaman harus ringan dan cepat.
  • Data pribadi (nama, nomor telepon, RSVP) harus terlindungi sejak rilis pertama, bukan ditambahkan belakangan.

Yang saya bangun

Landing & tampilan tamuPanel customerAplikasi adminPostgreSQLRedis & antrean pekerjaanPenyimpanan objek + CDNLayanan emailAPI Go
Arsitektur tingkat tinggi

Satu tautan pribadi per tamu. Setiap tamu mendapat token unik. Tidak ada URL undangan publik yang bisa ditebak, sehingga tidak ada yang bisa di-enumerasi. Membuka tautan mencatat bahwa tamu sudah melihat undangan; membalas mencatat RSVP.

API Go dengan lapisan yang jelas. Backend adalah layanan Go (Fiber) di atas PostgreSQL, dengan Redis untuk pembatasan laju dan antrean pekerjaan untuk email. Kodenya dibagi menjadi route, service, dan model, dengan transaksi yang dibungkus konsisten sehingga satu langkah yang gagal tidak meninggalkan data setengah jadi. Isi undangan disimpan sebagai konfigurasi JSON bertipe, jadi menambah templat berarti menambah desain, bukan model data baru.

Lapisan query yang fleksibel. Saya merancang lapisan akses data agar query bisa dirakit, bukan satu blok tetap per model. Kondisi pencarian berupa pohon: grup AND dan OR bisa bersarang satu sama lain sedalam apa pun, sehingga filter seperti city = 'yogyakarta' AND (regency = 'sleman' OR regency = 'bantul') AND price = 100000 tetap bermakna benar, dengan kurung di tempat yang seharusnya. Setiap field dan operator diperiksa terhadap allow-list milik model itu, dan nilainya dikirim sebagai parameter. UNION antarmodel berada di lapisan repository, jadi setiap model tetap bisa dipakai sendiri. Setiap model menyimpan select, join, dan where default untuk data utama sebuah endpoint, dan fungsi-fungsi kecil, seperti validasi yang membaca database, bisa memakai model yang sama dan hanya mengambil bagian yang dibutuhkan, misalnya hanya join dan where. Ini berangkat dari batasan yang saya temui di proyek-proyek sebelumnya.

Empat peran yang dipisahkan di kode. Admin platform, customer yang memiliki undangan, tamu, dan publik anonim masing-masing punya route dan pemeriksaan sendiri. Customer wajib punya akun dengan email terverifikasi; tamu tidak pernah butuh akun.

Tiga aplikasi web berbasis Next.js. Satu aplikasi untuk landing page, tampilan tamu, dan panel customer; satu aplikasi admin terpisah, sehingga fitur admin tidak pernah dikirim ke browser customer. Saya memakai design system tertulis per area (landing, panel customer, dashboard pemilik, dan tiap templat premium) agar layar baru tetap konsisten.

Templat gratis dan premium. Templat gratis tersedia di semua paket. Templat premium menambah gerak bertema dan tata letak yang lebih kaya, dan pembatasannya dilakukan di server, bukan hanya disembunyikan di antarmuka.

Halaman galeri template Undangoo yang menampilkan empat dari dua belas template undangan pernikahan, masing-masing dengan tautan demo.
  • Layar pembuka template undangan cat air hijau kebiruan dengan dua burung di atas bunga, nama pasangan, dan tombol Buka Undangan.
  • Layar pembuka template undangan merah marun dengan bunga mawar, monogram, nama pasangan, dan tombol Buka Undangan.
  • Layar pembuka template undangan gelap dengan jalan dan perbukitan di latar, huruf tebal untuk nama pasangan, dan tombol Buka Undangan.
  • Layar pembuka template undangan hijau tua dengan monogram emas, ranting zaitun, nama pasangan, dan tombol untuk membuka surat.
Layar demo, data pasangan dan tamu fiktif

Tantangan keamanan

Karena produk ini menyimpan data pribadi, saya memperlakukan keamanan sebagai bagian dari daftar fitur:

  • Login admin platform memerlukan kode sekali pakai lewat email selain kata sandi, dan perangkat baru dicatat.
  • Kode sekali pakai memiliki batas percobaan, sehingga tidak bisa ditebak dengan brute force.
  • Kata sandi diperiksa dengan kebijakan kekuatan, dengan satu aturan bersama dan kasus uji bersama agar server dan kedua aplikasi web sepakat.
  • Formulir publik memakai perlindungan bot dan kolom honeypot.
  • Peran diisolasi di lapisan data. Saya meninjau isolasi ini, memperbaiki masalah kontrol akses yang ditemukan saat peninjauan, dan melindunginya dengan test.
  • Data pribadi punya aturan retensi: undangan dan data tamunya dihapus permanen 30 hari setelah paket berakhir, dan customer melihat peringatan dengan tanggal pastinya sebelum itu terjadi.

Saya juga sengaja tidak membahas penanganan pembayaran di tulisan ini, dan tidak ada rahasia yang disimpan di repositori; konfigurasi berasal dari environment.

Rilis dan kualitas

  • Rilis: aplikasi web dan API dirilis otomatis dari branch utama lewat CI. Container menjalankan layanan, dan aset statis disajikan dari penyimpanan objek di belakang CDN.
  • Backup dan peringatan: backup database berjalan harian ke penyimpanan terpisah, dan kegagalan memunculkan peringatan di ponsel saya.
  • Pengujian: unit test di backend, dan end-to-end test yang berjalan di browser Chrome sungguhan. Sebuah fitur baru dianggap teruji setelah suite end-to-end lulus di sana.
  • Keputusan tertulis: rencana produk, implementasi saat ini, dan kebenaran produk disimpan dalam tiga dokumen yang disinkronkan, dan tugas terbuka berada di satu pelacak. Untuk proyek satu orang, inilah yang menjaga keputusan agar tidak hilang.

Hasil

  • Undangoo sudah berjalan di produksi di undangoo.com, dengan paket gratis dan berbayar, aplikasi admin, dan 12 templat di tingkat gratis dan premium.
  • Pemasaran publik sudah dimulai. Saya belum mencantumkan angka penggunaan, karena produknya masih baru dan saya lebih memilih angka yang nyata daripada angka yang terlihat besar.
  • Backend dan infrastrukturnya cukup kecil sehingga satu orang bisa mengoperasikan dan mengubahnya dengan aman, dan itulah tujuan engineering utamanya.

Yang saya pelajari

  • Merancang privasi sejak awal (satu tautan pribadi per tamu, peran yang ketat) jauh lebih murah daripada menambahkannya belakangan.
  • Satu sumber kebenaran untuk aturan yang dipakai beberapa aplikasi, seperti kebijakan kata sandi, mencegah penyimpangan diam-diam yang menjadi sumber bug.
  • State yang milik satu request harus tetap bersama request itu. Di proyek sebelumnya yang memakai Gin, context diambil dari *gin.Context global sehingga sering terjadi response ganda; di Fiber context dioper secara eksplisit ke tiap lapisan, jadi bug itu tidak bisa terjadi, dan ketika saya menemui masalah yang sama di proyek sebelumnya, saya sudah tahu cara memperbaikinya.
  • Untuk produk solo, keputusan yang tertulis dan test otomatis lebih penting daripada pilihan teknologi tunggal mana pun.

Stack

Go, Fiber, PostgreSQL, Redis, Next.js, Docker, Cloudflare R2, GitHub Actions.

Hubungi saya
Lihat CV