Vibe Coding sampai Live Dari Webpify Pribadi ke Converter Tim Kantor

Ilustrasi developing tools

Setelah Webpify, Sekarang Giliran Kantor

Aku sudah lebih dulu membuat Webpify, converter WebP pribadi yang berjalan penuh di browser, tanpa mengirim gambar ke server mana pun. Proyek itu lahir dari vibe coding di AI Studio, dan sekarang sudah online. Ide yang tadinya cuma wacana akhirnya bisa dibuka siapa saja lewat satu alamat.

Setelah itu muncul pikiran berikutnya: kenapa tidak dibuat juga untuk tim kantor Agro Sukses Abadi, dan dipasang di hosting kantor sendiri? Sebagai SEO Specialist yang mengurus beberapa website brand, aku melihat masalah yang sama berulang: gambar. Foto produk, banner, dan thumbnail artikel datang sebagai PNG atau JPG berukuran besar, lalu masuk ke website apa adanya. Obatnya sederhana, ubah ke WebP. Yang bikin males justru caranya: unggah satu-satu ke situs converter pihak ketiga, atau buka aplikasi yang belum tentu dipasang semua orang di tim.

Bedanya dengan proyek pribadi, versi kantor harus terasa milik tim: identitas brand Eka Farm, repo di organisasi, dan alamat di domain kantor. Tulisan ini mencatat perjalanan dari kode yang sudah jadi itu sampai siap tayang di subdomain converter.ekafarm.com, termasuk jebakan-jebakan yang aku temui di tengah jalan.

Kenapa Gambar yang Ringan Itu Urusan SEO

Menurut pengujian Google, WebP lossy berukuran 25 sampai 34 persen lebih kecil daripada JPEG yang sebanding pada indeks kualitas SSIM yang sama, sedangkan WebP lossless 26 persen lebih kecil daripada PNG. Untuk gambar bertransparansi yang boleh dikompresi lossy, WebP biasanya sekitar tiga kali lebih kecil daripada PNG (Google for Developers). Chrome, Safari, Firefox, Edge, dan Opera sudah mendukungnya secara native.

Angka itu baru berarti kalau dikaitkan dengan kecepatan halaman. Salah satu metrik Core Web Vitals adalah Largest Contentful Paint (LCP), yaitu saat konten terbesar di layar selesai tampil. Pada banyak halaman, konten terbesar itu adalah gambar utama. Batas LCP yang dianggap baik adalah 2,5 detik atau kurang pada persentil ke-75 pengunjung, dan di atas 4 detik dinilai buruk (web.dev). Memperkecil gambar utama adalah salah satu cara paling murah untuk mendekati batas itu.

Catatan jujur: angka di atas adalah hasil benchmark Google, bukan hasil pengukuran gambar milik tim kita. Penghematan sebenarnya bergantung pada jenis gambar, kualitas yang dipilih, dan ukuran awalnya. Setelah tool ini dipakai rutin, aku mau mencatat selisih nyatanya.

Dari Satu Prompt ke Produk yang Terasa Milik Tim

Hasil awal dari AI Studio, yang sekarang online sebagai Webpify, langsung jalan: unggah gambar, atur kualitas, konversi, unduh. Strukturnya juga lumayan rapi, dipecah ke komponen, hook, dan utilitas. Tampilannya gelap bergaya cyberpunk. Cocok untuk proyek pribadi, tapi jelas bukan wajah Eka Farm.

Sebelum mengubah apa pun untuk versi kantor, aku kunci kondisi awalnya di Git dengan tag v0-oneshot. Kalau nanti berantakan, ada tempat untuk pulang. Setelah itu urutannya sengaja dibuat membosankan:

  1. Refactor tanpa mengubah tampilan. Semua warna yang tertanam langsung di komponen dipindahkan ke theme token. Hasil visualnya harus identik. Kalau ada yang berubah, berarti ada yang salah.
  2. Ganti tema. Setelah warna terpusat, tema light Eka Farm cukup dibuat dengan mengganti token: palet, peran teks, sampai warna status bahaya.
  3. Ganti font. Nunito untuk teks utama dan JetBrains Mono untuk teks monospace, keduanya di-host sendiri supaya tidak bergantung pada layanan font eksternal.

