frontend
Incentro
Situs perusahaan konsultan IT multi-bahasa di atas headless CMS, lengkap dengan indexer pencarian sendiri.
- Peran
- Software Engineer
- Tanggal
- Januari 2026
Teknologi
- next.js
- react
- typescript
- contentful
- graphql
- next-intl
- algolia
- fastify
- redis
- turborepo
- tailwind css
- gcp
Masalah
Situs ini adalah platform pemasaran untuk kantor di beberapa kawasan: sebelas varian bahasa, dan setiap halaman dikendalikan editor konten, bukan kode. Kombinasi itu mematahkan asumsi yang biasa dipakai. Situs yang di-generate statis cepat tapi cepat basi; situs yang dirender per permintaan selalu segar tapi harus membayarnya di setiap kunjungan. Pencarian punya masalah serupa dalam bentuk lain: studi kasus dan insights baru harus segera bisa ditemukan, tanpa editor perlu memikirkan soal indeks.
Platform sebesar ini lebih banyak dirawat daripada dibangun, dan perawatannya sudah tertinggal. Pull request pembaruan dependensi menumpuk tak ter-merge selama berminggu-minggu; bukan karena pembaruannya sendiri berisiko, tapi karena lockfile-nya sudah tidak lagi sepakat dengan deklarasi dependensinya, sehingga semuanya berkonflik. Bug yang menunggu di backlog yang sama punya bentuk serupa: hanya muncul di tepi. Jam yang ditampilkan untuk locale Indonesia salah, karena formatter tanggalnya jatuh ke zona waktu Eropa untuk semua bahasa. Hero di halaman campaign berukuran dengan margin persentase yang hanya pas di satu viewport, menyisakan pita ruang kosong di bawahnya. Teks pada form kontak mendorong keluar dari tepi panelnya. Dan satu kegagalan proses layak disebut: ada merge yang mendarat di branch yang salah dan menyeret 111 berkas tak terkait, sehingga fitur yang tidak seharusnya berpindah terbaca seperti regresi.
Solusi
Konten dikelola di Contentful dan diambil lewat GraphQL. Skemanya di-generate dari CMS dan tipe
TypeScript-nya di-infer dengan gql.tada, sehingga field yang berubah di Contentful gagal saat
build, bukan menampilkan halaman kosong. Halamannya berupa server component di Next.js App Router,
sehingga tiap pengambilan data menempel pada komponen yang membutuhkannya.
Dua keputusan yang paling berpengaruh. Pertama, cache-nya berlapis dan cache handler Next.js
disandarkan ke Redis, jadi semua instance berbagi satu cache dan melihat invalidasi yang sama
alih-alih masing-masing menyimpan salinannya sendiri, yang membuat penskalaan horizontal
jadi aman, bukan sekadar mungkin. Kedua, routing bahasa lewat next-intl dengan localized
pathnames, yang memungkinkan sebelas bahasa berbagi satu basis kode dan tetap dirender statis.
Next.js sendiri dipatch lewat pnpm patch untuk memperbaiki bug s-maxage pada respons 404.
Pencarian dijalankan sebagai layanan terpisah: aplikasi Fastify yang mengindeks Contentful ke Algolia, dipicu webhook CMS saat publish dan scheduler tiap malam untuk sapuan penuh. Memisahkannya dari aplikasi web berarti kegagalan indeks tidak akan pernah menjatuhkan situsnya. Semuanya ada dalam satu monorepo Turborepo (aplikasi web, indexer, dan package bersama) lalu di-deploy ke Cloud Run sebagai server Next.js standalone, dengan Playwright menjalankan visual regression di CI; itu penting karena tata letaknya dikendalikan CMS.
Merapikan dependensinya adalah rangkaian langkah, bukan satu perintah: mutakhirkan main, merge ke tiap branch pembaruan satu per satu, lalu gabungkan hasilnya di satu branch agregat dan selesaikan konflik lockfile-nya sampai ia sepakat dengan dirinya sendiri lagi. Merge yang salah itu harus di-revert lebih dulu: cara tercepat membuka jalan adalah membatalkannya lalu mengerjakannya ulang di tempat yang benar.
Tiap bug diperbaiki di penyebabnya, bukan di gejalanya, dan yang zona waktu paling jelas menunjukkan bagaimana sampai ke jawaban yang lebih kecil. Pendekatan pertama menambahkan pemetaan tiga zona Indonesia plus helper yang memangkas offset dari string tanggal dan menormalkannya. Pendekatan kedua menghapus semuanya: untuk locale yang memang perlu dikoreksi, memotong offset dari string ISO sudah cukup. 82 baris jadi 12, tanpa mengubah perilaku. Hero-nya dibangun ulang di atas aset mask baru dengan margin tetap per breakpoint alih-alih persentase, dan itulah yang akhirnya menghilangkan sisa ruang kosongnya. Teks form dikembalikan ke dalam panel dengan memotong isinya dan memberi padding bawah responsif, bukan dengan memaksa scroll area setinggi penuh. Dan spec navigasinya berkembang dari dua halaman dengan asersi basi menjadi pemeriksaan logo, tiga item menu, dan tombol kontak di empat halaman.
Galeri
Tangkapan layar

Halaman depan
Kontak
Tertarik untuk bekerja sama?
Ceritakan apa yang sedang Anda bangun dan apa yang dibutuhkan. Catatan singkat sudah cukup.