Untuk identitas visual, aku pakai logo tiga daun milik Eka Farm yang aku trace menjadi SVG. Ada kejutan kecil di sini: tiga file hasil trace ternyata berisi bentuk daun yang sama persis dalam tiga warna. Jadi cukup satu <path> yang ditampilkan tiga kali dengan <use>, dan ukuran file turun ke sekitar 4 KB per file. Hasilnya jadi palet sederhana:

PeranHex
Daun tengah, hijau terang#a9d463
Daun kanan, hijau sedang#80c14d
Daun kiri dan theme color, hijau tua#467f43
Latar halaman dan ikon#fafafa

Pelajaran dari bagian ini: urutan kerja lebih menentukan daripada kecepatan mengetik. Refactor yang tidak mengubah tampilan membuat ganti tema berikutnya terasa aman, bukan menegangkan.

Rumah Baru untuk Kode: Dua Akun GitHub di Satu Mac

Kode proyek kantor sebaiknya tinggal di organisasi, bukan di akun pribadi. Masalahnya, Macku sudah lama login sebagai akun pribadi, dan GitHub tidak mengizinkan satu kunci SSH dipakai di dua akun. Solusinya satu kunci per akun, lalu satu alias host supaya Git tahu kunci mana yang dipakai.

Kunci khusus akun DevOps kantor dibuat dan dimasukkan ke agent:

ssh-keygen -t ed25519 -C "agro-devops" -f ~/.ssh/id_ed25519_agro_devops
ssh-add --apple-use-keychain ~/.ssh/id_ed25519_agro_devops

Lalu alias di ~/.ssh/config. Baris IdentitiesOnly yes penting supaya SSH tidak iseng mencoba kunci akun pribadi:

Host github-agro
       HostName github.com
       User git
       IdentityFile ~/.ssh/id_ed25519_agro_devops
       IdentitiesOnly yes
       UseKeychain yes
       AddKeysToAgent yes

Identitas commit juga dipisah, hanya untuk repo ini, tanpa menyentuh konfigurasi global:

git config --local user.name "agro-devops"
git config --local user.email "email-akun-devops@contoh.com"
git remote add origin git@github-agro:agro-sukses-abadi/converter-ekafarm.git

Saat tes pertama muncul Permission denied (publickey), dan sempat bikin aku mengira config-nya salah. Ternyata justru kebalikannya. Kalau alias salah, pesannya Could not resolve hostname. Pesan Permission denied berarti SSH sudah sampai ke GitHub dan ditolak di sana. Penyebabnya sepele: halaman SSH keys di akun DevOps masih kosong, public key belum didaftarkan. Setelah didaftarkan, balasannya berubah menjadi Hi agro-devops! dan push pertama langsung masuk.

Deploy Lewat Git Pull, Tanpa Node di Server

Berbeda dengan cerita hosting tanpa SSH yang pernah aku tulis, hosting kantor di Niagahoster punya akses SSH. Satu perintah cukup untuk mengecek isi servernya:

ssh login-niagahoster 'git --version; node -v; rsync --version | head -1'

Git (2.48.2) dan rsync ada, tapi Node tidak: node: command not found. Artinya npm run build tidak bisa dijalankan di server. Solusinya mirip trik vendor/ di cerita sebelumnya, hanya arahnya dibalik. Build dilakukan di laptop, lalu folder dist/ sengaja ikut masuk repo. Server cukup menarik dan menyalin.

Alurnya di laptop:

npm run build
find dist -name .DS_Store -delete
git add -Af dist
git commit -m "chore: build produksi"
git push

Baris find ... .DS_Store bukan hiasan. Waktu pertama kali git add -Af dist, file sampah bawaan macOS itu ikut masuk daftar. Kalau terbawa ke server, ia bisa diakses lewat URL dan membocorkan daftar nama file di folder tersebut.

Di server, repo di-clone di luar folder web, ke ~/repositories. Kalau di-clone langsung ke folder subdomain, .git, src/, dan package.json ikut bisa dibuka lewat browser. Yang masuk ke folder subdomain hanya isi dist/:

ssh login-niagahoster 'cd ~/repositories/converter-ekafarm && git pull --ff-only && rsync -a --delete --exclude=".well-known" --exclude="cgi-bin" dist/ ~/public_html/converter.ekafarm.com/'

Dua --exclude itu hasil dari mengintip isi foldernya dulu. Folder subdomain yang baru dibuat ternyata tidak kosong: ada .well-known yang dipakai untuk validasi sertifikat SSL, dan cgi-bin. Opsi --delete tanpa pengecualian akan menghapus keduanya. Karena itu langkah pertama selalu dry-run dengan opsi -n, yang hanya mencetak daftar tanpa mengubah apa pun. Daftar yang wajar berisi file-file dist/ dan tidak ada satu pun baris deleting.

Plot Twist: DNS di Cloudflare dan Status 200 yang Menipu

Subdomain sudah dibuat di panel hosting, file sudah tersalin, tapi alamatnya belum bisa dibuka. Alasannya sederhana: membuat subdomain di panel hosting tidak otomatis membuat record DNS-nya, dan DNS domain kantor dipegang Cloudflare. Urusannya pun berpindah ke admin, yang kebetulan memegang autentikasi dua langkah di ponselnya.

Daripada menunggu, aku tes lebih dulu tanpa DNS. Perintah curl --resolve memaksa sebuah nama domain diarahkan ke IP tertentu, seolah-olah DNS-nya sudah benar:

curl -I --resolve converter.ekafarm.com:80:IP_SERVER http://converter.ekafarm.com

Percobaan pertama menghasilkan 200 OK dan aku sempat senang. Untung sempat membaca header lainnya: Content-Length hanya 157 byte dan Last-Modified bertanggal Maret. Padahal index.html aplikasiku 1.595 byte dan baru ditulis hari itu. Yang menjawab ternyata halaman placeholder bawaan server, bukan aplikasiku. Status 200 hanya bilang bahwa ada yang menjawab, bukan bahwa yang menjawab itu benar.

IP yang aku pakai ternyata salah. Aku mengambilnya dari hasil resolve nama host server, sementara IP yang benar tertera sebagai Shared IP Address di sidebar cPanel. Mencari IP lewat dig ke domain kantor juga buntu, karena domainnya lewat proxy Cloudflare, jadi yang muncul adalah IP milik Cloudflare, bukan IP server asli. Dengan IP dari cPanel, hasilnya cocok: 1.595 byte, tanggal hari itu, dan baris pertama isinya <!doctype html> milik aplikasi.

Setelah terbukti, permintaan ke admin cukup satu record: tipe A, nama converter, mengarah ke IP server, dengan proxy dalam mode DNS only. Sertifikat SSL dari server diterbitkan dulu lewat AutoSSL. Proxy Cloudflare baru dinyalakan sesudahnya, dengan mode SSL/TLS Full (strict) supaya tidak terjadi redirect loop.

Saat tulisan ini dibuat, sisi server sudah siap dan terverifikasi lewat curl. Tinggal menunggu record DNS aktif.

Yang Aku Bawa Pulang

Vibe coding membawaku ke versi yang jalan jauh lebih cepat daripada menulis dari nol. Tapi tiga hal yang membuatnya layak dipakai tim, yaitu identitas brand, repo yang rapi, dan deploy yang bisa diulang, tetap kerja manual yang butuh dipikirkan.

  • Kunci baseline sebelum mengubah apa pun. Satu tag Git membuat eksperimen berani jadi murah.
  • Refactor tanpa perubahan tampilan dulu. Setelah warna terpusat di token, ganti tema bukan lagi operasi besar.
  • Satu kunci SSH per akun. Dan baca pesan error dengan teliti: Permission denied justru tanda konfigurasi sudah benar.
  • Clone di luar folder web. Yang boleh tampil di internet hanya isi dist/.
  • Dry-run sebelum --delete. Folder yang tampak kosong belum tentu kosong.
  • Jangan percaya status 200. Lihat ukuran dan tanggal file yang dikembalikan, baru yakin itu aplikasinya.

Langkah berikutnya sederhana: begitu DNS dan SSL aktif, tool ini dibuka untuk tim, dan aku mencatat berapa persen gambar yang benar-benar terpangkas. Kodenya terbuka di repositori GitHub organisasi, siapa tahu berguna untuk yang sedang mengalami kasus serupa. Versi pribadinya, Webpify, sudah online dan bisa dicoba siapa saja.

Sumber

 

Tidak ada komentar