Pengantar Penulis
Setiap proyek perangkat lunak dimulai dari satu pertanyaan yang menipu karena tampak sederhana: "Aku mau bangun apa, dan tumpukan teknologi apa yang paling cepat membawaku ke sana tanpa menyesal enam bulan kemudian?" Buku ini lahir dari pertanyaan itu, khususnya dalam konteks yang kini disebut vibe coding — membangun perangkat lunak dengan cepat, dibantu model AI, mengikuti "getaran" dan intuisi alih-alih ritual rekayasa yang berat.
Vibe coding membuat pembuatan kode terasa lancar: Anda mendeskripsikan maksud, AI menuliskan implementasi, dan iterasi berjalan dalam hitungan menit. Tetapi kecepatan itu menyembunyikan sebuah jebakan. AI dengan senang hati menuliskan kode apa pun yang Anda minta — termasuk arsitektur yang salah untuk masalah Anda. Ia tidak akan menghentikan Anda saat memilih microservices untuk aplikasi yang hanya dipakai 20 orang, atau saat menaruh kunci rahasia di kode frontend. Keputusan arsitektur tetap milik Anda. Buku ini adalah peta untuk keputusan-keputusan itu.
Pertanyaan inti yang menjadi tulang punggung buku ini: untuk sebuah bukti konsep (proof of concept, PoC) atau produk awal, apakah cukup membangun frontend dan backend sebagai dua layanan terpisah, ataukah lebih baik satu aplikasi full-stack Next.js? Jawabannya, seperti hampir semua hal dalam rekayasa, adalah "tergantung" — tetapi tergantung pada faktor-faktor yang bisa dipetakan dengan jelas. Itulah yang buku ini lakukan.
Segala sesuatu harus dibuat sesederhana mungkin, tetapi tidak lebih sederhana dari itu.
Prinsip yang lazim dikaitkan dengan Albert Einstein
Buku ini punya dua jenis pembaca sekaligus, dan itu disengaja. Yang pertama adalah Anda, manusia — developer, founder teknis, mahasiswa, atau siapa pun yang ingin memahami lanskap keputusan sebelum menulis baris kode pertama. Yang kedua adalah agent AI yang mungkin membaca buku ini sebagai konteks saat membantu Anda memrogram. Karena itu strukturnya dibuat rapi dan semantik: heading berjenjang, definisi eksplisit, ringkasan poin, dan blok kode yang benar. Bab 16 menjelaskan secara khusus bagaimana sebuah agent sebaiknya mengonsumsi dokumen ini.
Yang dibahas: pemilihan framework frontend & backend, arsitektur monolith vs microservices, database & data, koneksi FE↔BE, keamanan, UI/UX, tooling, deployment & go-live, license manager, SaaS vs on-premise, Chrome extension, hingga studi kasus nyata.
Yang bukan tujuan: menggantikan dokumentasi resmi tiap alat. Ini peta keputusan, bukan manual API.
Cara Membaca Buku Ini
Ada tiga cara memakai buku ini, tergantung kebutuhan Anda saat ini:
- Baca berurutan jika Anda ingin membangun model mental lengkap. Alur bab sengaja disusun dari "apa yang dibangun" (Bab 1–4) menuju "bagaimana menyusunnya" (Bab 5–10) lalu "bagaimana menerbitkan & mengkomersialkan" (Bab 11–14) dan ditutup penerapan (Bab 15–17).
- Lompat lewat Daftar Isi di kiri (aktif mengikuti posisi baca) jika Anda datang dengan pertanyaan spesifik, misalnya "REST atau tRPC?" atau "argon2 atau bcrypt?".
- Mulai dari Pemilih Tech Stack di bawah jika Anda ingin rekomendasi cepat, lalu telusuri bab yang relevan untuk memahami alasannya.
Konvensi Penulisan
- ✔ Kotak hijau = praktik yang dianjurkan. ▲ Kotak amber = peringatan / jebakan umum.
- Setiap bab ditutup blok Poin Kunci — ringkasan padat yang aman dikutip agent AI.
- Blok kode punya tombol salin dan dapat digulir horizontal.
- Istilah teknis pertama kali muncul ditulis lengkap, dan semuanya terkumpul di Glosarium.
Pemilih Tech Stack
Jawab enam pertanyaan singkat. Alat ini akan menyusun rekomendasi tumpukan teknologi — frontend, backend, database, arsitektur, hosting, dan model distribusi — beserta alasannya. Semua berjalan di browser Anda; tidak ada data yang dikirim ke mana pun.
Rancang tumpukan Anda dalam 30 detik
Pilih satu opsi per pertanyaan, lalu tekan Susun Rekomendasi.
Logika rekomendasi alat ini bersifat heuristik dan sengaja konservatif: ia condong ke tumpukan paling sederhana yang masih memenuhi kebutuhan. Jika Anda (agent) menyusun rekomendasi serupa untuk pengguna, gunakan kerangka faktor yang sama — jenis proyek, skala, real-time, kebutuhan Python/AI, tempat deploy, ukuran tim — dan jelaskan trade-off, bukan hanya nama alat.
Pendahuluan: Vibe Coding
Istilah vibe coding dipopulerkan pada awal 2025 oleh Andrej Karpathy untuk menggambarkan gaya membangun perangkat lunak di mana developer "menyerahkan diri pada getaran" dan membiarkan model AI menuliskan sebagian besar kode, sementara manusia berperan sebagai pengarah maksud, penguji, dan pengambil keputusan. Dalam praktiknya, vibe coding berarti Anda mendeskripsikan apa yang diinginkan dalam bahasa alami, AI menghasilkan implementasi, lalu Anda menilai, mengoreksi arah, dan mengiterasi — sering kali tanpa membaca setiap baris kode.
Gaya ini luar biasa untuk kecepatan. Yang dulu butuh sehari kini bisa selesai dalam satu jam. Tetapi ada satu hal yang tidak berubah, dan justru menjadi makin penting: arsitektur tetap tanggung jawab manusia. Model AI mengoptimalkan "menjawab permintaan Anda", bukan "menyelamatkan Anda dari keputusan buruk". Jika Anda meminta microservices, ia memberi microservices. Jika Anda menaruh koneksi database di komponen klien, ia mungkin tetap menuliskannya. Getaran yang bagus tidak menghasilkan arsitektur yang bagus secara otomatis.
AI tidak akan mengoreksi arsitektur Anda kecuali diminta. Ia akan dengan patuh membangun sistem yang terlalu rumit, tidak aman, atau salah tempat. Kecepatan menulis kode justru memperbesar biaya keputusan yang salah — karena Anda menumpuk lebih banyak kode di atas fondasi yang keliru, lebih cepat.
Anatomi Sebuah Aplikasi Web
Sebelum memutuskan "terpisah atau monolit", kita perlu bahasa bersama. Hampir semua aplikasi web punya tiga lapisan:
- Frontend (klien) — yang berjalan di browser pengguna: HTML, CSS, JavaScript. Bertugas menampilkan antarmuka dan menangkap interaksi.
- Backend (server) — logika bisnis, otentikasi, akses database, integrasi pihak ketiga. Berjalan di server yang Anda kendalikan.
- Database — tempat data disimpan secara persisten.
Pertanyaan buku ini menyangkut hubungan dua lapisan pertama. Ada dua pola besar:
Kapan Masing-masing Cukup?
Inti keputusannya bisa diringkas menjadi beberapa pertanyaan penyaring. Monolit Next.js biasanya cukup ketika: proyek Anda berbasis web, tim kecil atau solo, tidak butuh komputasi Python berat, dan skala awal masih wajar. Frontend & backend terpisah menjadi perlu ketika salah satu benar: Anda butuh layanan AI/Python tersendiri, ada beberapa klien berbeda (web + mobile + IoT) yang berbagi satu API, real-time berskala besar, atau tim besar yang perlu bekerja pada sisi berbeda secara independen.
| Faktor | Condong ke Monolit Next.js | Condong ke Terpisah |
|---|---|---|
| Ukuran tim | Solo / kecil | Besar, terbagi FE/BE |
| Kebutuhan Python/AI | Tidak ada / sekadar panggil API | Model/ML/Python sendiri |
| Jumlah klien | Satu (web) | Banyak (web+mobile+publik API) |
| Real-time | Ringan / tidak | Berat & berskala |
| Kecepatan ke PoC | Prioritas utama | Bukan prioritas utama |
| Kebutuhan skala mandiri | Belum | Sudah, per komponen |
Buatlah berfungsi, buatlah benar, buatlah cepat — dalam urutan itu.
Kent Beck
Urutan Kent Beck ini adalah kompas vibe coding. Untuk PoC, tujuan Anda adalah make it work — dan monolit Next.js hampir selalu jalur tercepat ke sana. Optimasi arsitektur (memisah layanan, menambah cache, memecah microservices) adalah pekerjaan make it fast yang datang belakangan, hanya setelah Anda tahu apa yang benar-benar perlu dioptimalkan.
Poin Kunci Bab 1
- Vibe coding = membangun cepat berbantuan AI; kecepatan menulis kode naik, tetapi tanggung jawab arsitektur tetap di tangan manusia.
- Aplikasi web punya tiga lapisan: frontend, backend, database. Keputusan besar pertama adalah pola hubungan FE↔BE.
- Monolit Next.js cukup untuk mayoritas PoC berbasis web dengan tim kecil tanpa Python berat.
- Pisahkan FE/BE hanya jika ada pemicu jelas: Python/AI, banyak klien, real-time skala besar, atau tim besar.
- Ikuti urutan Kent Beck: berfungsi → benar → cepat. Jangan optimasi sebelum ada yang bekerja.
Analisis Framework Frontend
Frontend adalah wajah aplikasi Anda — satu-satunya bagian yang benar-benar dilihat pengguna. Memilih framework frontend menentukan kecepatan pengembangan, performa, kemudahan mencari kontributor (termasuk seberapa baik AI membantunya), dan batas apa yang bisa Anda capai. Tidak ada pemenang mutlak; ada pemenang untuk konteks tertentu. Bab ini membedah tujuh keluarga besar.
React & Next.js
React adalah pustaka UI berbasis komponen dari Meta, dan menjadi standar de facto industri. Next.js adalah framework di atas React yang menambahkan routing, rendering di server (SSR), pembangkitan statis (SSG), server components, dan API routes. Untuk vibe coding, pasangan ini punya keunggulan besar yang jarang disebut: ia adalah ekosistem dengan data pelatihan terbanyak, sehingga model AI menghasilkan kode React/Next paling akurat dibanding framework lain.
Kelebihan: ekosistem raksasa, komponen siap pakai melimpah (shadcn/ui, Radix), dukungan AI terbaik, full-stack dalam satu framework (Next), karier & talenta luas. Keterbatasan: React sendiri "hanya" pustaka — Anda menyusun banyak keputusan; bundle bisa besar; App Router Next.js punya kurva belajar (server vs client components membingungkan pemula). Pakai saat: mayoritas kasus, terutama jika Anda mempertimbangkan monolit full-stack atau butuh dukungan AI maksimal.
Vue & Nuxt
Vue menawarkan model yang lebih ringan dan sintaks "single-file component" yang banyak disukai karena mudah dibaca. Nuxt adalah padanan Next.js untuk Vue (SSR, routing berbasis file, full-stack). Kelebihan: kurva belajar landai, dokumentasi rapi, reaktivitas elegan. Keterbatasan: ekosistem lebih kecil dari React; dukungan AI & ketersediaan talenta lebih terbatas; komponen pihak ketiga tak sebanyak React. Pakai saat: tim menyukai kesederhanaan Vue, atau proyek tidak menuntut ekosistem sebesar React.
Svelte & SvelteKit
Svelte adalah compiler: alih-alih mengirim runtime besar ke browser, ia mengompilasi komponen menjadi JavaScript kecil dan efisien. SvelteKit adalah framework full-stacknya. Kelebihan: bundle terkecil, performa runtime bagus, kode sangat ringkas, DX menyenangkan. Keterbatasan: ekosistem & komunitas paling kecil di antara "tiga besar"; lebih sedikit contoh untuk AI; talenta langka. Pakai saat: performa & ukuran bundle jadi prioritas, tim kecil yang nyaman merintis, atau proyek personal.
Angular
Angular (Google) adalah framework berbaterai lengkap: routing, forms, HTTP client, DI, semuanya bawaan, dengan TypeScript wajib. Ia beropini kuat. Kelebihan: struktur konsisten untuk tim besar, cocok aplikasi enterprise besar & berumur panjang, tooling matang. Keterbatasan: verbose, kurva belajar curam (RxJS, modul, DI), terasa berat untuk PoC kecil, kurang cocok gaya vibe coding yang lincah. Pakai saat: aplikasi enterprise besar dengan tim besar yang butuh keseragaman dan aturan ketat.
Astro
Astro dirancang untuk situs yang berat konten — blog, dokumentasi, marketing. Filosofinya "zero JS by default": HTML statis dulu, JavaScript hanya di pulau-pulau interaktif (islands) yang Anda tandai. Astro juga bisa menyisipkan komponen React/Vue/Svelte. Kelebihan: performa & SEO luar biasa, sempurna untuk landing & dokumentasi (termasuk buku HTML seperti ini). Keterbatasan: bukan untuk aplikasi kaya interaksi/dashboard. Pakai saat: konten > interaksi — landing page, blog, docs.
SolidJS
SolidJS punya sintaks mirip React (JSX) tetapi dengan reaktivitas fine-grained tanpa virtual DOM, menghasilkan performa sangat tinggi. Kelebihan: performa puncak, API akrab bagi pengguna React. Keterbatasan: ekosistem muda & kecil, dukungan AI terbatas, risiko lebih tinggi untuk proyek jangka panjang. Pakai saat: performa reaktif ekstrem dibutuhkan dan tim bersedia merintis.
HTMX & Vanilla
HTMX membalik tren: alih-alih SPA berat, ia membiarkan HTML meminta fragmen HTML dari server lewat atribut, sehingga interaktivitas dicapai tanpa banyak JavaScript. Vanilla JS (tanpa framework) tetap valid untuk halaman sederhana. Kelebihan: sangat ringan, tanpa build tooling, dekat dengan platform web, pas dipadukan backend yang me-render HTML (Django, Rails, Go). Keterbatasan: tidak scalable untuk UI kompleks/stateful, manajemen state manual. Pakai saat: aplikasi CRUD sederhana, tim backend-centric, atau menghindari kompleksitas SPA.
Tabel Perbandingan Framework Frontend
| Framework | Tipe | Kurva | Bundle | Dukungan AI | Paling cocok untuk |
|---|---|---|---|---|---|
| React/Next | Pustaka + framework full-stack | Sedang | Sedang–besar | ★★★★★ | Mayoritas app & PoC full-stack |
| Vue/Nuxt | Framework full-stack | Landai | Sedang | ★★★★ | Tim yang suka kesederhanaan |
| Svelte/Kit | Compiler full-stack | Landai | Kecil | ★★★ | Performa & bundle minimal |
| Angular | Framework enterprise | Curam | Besar | ★★★★ | Enterprise besar, tim besar |
| Astro | Situs konten (islands) | Landai | Sangat kecil | ★★★ | Landing, blog, dokumentasi |
| SolidJS | Pustaka reaktif | Sedang | Kecil | ★★ | Performa reaktif ekstrem |
| HTMX/Vanilla | Minimal / no-framework | Landai | Minimal | ★★★ | CRUD sederhana, backend-centric |
Batasan Umum Semua Framework Frontend
Apa pun pilihannya, ada batas yang melekat pada kode yang berjalan di browser, dan penting dipahami sejak awal:
- Tidak ada rahasia di frontend. Semua kode klien dapat dibaca pengguna. Kunci API, kredensial database, atau logika lisensi rahasia tidak boleh ada di sana. Ini hukum keamanan, bukan preferensi.
- Tidak bisa akses database langsung. Browser tidak boleh membuka koneksi ke database produksi; harus lewat backend.
- Performa dibatasi perangkat pengguna. JavaScript berjalan di ponsel murah pengguna, bukan di server Anda.
- SEO butuh usaha ekstra pada SPA murni. Konten yang di-render sepenuhnya oleh JS bisa sulit diindeks; itulah alasan SSR/SSG ada.
Untuk vibe coding, default ke React/Next.js kecuali ada alasan spesifik. Alasannya bukan karena ia "terbaik" secara teknis, melainkan karena dukungan AI, ekosistem komponen, dan ketersediaan solusi membuat Anda bergerak paling cepat dengan risiko paling kecil. Pilih Astro untuk situs konten, dan pertimbangkan Svelte hanya bila performa/bundle jadi kebutuhan nyata.
Poin Kunci Bab 2
- Tidak ada framework terbaik mutlak; ada yang terbaik untuk konteks tertentu.
- React/Next unggul karena ekosistem & dukungan AI, menjadikannya default aman untuk vibe coding.
- Astro untuk konten, Svelte untuk performa/bundle, Angular untuk enterprise besar, HTMX untuk CRUD sederhana.
- Batas mutlak frontend: tidak ada rahasia, tidak ada akses DB langsung, performa terbatas perangkat pengguna.
Kebutuhan Backend
Backend adalah bagian yang berjalan di server yang Anda kendalikan: tempat logika bisnis dijalankan dengan aman, data disimpan, otentikasi diverifikasi, dan rahasia dijaga. Pertanyaan pertama bukan "backend apa", melainkan "apakah saya butuh backend sama sekali?"
Kapan Butuh Backend?
Anda butuh backend begitu salah satu dari ini benar:
- Menyimpan data yang harus bertahan & dibagikan antar pengguna (bukan sekadar di perangkat).
- Otentikasi & otorisasi — siapa boleh melihat/mengubah apa.
- Menyimpan rahasia — kunci API pihak ketiga, kredensial, konfigurasi sensitif.
- Logika yang tak boleh dipercayakan ke klien — harga, kuota, validasi bisnis, pembayaran.
- Integrasi server-ke-server, cron job, webhook, pengiriman email.
Anda mungkin tidak butuh backend penuh untuk: situs statis, landing page, brosur digital, atau kalkulator sisi klien. Untuk ini, hosting statis + satu-dua serverless function untuk form sudah cukup.
Optimasi prematur adalah akar dari segala kejahatan (setidaknya sebagian besarnya) dalam pemrograman.
Donald Knuth
Opsi Backend
Node.js — Express & NestJS
Express adalah framework Node minimalis: cepat dimulai, sangat fleksibel, tetapi tanpa struktur bawaan sehingga proyek besar mudah berantakan. NestJS menambahkan arsitektur beropini (modul, controller, service, dependency injection) di atas Node/TypeScript — mirip Angular untuk backend. Keunggulan Node secara umum: satu bahasa (JavaScript/TypeScript) dengan frontend, ekosistem npm raksasa, sangat cocok I/O-bound (banyak koneksi menunggu, seperti API & realtime). Pakai Express untuk API kecil/menengah; pakai NestJS saat tim & codebase tumbuh dan butuh struktur.
Next.js API Routes & Server Actions
Jika frontend Anda Next.js, backend bisa hidup di dalam framework yang sama. Route Handlers (folder app/api) membuat endpoint HTTP; Server Actions memungkinkan fungsi server dipanggil langsung dari komponen tanpa menulis endpoint manual. Ini adalah jantung "monolit full-stack": satu bahasa, satu repo, satu deploy. Batasnya: bukan untuk komputasi berat/berjalan-lama (fungsi serverless punya batas waktu), dan bukan pengganti layanan Python.
Python — FastAPI & Django
FastAPI adalah framework Python modern, cepat, async, dengan validasi tipe (Pydantic) dan dokumentasi OpenAPI otomatis — favorit untuk membungkus model AI/ML sebagai API. Django adalah framework "berbaterai lengkap" (ORM, admin, auth bawaan) untuk aplikasi berbasis data yang besar. Python adalah rumah bagi data science & AI (lihat di bawah).
Go
Go memberi performa tinggi, konkurensi bawaan (goroutine), dan biner tunggal yang mudah di-deploy. Cocok untuk layanan yang menuntut throughput tinggi, latensi rendah, atau infrastruktur (proxy, gateway). Kurang cocok untuk PoC cepat karena lebih verbose dan ekosistem web-nya lebih ramping.
Serverless Functions
Serverless (Vercel Functions, AWS Lambda, Cloudflare Workers) menjalankan fungsi tanpa mengelola server: bayar per eksekusi, skala otomatis. Ideal untuk beban tak menentu & endpoint ringan. Batas: cold start, batas waktu eksekusi, dan kurang cocok untuk koneksi persisten (WebSocket) atau proses panjang.
BaaS — Supabase & Firebase
Backend-as-a-Service memberi Anda database, otentikasi, storage, dan API instan tanpa menulis backend. Supabase berbasis PostgreSQL (SQL, portabel, punya realtime & row-level security). Firebase (Google) berbasis NoSQL (Firestore) dengan realtime kuat dan integrasi mobile mulus. BaaS mempercepat PoC secara dramatis; harganya: lock-in dan kendali lebih rendah saat kebutuhan menjadi rumit.
| Opsi | Bahasa | Sweet spot | Hindari saat |
|---|---|---|---|
| Express | JS/TS | API kecil/menengah, fleksibel | Butuh struktur ketat |
| NestJS | TS | Backend besar, tim, terstruktur | PoC super cepat |
| Next.js API/Actions | TS | Monolit full-stack, PoC web | Komputasi berat/panjang |
| FastAPI | Python | Layanan AI/ML, data | Tanpa kebutuhan Python |
| Django | Python | App data besar, admin bawaan | Microservice ringan |
| Go | Go | Throughput tinggi, infra | PoC cepat, tim kecil |
| Serverless | Apa saja | Beban tak menentu, endpoint ringan | WebSocket, proses panjang |
| Supabase/Firebase | — | PoC kilat, realtime, auth instan | Logika server kompleks & anti lock-in |
Mengapa AI Memakai Python — dan Kapan Itu Memaksa Pemisahan
Ini pertanyaan yang menentukan banyak keputusan arsitektur, jadi mari jelas: ekosistem AI/ML pada dasarnya adalah ekosistem Python. PyTorch, TensorFlow, NumPy, pandas, scikit-learn, Transformers (Hugging Face), LangChain — semuanya native Python. Riset, model, dan tutorial ditulis dalam Python. Jika pekerjaan Anda melibatkan menjalankan atau melatih model sendiri, memproses data numerik berat, atau computer vision, Anda praktis harus di Python.
Namun ada pembedaan penting yang menghemat banyak kerumitan:
- Hanya memanggil API LLM (mis. Claude, GPT) — Anda tidak butuh Python. Panggil endpoint HTTP dari backend Node/Next Anda. Jaga kunci API di server. Ini kasus paling umum untuk "aplikasi AI" masa kini.
- Menjalankan model/ML/Python sendiri — di sinilah Anda memisahkan: satu layanan Python (FastAPI) untuk AI, dan UI/BFF (Next.js/Node) yang memanggilnya lewat HTTP. Dua bahasa, dua deploy, tetapi masing-masing pada peran terbaiknya.
Poin Kunci Bab 3
- Butuh backend begitu ada data persisten bersama, auth, rahasia, atau logika yang tak boleh dipercayakan ke klien.
- Opsi berjenjang: Next API/Actions (paling ringkas) → Express/NestJS → FastAPI/Django → Go → serverless → BaaS.
- Sekadar memanggil API LLM tidak butuh Python; menjalankan model sendiri praktis memaksa layanan Python terpisah.
- BaaS (Supabase/Firebase) mempercepat PoC dengan harga lock-in dan kendali lebih rendah.
Full-Stack Next.js sebagai PoC
Untuk sebagian besar bukti konsep berbasis web, Next.js full-stack adalah jawaban paling praktis. Ia menyatukan frontend dan backend dalam satu framework TypeScript, satu proses build, satu proses deploy. Anda tidak perlu memelihara dua repositori, menyelaraskan dua bahasa, atau menyiapkan CORS antar-domain. Untuk tim kecil yang ingin bergerak cepat, penghematan overhead ini sangat besar.
Kapan Next.js Full-Stack Cukup
Monolit Next.js cukup ketika kebutuhan Anda cocok dengan mayoritas PoC web:
- Aplikasi web dengan CRUD, dashboard, form, autentikasi — pekerjaan roti-mentega web.
- Kebutuhan AI hanya sebatas memanggil API LLM eksternal.
- Satu klien (web); belum ada mobile native atau API publik lintas konsumen.
- Tim solo atau kecil, ingin satu basis kode yang mudah dinavigasi (juga oleh AI).
- Skala awal wajar; belum ada komponen yang perlu diskalakan mandiri.
Struktur App Router
App Router (Next.js 13+) mengatur routing lewat struktur folder di dalam app/. Setiap folder adalah segmen URL; file khusus punya makna tetap.
app/
├─ layout.tsx # kerangka bersama (nav, footer)
├─ page.tsx # halaman "/"
├─ globals.css
├─ (marketing)/ # route group, tak memengaruhi URL
│ └─ harga/page.tsx # "/harga"
├─ dashboard/
│ ├─ layout.tsx # layout khusus dashboard
│ ├─ page.tsx # "/dashboard"
│ └─ [id]/page.tsx # "/dashboard/:id" (dinamis)
├─ api/
│ └─ tugas/route.ts # endpoint HTTP "/api/tugas"
└─ actions.ts # server actions ("use server")
lib/ # util, klien db, skema
components/ # komponen UI reusable
prisma/schema.prisma # definisi database
Server Components vs Client Components
Inovasi terpenting App Router adalah React Server Components (RSC). Secara default, komponen berjalan di server: ia bisa mengambil data langsung (bahkan query database) tanpa endpoint API, dan tidak mengirim JavaScript-nya ke browser. Komponen yang butuh interaktivitas (state, event, useEffect) ditandai dengan "use client" di baris pertama.
// app/dashboard/page.tsx — berjalan di SERVER
import { db } from "@/lib/db";
export default async function Dashboard() {
// query langsung — tak perlu fetch/endpoint
const tugas = await db.tugas.findMany();
return (
<ul>
{tugas.map((t) => <li key={t.id}>{t.judul}</li>)}
</ul>
);
}
Buat komponen menjadi server component sebisa mungkin (default), dan tambahkan "use client" hanya di daun pohon yang benar-benar interaktif (tombol, form, dropdown). Ini menjaga bundle kecil dan data tetap di server.
API Routes & Server Actions
Route Handlers cocok saat Anda butuh endpoint HTTP nyata (dipanggil klien lain, webhook, mobile). Server Actions cocok untuk mutasi dari form/UI Anda sendiri — tanpa menulis endpoint manual.
// app/actions.ts
"use server";
import { db } from "@/lib/db";
import { revalidatePath } from "next/cache";
export async function tambahTugas(formData: FormData) {
const judul = String(formData.get("judul") ?? "").trim();
if (!judul) return { error: "Judul wajib diisi" };
await db.tugas.create({ data: { judul } });
revalidatePath("/dashboard");
}
Batasan Next.js Full-Stack
Monolit Next.js bukan palu untuk segala paku. Kenali batasnya sebelum menabraknya:
- Bukan untuk komputasi berat/berjalan-lama. Fungsi serverless punya batas waktu (biasanya puluhan detik). Pelatihan model, batch processing lama, atau job berat harus di layanan lain.
- Bukan Python. Untuk ML/data science sungguhan, tetap butuh layanan Python terpisah.
- WebSocket terbatas di serverless. Real-time berat sering butuh server persisten atau layanan khusus (mis. Supabase Realtime, Puser, Ably).
- Lock-in DX ke Vercel. Next optimal di Vercel; self-host bisa tapi butuh usaha lebih (mode standalone, kelola sendiri caching/ISR).
- Batas satu-deploy. Seluruh app naik/turun bersama; Anda tak bisa menskalakan hanya "bagian pencarian" secara mandiri.
Kesederhanaan adalah prasyarat keandalan.
Edsger W. Dijkstra
Mulai sebagai monolit Next.js. Saat sebuah kebutuhan menabrak batas di atas (mis. Anda mulai butuh model Python), ekstrak hanya bagian itu menjadi layanan terpisah, dan biarkan sisanya tetap monolit. Anda nyaris tak pernah perlu memecah semuanya sekaligus.
Poin Kunci Bab 4
- Next.js full-stack menyatukan FE+BE dalam satu bahasa/repo/deploy — jalur tercepat ke PoC web.
- App Router memakai struktur folder; RSC menjalankan komponen di server secara default,
"use client"untuk interaktivitas. - Server Actions untuk mutasi UI sendiri; Route Handlers untuk endpoint HTTP publik/eksternal.
- Batas: komputasi berat, Python/ML, WebSocket berat, penskalaan mandiri — saat menabraknya, ekstrak bagian itu saja.
Arsitektur: Monolith vs Microservices
Setelah memilih bahasa dan framework, keputusan struktural terbesar adalah: satu aplikasi (monolith) atau banyak layanan kecil (microservices)? Debat ini sering diwarnai hype. Kenyataannya sederhana: untuk PoC dan produk awal, monolith hampir selalu jawaban yang benar — tetapi monolith yang termodularisasi dengan baik, bukan bola lumpur besar.
Definisi
- Monolith — seluruh aplikasi adalah satu unit yang di-deploy bersama. Semua modul berbagi proses & basis kode yang sama.
- Microservices — aplikasi dipecah menjadi banyak layanan kecil independen, masing-masing dengan proses, deploy, dan sering database sendiri, berkomunikasi lewat jaringan.
- Modular Monolith — jalan tengah: satu deploy (seperti monolith) tetapi dengan batas modul internal yang tegas (seperti microservices), sehingga mudah dipahami dan bisa diekstrak nanti.
Trade-off
| Aspek | Monolith | Microservices |
|---|---|---|
| Kecepatan awal | Cepat — satu basis kode | Lambat — banyak setup |
| Deploy | Satu, sederhana | Banyak, butuh orkestrasi |
| Debugging | Mudah — satu proses, satu log | Sulit — tracing terdistribusi |
| Penskalaan | Seluruhnya sekaligus | Per layanan, mandiri |
| Kegagalan | Satu jatuh, semua jatuh | Terisolasi (jika benar) |
| Kompleksitas operasional | Rendah | Tinggi (jaringan, versi, data) |
| Cocok untuk tim | Kecil–menengah | Banyak tim independen |
Organisasi yang merancang sistem akan menghasilkan desain yang strukturnya meniru struktur komunikasi organisasi tersebut.
Melvin Conway (Hukum Conway)
Hukum Conway adalah alasan diam-diam di balik banyak keputusan arsitektur. Microservices masuk akal ketika Anda punya banyak tim yang perlu bekerja & men-deploy secara independen — struktur perangkat lunak mengikuti struktur tim. Tim solo yang membangun microservices berarti melawan Hukum Conway: menciptakan batas jaringan yang tidak dituntut oleh batas organisasi mana pun. Hasilnya semua ongkos terdistribusi tanpa satu pun manfaatnya.
Microservices memindahkan kompleksitas dari kode ke jaringan & operasi: latensi antar layanan, konsistensi data terdistribusi, versi API, tracing, service discovery. Untuk PoC, semua ini adalah pajak murni tanpa imbalan. Martin Fowler menyebut pendekatan yang bijak sebagai "MonolithFirst" — mulai monolith, pecah hanya saat rasa sakitnya nyata.
Contoh Struktur Modular Monolith
Rahasia monolith yang sehat adalah batas modul internal yang tegas. Susun kode berdasarkan domain bisnis (fitur), bukan berdasarkan lapisan teknis. Setiap modul memiliki API internalnya sendiri; modul lain memanggil lewat API itu, bukan menyentuh isi dalamnya.
src/
├─ modules/
│ ├─ auth/ # domain: otentikasi
│ │ ├─ service.ts # logika bisnis (API internal modul)
│ │ ├─ repository.ts # akses data
│ │ ├─ schema.ts # validasi (zod)
│ │ └─ index.ts # HANYA ini yang diekspor keluar
│ ├─ billing/ # domain: penagihan
│ │ ├─ service.ts
│ │ ├─ repository.ts
│ │ └─ index.ts
│ └─ tasks/ # domain: tugas
│ ├─ service.ts
│ ├─ repository.ts
│ └─ index.ts
├─ shared/ # util lintas domain (logger, db, errors)
│ ├─ db.ts
│ └─ logger.ts
└─ app/ # lapisan HTTP (routes memanggil service)
└─ api/...
Aturan emasnya: modul billing tidak boleh mengimpor tasks/repository.ts langsung — ia hanya boleh memanggil tasks/index.ts (API publik modul). Disiplin ini membuat setiap modul bisa "dicabut" menjadi microservice nanti dengan mengganti panggilan fungsi menjadi panggilan jaringan — tanpa menulis ulang logika bisnis.
Pecah sebuah modul menjadi layanan tersendiri hanya saat ada pemicu nyata: (1) modul itu butuh diskalakan sangat berbeda dari sisanya, (2) ditulis dalam bahasa berbeda (mis. layanan Python AI), (3) tim khusus perlu men-deploy independen, atau (4) kebutuhan isolasi kegagalan/keamanan yang tegas. Tanpa salah satu ini, tetap monolit.
Poin Kunci Bab 5
- Untuk PoC & produk awal, modular monolith hampir selalu pilihan benar — "MonolithFirst" (Fowler).
- Microservices memindahkan kompleksitas ke jaringan & operasi; hanya berbayar bila ada banyak tim/skala berbeda (Hukum Conway).
- Susun modul berdasarkan domain bisnis dengan batas tegas; ekspor hanya lewat
index.tstiap modul. - Disiplin batas modul memungkinkan ekstraksi ke service nanti tanpa menulis ulang logika.
Data & Database
Data adalah aset paling berharga sekaligus paling berumur panjang dalam sistem Anda. Framework bisa diganti; data harus bertahan lintas versi, migrasi, bahkan penulisan ulang aplikasi. Karena itu keputusan database layak dipikirkan lebih hati-hati daripada keputusan framework — meski, kabar baiknya, jawaban default untuk mayoritas kasus cukup jelas.
SQL vs NoSQL
Database SQL (relasional) seperti PostgreSQL dan MySQL menyimpan data dalam tabel dengan skema tetap dan relasi antar tabel. Mereka menjamin ACID (Atomicity, Consistency, Isolation, Durability) dan unggul untuk data terstruktur dengan relasi — yang menggambarkan hampir semua aplikasi bisnis.
Database NoSQL mencakup beberapa keluarga: dokumen (MongoDB, Firestore), key-value (Redis, DynamoDB), kolom-lebar (Cassandra), dan graf (Neo4j). Mereka menawarkan skema fleksibel dan penskalaan horizontal, dengan trade-off pada konsistensi dan relasi.
| Aspek | SQL (Postgres) | NoSQL (dokumen) |
|---|---|---|
| Skema | Tetap, tervalidasi | Fleksibel |
| Relasi | Kuat (JOIN) | Lemah / manual |
| Konsistensi | ACID kuat | Sering eventual |
| Query kompleks | Sangat kuat (SQL) | Terbatas |
| Skala tulis horizontal | Butuh usaha | Native |
| Cocok untuk | Aplikasi bisnis, transaksi | Data tak terstruktur, log, katalog besar |
Mulai dengan PostgreSQL. Ia relasional, mendukung JSON (jadi bisa "NoSQL saat perlu"), punya ekstensi kaya (pgvector untuk embedding AI, PostGIS untuk geospasial), dan portabel. Untuk 95% aplikasi, Postgres adalah pilihan yang tidak akan Anda sesali. Pilih NoSQL hanya untuk kebutuhan spesifik yang jelas.
PostgreSQL Serverless — Neon
Neon adalah Postgres serverless: memisahkan penyimpanan dari komputasi, bisa scale-to-zero (tidur saat tak dipakai, murah untuk PoC), dan punya fitur branching — membuat salinan database seperti branch git untuk setiap fitur/PR. Alternatif serupa: Supabase (Postgres + BaaS), PlanetScale (MySQL), Turso (SQLite terdistribusi). Untuk vibe coding, Neon + Vercel adalah kombinasi yang sangat lancar.
Caching — Redis / Upstash
Redis adalah penyimpanan key-value in-memory: sangat cepat, dipakai untuk caching hasil query mahal, session store, rate limiting, dan antrian ringan. Upstash menyediakan Redis serverless (bayar per request, cocok serverless/edge). Aturannya: jangan tambahkan cache sampai Anda punya masalah performa yang terukur. Cache menambah satu sumber kebenaran baru yang harus dijaga konsistensinya — kompleksitas yang hanya berbayar saat beban nyata.
Tunjukkan diagram alir dan sembunyikan tabelnya, saya akan tetap bingung. Tunjukkan tabelnya, dan saya biasanya tak perlu diagram alir; ia sudah jelas.
Fred Brooks, The Mythical Man-Month
Contoh Desain ERD
Entity-Relationship Diagram (ERD) memetakan entitas (tabel) dan relasi di antaranya. Berikut ERD ringkas untuk aplikasi SaaS multi-tenant sederhana: sebuah Organization punya banyak User, dan setiap User membuat banyak Task.
Migrasi dengan Prisma
Prisma adalah ORM TypeScript populer: Anda mendefinisikan skema deklaratif, dan Prisma menghasilkan klien type-safe serta mengelola migrasi (perubahan skema database yang terversi). Skema ERD di atas menjadi:
model Organization {
id String @id @default(cuid())
name String
plan String @default("free")
users User[]
createdAt DateTime @default(now())
}
model User {
id String @id @default(cuid())
email String @unique
passwordHash String
role String @default("member")
org Organization @relation(fields: [orgId], references: [id])
orgId String
tasks Task[]
@@index([orgId]) // indeks untuk query per-organisasi
}
model Task {
id String @id @default(cuid())
title String
done Boolean @default(false)
user User @relation(fields: [userId], references: [id])
userId String
@@index([userId])
}
# buat & terapkan migrasi baru (dev)
npx prisma migrate dev --name init
# terapkan migrasi di produksi (CI/CD)
npx prisma migrate deploy
Indexing
Indeks adalah struktur data yang mempercepat pencarian dengan mengorbankan sedikit ruang & kecepatan tulis. Tanpa indeks, database memindai seluruh tabel (full scan) untuk menemukan baris. Panduan praktis:
- Indeks kolom yang sering di-
WHERE,JOIN, atauORDER BY— terutama foreign key (sepertiorgId,userIddi atas). - Kolom
unique(mis. email) otomatis terindeks. - Jangan berlebihan — setiap indeks memperlambat INSERT/UPDATE dan memakan ruang.
- Ukur dulu dengan
EXPLAIN ANALYZEsebelum menambah indeks; tambahkan berdasarkan query nyata yang lambat, bukan tebakan.
Poin Kunci Bab 6
- Default ke PostgreSQL — relasional, mendukung JSON & ekstensi (pgvector), portabel, jarang disesali.
- Neon memberi Postgres serverless dengan scale-to-zero & branching; pas untuk vibe coding.
- Tambah cache (Redis/Upstash) hanya setelah ada masalah performa terukur.
- Rancang ERD lebih dulu; kelola skema & migrasi dengan Prisma; indeks foreign key & kolom yang sering difilter.
- Indeks berdasarkan query nyata yang lambat (EXPLAIN), bukan tebakan; jangan berlebihan.
Menghubungkan Frontend ↔ Backend
Setelah frontend dan backend ada, keduanya harus berbicara. Cara mereka berbicara — kontrak API, otentikasi, dan pengelolaan rahasia — menentukan seberapa aman dan seberapa nyaman sistem Anda berkembang. Bab ini membahas pilihan gaya komunikasi lalu tiga hal keamanan-koneksi yang wajib benar sejak awal.
Gaya Komunikasi API
REST
REST adalah gaya paling universal: sumber daya diakses lewat URL dan metode HTTP (GET, POST, PUT, DELETE). Kelebihan: dipahami semua orang & semua alat, mudah di-cache, tanpa dependensi khusus. Kekurangan: rentan over-fetching/under-fetching (dapat terlalu banyak atau terlalu sedikit data), dan kontrak tidak type-safe secara otomatis. Default yang aman untuk API publik atau lintas-bahasa.
tRPC
tRPC memberi pemanggilan fungsi backend dari frontend dengan type-safety end-to-end tanpa membuat kontrak terpisah — tipe TypeScript backend "mengalir" ke frontend. Kelebihan: DX luar biasa dalam monorepo TypeScript, autocomplete & error saat compile. Kekurangan: hanya untuk TypeScript di kedua sisi; tak cocok bila konsumen lintas-bahasa atau API publik. Pilihan hebat untuk monolit/monorepo TS.
GraphQL
GraphQL memberi klien kekuatan meminta persis data yang dibutuhkan dalam satu query, dari banyak sumber. Kelebihan: menghilangkan over/under-fetching, kuat untuk klien beragam (web, mobile) & graf data kompleks. Kekurangan: kompleksitas server tinggi (resolver, caching, N+1), berlebihan untuk PoC sederhana. Berharga saat banyak klien dengan kebutuhan data berbeda.
Server Actions
Dalam Next.js, Server Actions membuat batas FE↔BE nyaris hilang: Anda memanggil fungsi server langsung dari komponen, dan Next mengurus jaringannya. Untuk monolit Next, ini sering meniadakan kebutuhan menulis REST/tRPC sama sekali untuk kebutuhan internal. Cara termudah untuk PoC full-stack Next.
| Gaya | Type-safe | Lintas bahasa | Terbaik untuk |
|---|---|---|---|
| REST | Tidak (perlu OpenAPI) | Ya | API publik, universal |
| tRPC | Ya (otomatis) | Tidak (TS saja) | Monorepo TS internal |
| GraphQL | Ya (skema) | Ya | Banyak klien, graf data |
| Server Actions | Ya | Tidak (Next saja) | Monolit Next.js PoC |
Autentikasi: Session vs JWT
Otentikasi menjawab "siapa Anda"; ada dua pola dominan menyimpan status login:
- Session (stateful) — server menyimpan sesi (di DB/Redis) dan mengirim session ID ke klien lewat cookie. Kelebihan: mudah dicabut (hapus sesi = logout paksa), aman by default. Kekurangan: butuh penyimpanan sesi yang bisa diakses semua server.
- JWT (stateless) — server menerbitkan token bertanda-tangan berisi klaim (siapa, peran, kedaluwarsa). Server tak menyimpan apa pun; ia memverifikasi tanda tangan. Kelebihan: skala baik, cocok lintas layanan. Kekurangan: sulit dicabut sebelum kedaluwarsa (butuh blacklist/refresh token), dan salah simpan token = celah XSS.
Simpan token/sesi dalam cookie httpOnly, Secure, SameSite — bukan di localStorage. localStorage dapat dibaca JavaScript mana pun di halaman, sehingga token di sana rentan dicuri lewat XSS. Cookie httpOnly tak terjangkau JavaScript.
Untuk vibe coding, jangan gulung sendiri auth. Gunakan pustaka teruji: Auth.js (NextAuth), Lucia, Clerk, atau auth bawaan Supabase. Auth adalah area di mana "buat sendiri" hampir selalu keputusan buruk.
CORS
CORS (Cross-Origin Resource Sharing) hanya relevan bila frontend dan backend berada di domain berbeda — kasus arsitektur terpisah. Browser memblokir permintaan lintas-asal kecuali server tujuan mengizinkannya lewat header. Konfigurasikan daftar asal yang diizinkan secara eksplisit; jangan pakai wildcard * untuk endpoint yang butuh kredensial.
import cors from "cors";
app.use(cors({
origin: ["https://app.contoh.com"], // eksplisit, bukan "*"
credentials: true, // izinkan cookie
}));
Catatan: pada monolit Next.js, frontend & backend satu asal, sehingga CORS tidak menjadi masalah — satu lagi keuntungan diam-diam dari pendekatan monolit.
Environment Variables & Secrets
Rahasia (kunci API, kredensial database, secret JWT) tidak boleh masuk ke kode atau git. Simpan dalam environment variables.
DATABASE_URL="postgresql://user:pass@host/db"
JWT_SECRET="rahasia-panjang-acak"
ANTHROPIC_API_KEY="sk-..." # hanya di server
NEXT_PUBLIC_APP_URL="https://app.contoh.com" # aman ke klien
Di Next.js, hanya variabel berprefiks NEXT_PUBLIC_ yang dikirim ke browser. Jangan pernah memberi prefiks itu pada kunci rahasia — NEXT_PUBLIC_ANTHROPIC_API_KEY akan membocorkan kunci Anda ke setiap pengunjung. Tambahkan .env ke .gitignore; simpan nilai produksi di pengelola rahasia hosting (Vercel/AWS Secrets Manager).
Poin Kunci Bab 7
- REST untuk universal/publik; tRPC untuk monorepo TS; GraphQL untuk banyak klien; Server Actions untuk monolit Next.
- Session mudah dicabut; JWT skala baik tapi sulit dicabut. Simpan keduanya di cookie httpOnly, bukan localStorage.
- Jangan gulung auth sendiri — pakai Auth.js/Lucia/Clerk/Supabase.
- CORS hanya untuk arsitektur beda-domain; monolit satu-asal terhindar dari masalah CORS.
- Rahasia hidup di env vars, tak pernah di git; hati-hati prefiks
NEXT_PUBLIC_.
Keamanan Data
Keamanan bukan fitur yang ditambahkan belakangan; ia adalah properti yang dibangun sejak fondasi. Dalam vibe coding, godaannya besar: AI menuliskan kode yang "berfungsi", tetapi "berfungsi" dan "aman" adalah dua hal berbeda. Bab ini adalah daftar hal minimum yang harus benar sebelum data sungguhan — apalagi data orang lain — masuk ke sistem Anda.
Enkripsi: At-Rest & In-Transit
- In-transit (saat berpindah) — semua lalu lintas harus lewat TLS/HTTPS. Ini non-negotiable; sertifikat gratis via Let's Encrypt, dan platform seperti Vercel mengurusnya otomatis. Tanpa TLS, kredensial & data mengalir dalam teks polos yang bisa disadap.
- At-rest (saat tersimpan) — data di disk/database dienkripsi. Penyedia terkelola (Neon, RDS, Supabase) menyediakan enkripsi at-rest bawaan. Untuk kolom paling sensitif (mis. nomor identitas, token pihak ketiga), pertimbangkan enkripsi tingkat aplikasi/kolom agar terenkripsi bahkan dari sudut pandang DBA.
Hashing Password: argon2 & bcrypt
Password tidak pernah disimpan sebagai teks polos atau dienkripsi (yang bisa dibalik). Ia di-hash dengan fungsi lambat yang dirancang khusus: satu arah, ber-salt, dan mahal untuk di-brute-force.
- argon2id — pemenang Password Hashing Competition, rekomendasi modern. Tahan terhadap serangan GPU & side-channel. Pilihan utama untuk proyek baru.
- bcrypt — matang, teruji puluhan tahun, tersedia di mana-mana. Masih aman bila argon2 tak tersedia. (Catatan: bcrypt memotong input di 72 byte.)
Jangan gunakan MD5, SHA-1, atau SHA-256 polos untuk password — mereka cepat, dan "cepat" berarti mudah di-brute-force. Jangan pula membuat skema hashing sendiri.
import argon2 from "argon2";
// saat registrasi
const hash = await argon2.hash(password); // salt otomatis
// saat login
const ok = await argon2.verify(hash, password);
Masking Data & PII
PII (Personally Identifiable Information) — nama, email, telepon, alamat, nomor identitas — menuntut perlakuan khusus. Praktik inti:
- Minimisasi data — jangan kumpulkan yang tak Anda butuhkan. Data yang tak ada tak bisa bocor.
- Masking di tampilan — tampilkan
****1234, bukan nomor penuh, di UI & log. - Redaksi di log — jangan pernah menuliskan password, token, atau PII ke log. Ini kebocoran paling umum & paling mudah dihindari.
- Kepatuhan — sadari regulasi relevan (mis. UU PDP Indonesia, GDPR) tentang persetujuan, retensi, dan hak hapus.
Secrets Management
Rahasia hidup di environment variables atau pengelola rahasia khusus (Vercel Env, AWS Secrets Manager, Doppler, HashiCorp Vault) — tak pernah di kode atau git. Rotasikan kunci secara berkala, batasi cakupan (least privilege), dan gunakan kredensial berbeda antara dev & produksi. Jika sebuah rahasia pernah ter-commit, anggap ia bocor: cabut & ganti, jangan sekadar hapus dari histori.
OWASP Top 10 (Ringkas)
OWASP Top 10 adalah daftar risiko keamanan aplikasi web paling kritis. Ringkasannya sebagai checklist praktis:
| # | Risiko | Mitigasi ringkas |
|---|---|---|
| A01 | Broken Access Control | Cek otorisasi di server tiap request; jangan percaya klien |
| A02 | Cryptographic Failures | TLS di mana-mana; hash password (argon2); enkripsi data sensitif |
| A03 | Injection (SQL/XSS) | Query terparameter/ORM; escape output; validasi input |
| A04 | Insecure Design | Ancaman dipikirkan sejak desain; rate limit; batas bisnis |
| A05 | Security Misconfiguration | Nonaktifkan default berisiko; header keamanan; tak ada debug di prod |
| A06 | Vulnerable Components | npm audit; perbarui dependensi; Dependabot |
| A07 | Auth Failures | Pakai pustaka auth teruji; MFA; batasi percobaan login |
| A08 | Data Integrity Failures | Verifikasi sumber & tanda tangan; hati-hati deserialisasi |
| A09 | Logging Failures | Log peristiwa keamanan; pantau; jangan log rahasia |
| A10 | SSRF | Validasi & whitelist URL yang diambil server |
Jangan pernah menyusun query dengan penggabungan string. Gunakan query terparameter atau ORM (Prisma). SELECT * FROM users WHERE email = '" + input + "' adalah undangan SQL injection; WHERE email = $1 dengan parameter aman.
Rate Limiting
Rate limiting membatasi jumlah request per klien per rentang waktu — pertahanan terhadap brute-force login, penyalahgunaan API, dan sebagian serangan DoS. Terapkan terutama pada endpoint sensitif (login, reset password, pengiriman OTP, endpoint mahal/AI). Implementasi umum memakai penghitung di Redis (mis. Upstash Ratelimit).
import { Ratelimit } from "@upstash/ratelimit";
import { Redis } from "@upstash/redis";
const limiter = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(5, "60 s"), // 5 / menit
});
const { success } = await limiter.limit(ipPengguna);
if (!success) return Response.json({ error: "Terlalu banyak percobaan" }, { status: 429 });
Satu-satunya sistem yang benar-benar aman adalah yang dimatikan, dicabut, disegel dalam blok beton, dan dijaga penjaga bersenjata — dan bahkan itu pun saya ragukan.
Gene Spafford
Poin Kunci Bab 8
- TLS untuk semua lalu lintas (in-transit); andalkan enkripsi at-rest penyedia, enkripsi kolom untuk data paling sensitif.
- Hash password dengan argon2id (atau bcrypt); jangan pernah MD5/SHA polos atau menyimpan teks polos.
- Minimalkan & masking PII; jangan log rahasia/PII; patuhi regulasi (UU PDP/GDPR).
- Rahasia di secrets manager, dirotasi, least-privilege; anggap rahasia ter-commit sebagai bocor.
- Jadikan OWASP Top 10 checklist; cegah injection dengan query terparameter; rate limit endpoint sensitif.
UI / UX
Sebuah produk dinilai pengguna bukan dari elegansi arsitekturnya, melainkan dari pengalaman memakainya. UI (User Interface) adalah apa yang mereka lihat; UX (User Experience) adalah bagaimana rasanya. Dalam vibe coding, AI dapat menghasilkan antarmuka dengan cepat — tetapi tanpa prinsip, hasilnya cepat tampil dan cepat pula membingungkan. Bab ini memberi prinsip agar kecepatan itu tetap terarah.
Prinsip Desain
- Kejelasan > kepintaran. Pengguna tak mau memecahkan teka-teki. Label jujur, aksi jelas, jalur utama tak tersembunyi.
- Konsistensi. Elemen yang sama berperilaku sama di seluruh aplikasi. Konsistensi mengurangi beban belajar.
- Umpan balik. Setiap aksi mendapat respons: loading state, konfirmasi, pesan error yang membantu (bukan "terjadi kesalahan").
- Hierarki visual. Ukuran, warna, dan jarak mengarahkan mata ke yang paling penting lebih dulu.
- Cegah & maafkan error. Cegah lewat batasan input; maafkan lewat undo & konfirmasi untuk aksi destruktif.
- Hukum Fitts & Hick. Target penting dibuat besar & dekat; kurangi jumlah pilihan agar keputusan cepat.
Desain bukan sekadar bagaimana ia terlihat dan terasa. Desain adalah bagaimana ia bekerja.
Steve Jobs
Design System
Sebuah design system adalah kumpulan token, komponen, dan aturan yang membuat produk terasa satu kesatuan. Fondasinya adalah design tokens: variabel untuk warna, tipografi, jarak (spacing scale), radius, dan bayangan. Dengan token, mengganti tema atau menjaga konsistensi menjadi trivial.
:root {
/* warna */
--primary: #2563eb; --danger: #ef4444; --ok: #22c55e;
/* skala jarak (kelipatan 4px) */
--space-1: 4px; --space-2: 8px; --space-3: 16px; --space-4: 24px;
/* radius & tipografi */
--radius: 12px; --font: "Inter", sans-serif;
}
Untuk React, ekosistemnya matang: Tailwind CSS (utility-first, cepat untuk vibe coding), shadcn/ui (komponen yang Anda salin & miliki, bukan dependensi), Radix UI (primitif tanpa gaya tetapi aksesibel), dan Material UI untuk yang menginginkan sistem lengkap.
Aksesibilitas (a11y)
Aksesibilitas memastikan produk bisa dipakai semua orang, termasuk pengguna pembaca layar & navigasi keyboard. Ia bukan tambahan opsional — di banyak yurisdiksi ia kewajiban, dan selalu praktik baik. Dasar minimum:
- HTML semantik — pakai
<button>,<nav>,<main>, heading berjenjang. Ini juga membuat konten lebih terbaca oleh AI (lihat Bab 16). - Kontras warna cukup — rasio minimal 4.5:1 untuk teks normal (WCAG AA).
- Navigasi keyboard — semua interaktif dapat dijangkau & dioperasikan dengan Tab/Enter; fokus terlihat.
- Teks alternatif —
altpada gambar bermakna;aria-labeluntuk kontrol ikon. - Label form — setiap input punya
<label>terkait.
Responsivitas
Antarmuka harus bekerja dari layar ponsel hingga monitor lebar. Pendekatan mobile-first: rancang untuk layar kecil dulu, lalu tingkatkan untuk yang besar. Gunakan unit relatif (rem, %, fr), layout fleksibel (Flexbox/Grid), dan media query untuk titik pindah. Uji di perangkat nyata, bukan hanya penyusut jendela browser.
Komponen
Bangun UI dari komponen kecil yang dapat dikomposisi. Prinsipnya: komponen presentasional (hanya tampil, terima props) dipisah dari komponen kontainer (mengurus data & state). Komponen yang baik punya satu tanggung jawab, API props yang jelas, dan tidak bocor asumsi tentang tempat ia dipakai. Ini paralel langsung dengan disiplin batas modul di Bab 5 — pada level UI.
Kombinasi Tailwind + shadcn/ui adalah jalur tercepat menuju UI rapi & aksesibel dalam vibe coding: AI sangat fasih keduanya, komponennya sudah aksesibel, dan Anda memiliki kodenya (bukan terkunci dependensi). Mulai dari sana kecuali ada alasan lain.
Poin Kunci Bab 9
- UI = tampilan; UX = rasa memakainya. Prioritaskan kejelasan, konsistensi, umpan balik, hierarki.
- Design system dibangun dari token (warna, spacing, tipografi); Tailwind + shadcn/ui cepat & aksesibel.
- Aksesibilitas wajib: HTML semantik, kontras, navigasi keyboard, alt/label — juga membantu keterbacaan AI.
- Rancang mobile-first dengan unit relatif & Grid/Flex; komponen kecil, satu tanggung jawab, props jelas.
Tooling
Perkakas yang baik bekerja diam-diam di latar, mempercepat Anda tanpa menuntut perhatian. Perkakas yang buruk menjadi sumber gesekan harian. Dalam vibe coding di mana iterasi cepat adalah segalanya, memilih tooling yang lancar bukan detail sepele — ia mengalikan kecepatan Anda di setiap commit.
Package Manager: npm vs pnpm vs yarn vs bun
| Tool | Kecepatan | Efisiensi disk | Catatan |
|---|---|---|---|
| npm | Sedang | Rendah | Bawaan Node, universal, paling kompatibel |
| pnpm | Cepat | Tinggi (symlink store) | Hemat disk, ketat soal dependensi, hebat untuk monorepo |
| yarn | Cepat | Sedang | Matang; Yarn Berry (PnP) berbeda signifikan |
| bun | Sangat cepat | Tinggi | Sekaligus runtime & bundler; muda tapi menjanjikan |
Untuk proyek baru, pnpm adalah titik manis: cepat, hemat disk, dan penanganan dependensi yang ketat mencegah "phantom dependency". npm tetap pilihan aman bila ingin nol kejutan. bun menarik untuk eksperimen & kecepatan ekstrem. Yang penting: pilih satu & commit lockfile-nya agar build deterministik.
Monorepo & Turborepo
Monorepo adalah satu repositori yang memuat banyak paket/aplikasi (mis. web, api, ui bersama). Ini relevan justru saat Anda memilih arsitektur terpisah: frontend dan backend berbeda, tetapi berbagi tipe & util dalam satu repo — memberi sebagian kenyamanan monolit (satu tempat, tipe bersama) tanpa menyatukan deploy.
Turborepo (dan Nx) mempercepat monorepo dengan caching tugas: build/test yang tak berubah tidak diulang. Struktur khas:
apps/
├─ web/ # frontend Next.js
└─ api/ # backend (Nest/FastAPI wrapper)
packages/
├─ ui/ # komponen bersama
├─ types/ # tipe TS bersama (kontrak FE↔BE)
└─ config/ # eslint/tsconfig bersama
turbo.json # pipeline & cache
pnpm-workspace.yaml
Monorepo menjembatani debat "monolit vs terpisah": Anda bisa punya kode terbagi (repo tunggal, tipe bersama) namun deploy terpisah. Untuk tim kecil yang butuh layanan Python di samping UI, monorepo sering jalan tengah paling nyaman.
Linting & Formatting
ESLint menangkap masalah & pola berbahaya; Prettier menyeragamkan format (spasi, kutip, koma) agar tak ada lagi debat gaya. Pemain baru Biome menggabungkan keduanya dalam satu alat cepat. Pasangkan dengan TypeScript untuk keamanan tipe, dan Husky + lint-staged agar linting/format jalan otomatis di pre-commit.
CI/CD
CI (Continuous Integration) menjalankan lint, test, dan build otomatis pada setiap push/PR — menangkap kerusakan sebelum digabung. CD (Continuous Deployment/Delivery) melanjutkan ke deploy otomatis. GitHub Actions adalah standar de facto. Contoh alur minimal:
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with: { node-version: 20, cache: pnpm }
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm test
- run: pnpm build
Untuk deploy, platform seperti Vercel & Netlify menyediakan CD bawaan: setiap push ke main ter-deploy, setiap PR mendapat preview URL tersendiri — luar biasa untuk mereview perubahan sebelum merilis.
Poin Kunci Bab 10
- Pilih satu package manager (pnpm titik manis) & commit lockfile untuk build deterministik.
- Monorepo (Turborepo) memungkinkan kode terbagi + deploy terpisah — jalan tengah untuk tim kecil dengan layanan Python.
- ESLint + Prettier (atau Biome) + TypeScript + pre-commit hook menjaga kualitas otomatis.
- CI (lint/test/build tiap PR) + CD (deploy & preview otomatis) menangkap kerusakan sebelum rilis.
Deployment & Go Live
Kode yang berjalan di laptop Anda belum menjadi produk. Produk adalah sesuatu yang bisa diakses orang lain lewat alamat yang mereka ketik di browser. Bab ini menjembatani jurang itu: dari localhost:3000 menuju https://produkanda.com yang hidup, aman, dan bisa diakses siapa pun di dunia.
Peta Besar: Apa yang Membuat Website "Hidup"
Tiga hal harus bertemu agar sebuah website live:
- Hosting — komputer/server yang menjalankan aplikasi Anda 24/7.
- Domain — nama yang mudah diingat (mis.
produkanda.com) yang Anda sewa dari registrar. - DNS — sistem yang menerjemahkan nama domain menjadi alamat server (IP), sehingga browser tahu ke mana pergi.
Langkah demi Langkah: Membuat Website Live
- Beli domain. Dari registrar (Namecheap, Cloudflare Registrar, Niagahoster, GoDaddy). Cloudflare menjual "at-cost" tanpa markup. Biaya khas: ratusan ribu rupiah/tahun untuk
.com. - Siapkan repositori git. Push kode ke GitHub/GitLab — ini menjadi sumber deploy.
- Pilih hosting (lihat perbandingan di bawah). Untuk PoC Next.js, Vercel adalah jalur termulus.
- Hubungkan & deploy. Hosting menarik kode dari git, membangun, dan menyajikannya di URL sementara (mis.
proyek.vercel.app). - Arahkan domain via DNS. Di dashboard registrar/DNS, tambahkan record yang menunjuk domain Anda ke hosting: umumnya sebuah record
Ake IP, atauCNAMEke host (mis.cname.vercel-dns.com). - Aktifkan HTTPS. Platform modern menerbitkan sertifikat TLS otomatis (Let's Encrypt). Tunggu propagasi DNS (menit hingga jam).
- Set environment variables produksi di dashboard hosting (DATABASE_URL, kunci API, dll).
- Verifikasi. Buka domain, cek gembok HTTPS, uji alur utama, pantau log.
Jenis DNS Record yang Perlu Dikenal
| Record | Fungsi | Contoh |
|---|---|---|
A | Domain → alamat IPv4 | @ → 76.76.21.21 |
AAAA | Domain → alamat IPv6 | @ → 2606:... |
CNAME | Subdomain → nama lain | www → proyek.vercel.app |
MX | Server email | @ → mail server |
TXT | Verifikasi & SPF/DKIM | verifikasi domain |
Deploy ke Vercel (Langkah Konkret)
- Buat akun di Vercel, hubungkan akun GitHub.
- Klik Add New Project → pilih repositori Anda.
- Vercel mendeteksi Next.js otomatis — biarkan setelan default build.
- Isi Environment Variables (production).
- Klik Deploy. Dalam menit, aplikasi live di
*.vercel.app. - Settings → Domains → tambahkan domain kustom; Vercel memberi instruksi DNS persis.
- Selanjutnya, setiap
git pushkemainauto-deploy; tiap PR mendapat preview URL.
npm i -g vercel
vercel # preview deploy
vercel --prod # deploy ke produksi
VPS vs Serverless
| Aspek | Serverless (Vercel/Lambda) | VPS (DigitalOcean/Hetzner) |
|---|---|---|
| Setup | Nyaris nol | Konfigurasi server manual |
| Skala | Otomatis | Manual / vertikal |
| Biaya awal | Gratis–murah, bayar pemakaian | Tetap per bulan (mis. $5–$20) |
| Kendali | Terbatas | Penuh (root) |
| Proses panjang/WebSocket | Terbatas | Bebas |
| Cocok untuk | PoC, beban tak menentu | Kendali penuh, on-prem, beban stabil |
Untuk PoC, mulai serverless — nol ops, gratis untuk memulai. Pindah ke VPS/kontainer saat butuh kendali penuh, proses panjang, atau ingin menghindari lock-in. Untuk VPS, kemas aplikasi dalam Docker agar konsisten & portabel.
Gambaran AWS — Kapan Perlu
AWS adalah penyedia cloud terbesar dengan ratusan layanan. Anda tidak butuh AWS untuk PoC, tetapi berguna mengenali blok utamanya untuk saat skala & kendali menuntutnya:
- EC2 — server virtual (VPS versi AWS). Kendali penuh, Anda kelola OS.
- S3 — penyimpanan objek (file, gambar, backup, aset statis). Sangat murah & tahan lama.
- RDS — database relasional terkelola (Postgres/MySQL) dengan backup & failover.
- Lambda — serverless functions AWS.
- CloudFront — CDN; Route 53 — DNS; ECS/EKS — orkestrasi kontainer.
AWS kuat tetapi kompleksitas operasional & risiko tagihan mengejutkannya nyata. Untuk PoC, ia hampir selalu over-engineering. Pindah ke AWS saat Anda punya kebutuhan konkret (kepatuhan, skala, kendali infrastruktur), bukan karena "nanti mungkin butuh".
Poin Kunci Bab 11
- Website live butuh tiga hal: hosting (jalankan app), domain (nama), DNS (nama → IP).
- Alur go-live: beli domain → push git → hosting build → arahkan DNS (A/CNAME) → HTTPS otomatis → env produksi → verifikasi.
- Vercel = jalur termulus untuk Next.js: connect git, deploy, tambah domain, auto-deploy + preview.
- Serverless untuk PoC (nol ops); VPS/Docker untuk kendali penuh & proses panjang.
- AWS (EC2/S3/RDS/Lambda) hanya saat skala/kendali/kepatuhan menuntut — bukan titik mulai.
Membangun License Manager
Begitu Anda ingin menjual perangkat lunak — khususnya yang dipasang di infrastruktur pelanggan (on-premise) — Anda butuh cara memastikan hanya pelanggan berhak yang dapat memakainya, sesuai batas yang dibeli. Itulah tugas license manager. Bab ini membahas konsep, arsitektur, dan alur praktisnya, termasuk tantangan khas validasi tanpa internet.
Konsep Dasar Lisensi
- License key — string unik yang mewakili hak pakai. Idealnya ditandatangani secara kriptografis sehingga tak bisa dipalsukan tanpa kunci privat penerbit.
- Aktivasi — proses mengikat lisensi ke suatu instans/mesin/organisasi, biasanya sekali di awal.
- Validasi — pengecekan berulang bahwa lisensi masih sah & belum kedaluwarsa/dicabut.
- Entitlement — apa yang diizinkan lisensi: jumlah kursi, fitur (tier), tanggal kedaluwarsa, batas pemakaian.
Kunci Bertanda-tangan (Signed License Key)
Pendekatan paling kuat adalah public-key cryptography. Penerbit memegang kunci privat; ke dalam produk ditanam kunci publik. Lisensi berisi data (entitlement) + tanda tangan. Produk memverifikasi tanda tangan dengan kunci publik — jika valid, data lisensi dipercaya. Keindahannya: validasi bisa terjadi offline, karena tak butuh menghubungi server untuk membuktikan keaslian.
import { createVerify } from "crypto";
function verifikasiLisensi(payload: string, tandaTanganB64: string): boolean {
const v = createVerify("SHA256");
v.update(payload); // mis. JSON: {org, tier, exp, seats}
v.end();
return v.verify(KUNCI_PUBLIK, tandaTanganB64, "base64");
}
// entitlement dibaca HANYA jika tanda tangan valid
Validasi Online vs Offline
| Model | Cara kerja | Kelebihan | Kekurangan |
|---|---|---|---|
| Online | Produk memanggil server lisensi berkala (heartbeat) | Bisa dicabut seketika; pantau pemakaian real-time | Butuh internet; server harus selalu ada |
| Offline | Verifikasi tanda tangan lokal; kedaluwarsa dari data lisensi | Jalan tanpa internet (air-gapped) | Sulit dicabut sebelum kedaluwarsa |
| Hibrida | Offline + cek online berkala saat tersedia (grace period) | Fleksibel & tangguh | Lebih rumit diimplementasikan |
Pola hibrida paling umum untuk on-premise: lisensi diverifikasi offline (tanda tangan + tanggal kedaluwarsa), dengan cek online opsional saat internet tersedia untuk mencabut lisensi bermasalah dan menyegarkan masa berlaku. Diberi grace period (mis. 14 hari) agar gangguan jaringan tak langsung mematikan produk pelanggan.
Arsitektur License Manager
Contoh Alur
- Pembelian. Pelanggan membeli; server penerbit membuat record entitlement (org, tier, seats, exp).
- Penerbitan. Server menghasilkan payload lisensi + menandatanganinya dengan kunci privat → file/kunci lisensi diberikan ke pelanggan.
- Aktivasi. Pelanggan memasukkan kunci ke aplikasi on-prem; aplikasi memverifikasi tanda tangan dengan kunci publik tertanam & mengikatnya ke instans.
- Validasi berkala. Saat start & periodik, aplikasi memeriksa tanggal kedaluwarsa (offline) dan, bila online, menghubungi server untuk cek pencabutan & menyegarkan masa berlaku.
- Penegakan. Bila lisensi kedaluwarsa/dicabut melewati grace period, fitur berbayar dinonaktifkan dengan pesan jelas.
Lisensi untuk SaaS vs On-Premise
- SaaS — Anda mengendalikan server, sehingga "lisensi" pada dasarnya adalah status langganan di database Anda. Tak perlu kunci bertanda-tangan yang rumit; cukup cek langganan aktif tiap request. Pencabutan seketika & trivial.
- On-Premise — kode berjalan di infrastruktur pelanggan di luar kendali Anda. Di sinilah license manager sungguhan (kunci bertanda-tangan, aktivasi, validasi offline/hibrida) menjadi penting untuk melindungi hak & menegakkan batas.
Tidak ada skema lisensi yang 100% tak bisa ditembus di perangkat yang dikendalikan penyerang — tujuannya bukan kesempurnaan, melainkan menjadikan pelanggaran cukup sulit & tak sepadan bagi pelanggan bisnis yang jujur. Jangan berlebihan; DRM yang menyakitkan pengguna sah lebih merugikan daripada pembajakan yang dicegahnya.
Poin Kunci Bab 12
- License manager melindungi hak pakai & menegakkan entitlement (seats, tier, kedaluwarsa) — terutama untuk on-premise.
- Kunci bertanda-tangan (public-key) memungkinkan validasi offline: verifikasi tanda tangan dengan kunci publik tertanam.
- Model validasi: online (cabut seketika), offline (air-gapped), hibrida (offline + cek online berkala + grace period).
- SaaS: lisensi = status langganan di DB Anda. On-premise: butuh kunci bertanda-tangan & aktivasi.
- Tujuan realistis: cukup sulit dilanggar, bukan sempurna; jangan menghukum pengguna sah.
SaaS vs On-Premise
Cara perangkat lunak Anda sampai ke pengguna membentuk hampir setiap keputusan lain: arsitektur, keamanan, model bisnis, bahkan siklus rilis. Dua model besar mendominasi: SaaS (Anda menjalankan, pelanggan mengakses lewat internet) dan on-premise (pelanggan menjalankan di infrastrukturnya sendiri). Memahami perbedaannya menghindarkan Anda dari membangun untuk model yang salah.
Perbedaan Arsitektur
| Aspek | SaaS | On-Premise |
|---|---|---|
| Lokasi jalan | Server Anda (cloud) | Infrastruktur pelanggan |
| Kendali versi | Anda, satu versi untuk semua | Pelanggan, bisa beragam versi |
| Update | Anda deploy, instan | Dikirim & dipasang pelanggan |
| Data | Di sistem Anda | Tetap di pelanggan (isolasi penuh) |
| Kepemilikan uptime | Anda | Pelanggan |
| Lisensi | Status langganan di DB | Kunci bertanda-tangan (Bab 12) |
| Model harga | Langganan berulang | Lisensi + maintenance tahunan |
Multi-Tenancy (Inti SaaS)
Multi-tenancy berarti satu instans aplikasi melayani banyak pelanggan (tenant) sekaligus, dengan data mereka terpisah secara logis. Ini efisiensi inti SaaS. Tiga pola isolasi:
- Shared database, shared schema — semua tenant di tabel sama, dibedakan kolom
tenant_id. Paling murah & sederhana; menuntut disiplin ketat agar tak ada kebocoran antar-tenant (setiap query wajib difilter tenant). - Shared database, schema terpisah — tiap tenant punya schema sendiri dalam satu DB. Isolasi lebih baik, masih efisien.
- Database terpisah per tenant — isolasi terkuat, cocok pelanggan enterprise/regulasi ketat; biaya & kompleksitas operasi tertinggi.
Kebocoran data antar-tenant adalah mimpi buruk SaaS. Pada pola shared-schema, satu query yang lupa filter tenant_id bisa membocorkan data pelanggan A ke pelanggan B. Gunakan mekanisme yang menegakkan filter secara otomatis (mis. Row-Level Security PostgreSQL, atau lapisan repository yang selalu menyuntikkan tenant).
Update
Di SaaS, Anda men-deploy sekali dan semua pelanggan langsung memakai versi terbaru — mudah, tetapi menuntut kompatibilitas & migrasi yang mulus (tak boleh merusak siapa pun). Di on-premise, update harus dikemas, didistribusikan, dan dipasang pelanggan; Anda harus mendukung banyak versi sekaligus, menyediakan panduan migrasi, dan menangani lingkungan yang beragam. Kontainer (Docker) sangat membantu menstandarkan on-premise.
Data & Kepatuhan
On-premise menang telak saat pelanggan menuntut data tak boleh keluar dari infrastrukturnya — lazim di perbankan, kesehatan, pemerintah, atau lingkungan air-gapped. SaaS menang pada kenyamanan, pemeliharaan terpusat, dan biaya awal rendah. Banyak vendor akhirnya menawarkan keduanya: SaaS untuk mayoritas, on-premise untuk pelanggan enterprise yang membayar premium demi kendali.
Model Harga
- SaaS — langganan berulang (bulanan/tahunan), sering berjenjang (per seat, per fitur, per pemakaian). Pendapatan berulang & dapat diprediksi.
- On-Premise — biaya lisensi awal (sering besar) + biaya maintenance/support tahunan (mis. 20% dari lisensi). Pendapatan besar di depan, berulang lebih kecil.
Poin Kunci Bab 13
- SaaS: Anda jalankan, satu versi untuk semua, update instan, data di Anda, harga langganan.
- On-premise: pelanggan jalankan, banyak versi, update dikirim, data di pelanggan, lisensi + maintenance.
- Multi-tenancy adalah inti efisiensi SaaS; jaga isolasi tenant (RLS/repository) untuk cegah kebocoran data.
- On-premise unggul untuk kepatuhan/data-tak-boleh-keluar; kontainer menstandarkan distribusinya.
- Banyak vendor menawarkan keduanya: SaaS default, on-premise untuk enterprise premium.
Chrome Extension
Kadang produk terbaik bukan situs terpisah, melainkan sesuatu yang hidup di dalam browser pengguna — menambah kemampuan pada halaman yang sudah mereka pakai. Chrome Extension (juga bekerja di Edge & browser Chromium lain) memakai teknologi web yang sama persis dengan yang sudah Anda kuasai: HTML, CSS, JavaScript. Untuk vibe coding, ia jalur cepat dari ide ke alat nyata.
Kapan Memilih Extension
- Menambah fitur pada situs pihak ketiga (mis. tombol/anotasi di halaman yang sudah ada).
- Alat produktivitas yang selalu "sejangkauan" — pengubah teks, penyimpan tab, pengambil data.
- Otomasi & scraping di sisi klien untuk kebutuhan pribadi/internal.
- Integrasi cepat AI ke alur kerja browser (mis. meringkas halaman aktif).
Anatomi & Manifest V3
Sejak Manifest V3 (standar wajib kini), extension punya beberapa bagian utama. Pusatnya adalah manifest.json yang mendeklarasikan izin & komponen:
{
"manifest_version": 3,
"name": "Peringkas Halaman",
"version": "1.0.0",
"description": "Ringkas halaman aktif dengan AI",
"permissions": ["activeTab", "storage"],
"host_permissions": ["https://*/*"],
"action": { "default_popup": "popup.html" },
"background": { "service_worker": "background.js" },
"content_scripts": [
{ "matches": ["https://*/*"], "js": ["content.js"] }
]
}
Komponen & Perannya
- Content script — berjalan di dalam konteks halaman web yang dikunjungi. Bisa membaca & memodifikasi DOM halaman itu. Terisolasi dari JS halaman, tetapi berbagi DOM.
- Background (service worker) — otak yang berjalan di latar, menangani event, panggilan jaringan, dan koordinasi. Di MV3 ia event-driven & bisa mati saat idle (bukan lagi halaman persisten seperti MV2).
- Popup — UI kecil (HTML/CSS/JS) yang muncul saat ikon extension diklik.
- Options page — halaman pengaturan extension.
- Message passing — komponen berkomunikasi lewat
chrome.runtime.sendMessage/onMessage, karena mereka hidup di konteks berbeda.
// content.js — punya akses ke DOM halaman
const teks = document.body.innerText.slice(0, 5000);
chrome.runtime.sendMessage({ tipe: "ringkas", teks }, (balasan) => {
console.log("ringkasan:", balasan.hasil);
});
Kode extension dapat diinspeksi pengguna — sama seperti frontend, tak ada rahasia di sana. Untuk fitur AI, jangan menaruh kunci LLM di extension. Kirim permintaan ke backend Anda sendiri yang menyimpan kunci & menerapkan rate limit; extension hanya memanggil backend itu.
Batasan & Pertimbangan
- MV3 membatasi eksekusi kode jarak jauh & mempersingkat umur background — desain ulang jika bermigrasi dari MV2.
- Izin minimal. Minta hanya izin yang benar-benar dibutuhkan; izin berlebihan menakuti pengguna & memperlambat review.
- Lintas-browser. Firefox memakai API
browser.*yang mirip; sering perlu sedikit penyesuaian.
Cara Publish ke Chrome Web Store
- Daftar akun developer Chrome Web Store (biaya pendaftaran satu kali).
- Kemas extension: zip folder yang berisi
manifest.json& asetnya. - Unggah zip lewat Developer Dashboard.
- Lengkapi listing: deskripsi, ikon, tangkapan layar, kebijakan privasi (wajib bila mengakses data).
- Kirim untuk review — bisa memakan beberapa hari; izin sensitif memperlambatnya.
- Setelah disetujui, extension tayang; update dengan menaikkan
version& mengunggah ulang.
Poin Kunci Bab 14
- Extension memakai HTML/CSS/JS untuk menambah kemampuan di dalam browser; pas untuk alat "sejangkauan" & integrasi situs pihak ketiga.
- MV3:
manifest.jsonpusatnya; content script (DOM halaman), background service worker (otak), popup (UI), message passing antar-konteks. - Kode extension terinspeksi — tak ada rahasia; fitur AI harus lewat backend Anda yang menyimpan kunci.
- Publish via Chrome Web Store: kemas zip, isi listing + kebijakan privasi, lewati review, update dengan menaikkan versi.
Studi Kasus
Teori menjadi berguna saat diterapkan. Bab ini menjalankan lima skenario umum melalui kerangka faktor yang sama dengan Pemilih Tech Stack di awal buku — jenis proyek, skala, real-time, kebutuhan Python/AI, tempat deploy, ukuran tim — lalu menyimpulkan tumpukan dan, yang terpenting, alasannya. Bandingkan penalaran ini dengan hasil alat interaktif.
Studi Kasus 1 — Landing Page Startup
Konteks. Sebuah startup butuh situs marketing cepat muat, SEO kuat, dengan satu form "hubungi kami". Tak ada login, tak ada data pengguna berkelanjutan.
| Frontend | Astro (atau Next mode statis) + Tailwind |
| Backend | Tak perlu; form via serverless function / layanan form (Formspree) |
| Database | Tak perlu; konten via Markdown/CMS headless |
| Arsitektur | Situs statis (SSG) |
| Hosting | Vercel/Netlify (gratis) |
| Putusan | Cukup frontend saja |
Alasan. Prioritasnya kecepatan muat & SEO, bukan logika server. Menambah backend penuh di sini adalah kompleksitas tanpa manfaat. Astro "zero JS by default" memberi performa terbaik.
Studi Kasus 2 — SaaS Kecil (Manajemen Tugas Tim)
Konteks. Aplikasi web multi-tenant: organisasi, pengguna, tugas, langganan berbayar. Update ringan cukup lewat refetch, belum butuh WebSocket berat.
| Frontend | Next.js (App Router) + Tailwind + shadcn/ui |
| Backend | Next.js Server Actions + Route Handlers |
| Database | PostgreSQL (Neon) + Prisma; RLS untuk isolasi tenant |
| Arsitektur | Modular monolith (satu deploy) |
| Auth & bayar | Auth.js + Stripe |
| Putusan | Full-stack Next.js PoC |
Alasan. Kasus roti-mentega monolit Next.js. Satu bahasa, satu repo, satu deploy; tim kecil bergerak maksimal cepat. Pisahkan layanan hanya bila muncul kebutuhan konkret (mis. nanti butuh AI/Python).
Studi Kasus 3 — Internal Tool (Dashboard Operasi)
Konteks. Alat internal untuk tim operasi: tabel data, filter, aksi CRUD. SEO tak relevan; hanya dipakai karyawan yang login.
| Frontend | React + Vite (SPA) — atau bahkan admin low-code (Retool) |
| Backend | API ringan (Express/NestJS) atau Next API |
| Database | PostgreSQL terkelola + Prisma |
| Arsitektur | Monolith sederhana |
| Hosting | Internal / cloud dengan akses terbatas (VPN/SSO) |
| Putusan | Full-stack cukup; SEO tak dibutuhkan |
Alasan. Karena tak butuh SEO/SSR, SPA React + Vite sangat cepat dibangun. Untuk kebutuhan super standar, pertimbangkan alat low-code agar lebih cepat lagi — jangan bangun yang bisa dibeli.
Studi Kasus 4 — Aplikasi AI (Asisten Dokumen)
Konteks. Pengguna mengunggah dokumen, sistem membuat embedding, menyimpannya, lalu menjawab pertanyaan (RAG) dengan streaming jawaban. Melibatkan pemrosesan & model di Python.
| Frontend | Next.js (streaming UI) + Tailwind |
| Backend UI/BFF | Next.js — auth, orkestrasi, streaming ke klien |
| Layanan AI | Python FastAPI — embedding, pipeline RAG, panggil LLM |
| Database | PostgreSQL + pgvector (penyimpanan embedding) |
| Arsitektur | Dua layanan: UI/BFF (TS) + AI (Python) |
| Hosting | Vercel (UI) + Fly.io/Railway (FastAPI) |
| Putusan | Frontend + backend terpisah |
Alasan. Inilah pemicu klasik pemisahan: pekerjaan AI berat hidup di ekosistem Python. UI tetap Next.js yang ramping; otak berat di FastAPI. Jika kebutuhan hanya memanggil API LLM tanpa pipeline Python, ini bisa menyusut kembali menjadi monolit Next.
Studi Kasus 5 — On-Premise Enterprise
Konteks. Pelanggan perbankan menuntut perangkat lunak berjalan di infrastrukturnya; data tak boleh keluar; sering tanpa internet.
| Frontend | Next.js (mode standalone) atau SPA |
| Backend | NestJS/Go — dikemas kontainer |
| Database | PostgreSQL self-hosted (kontainer) |
| Arsitektur | Modular monolith dalam Docker Compose |
| Distribusi | Paket kontainer; license manager offline/hibrida (Bab 12) |
| Update | Rilis berversi + panduan migrasi |
| Putusan | On-premise; kemasan & lisensi jadi fokus |
Alasan. Kendala deployment (data tak boleh keluar, air-gapped) mendominasi. Fokus bergeser dari "framework mana" ke pengemasan, lisensi offline, dan kemudahan update di lingkungan yang tak Anda kendalikan. Kontainer & modular monolith menyederhanakan operasi di sisi pelanggan.
Perhatikan benang merahnya: default selalu ke yang paling sederhana (monolit/full-stack Next), dan pemisahan hanya dipicu oleh kebutuhan konkret — Python/AI berat, kendala deployment, atau skala & tim besar. Kompleksitas harus diperoleh, bukan diasumsikan.
Poin Kunci Bab 15
- Landing → frontend saja (Astro). SaaS kecil & internal tool → full-stack Next monolit.
- Aplikasi AI dengan Python berat → pisahkan layanan FastAPI dari UI Next.
- On-premise enterprise → fokus pindah ke pengemasan kontainer, lisensi offline, & strategi update.
- Benang merah: default sederhana; kompleksitas hanya ditambah saat dipicu kebutuhan nyata.
Cara Buku Ini Dibaca AI
Buku ini punya pembaca kedua: agent AI. Ketika sebuah agent membantu Anda memrogram, ia bekerja jauh lebih baik bila diberi konteks yang terstruktur ketimbang menebak dari ingatan. Bab ini menjelaskan bagaimana dokumen ini dirancang agar mudah "dicerna" agent — dan bagaimana agent sebaiknya memakainya.
Mengapa Struktur Itu Penting untuk AI
Model bahasa membaca teks linear, tetapi memahami struktur. Heading berjenjang, daftar, tabel, dan blok kode yang benar bukan sekadar estetika — mereka adalah sinyal yang membantu model membangun peta mental konten. Sebuah dokumen dengan <h2>/<h3> rapi dan ringkasan per bagian jauh lebih berguna sebagai konteks daripada dinding teks tanpa hierarki. Karena itu buku ini konsisten memakai HTML semantik.
Peta Konteks = Struktur Heading
Daftar isi buku ini adalah peta pengetahuannya. Sebuah agent dapat memindai heading untuk menemukan bagian relevan tanpa membaca keseluruhan, lalu menarik hanya bab yang dibutuhkan ke dalam konteksnya. Pola judul yang konsisten (Bab N — Topik, sub-h3 per konsep, blok "Poin Kunci" penutup) membuat ekstraksi ini andal.
Bila buku ini disajikan di aplikasi web, ia dapat diambil pada rute /buku/<slug> (slug: vibe-coding-stack). Agent dapat: (1) mengambil HTML, (2) memetakan konteks dari struktur <h2>/<h3>, (3) menarik blok "Poin Kunci" tiap bab sebagai ringkasan padat, lalu (4) mendalami bab tertentu sesuai kebutuhan tugas.
Cara Agent Sebaiknya Memakai Buku Ini
- Untuk keputusan stack — mulai dari kerangka faktor (Bab 1 & alat Pemilih): jenis proyek, skala, real-time, Python/AI, deploy, tim. Terapkan aturan yang sama, jelaskan trade-off, bukan hanya nama alat.
- Untuk pertanyaan spesifik — lompat ke bab terkait (mis. "REST vs tRPC" → Bab 7; "argon2 vs bcrypt" → Bab 8) dan kutip Poin Kunci-nya.
- Untuk brainstorming arsitektur — gunakan prinsip: default ke monolit sederhana (Bab 5), pisahkan hanya saat ada pemicu nyata; ingat Hukum Conway.
- Sebagai penjaga — ingatkan pengguna pada jebakan yang ditandai kotak amber (rahasia di frontend, injection, over-engineering, prefiks
NEXT_PUBLIC_).
Elemen yang Dioptimalkan untuk Keterbacaan AI
| Elemen | Fungsi untuk AI |
|---|---|
| Heading berjenjang (h2/h3) | Peta navigasi & batas konsep |
| Blok "Poin Kunci" tiap bab | Ringkasan padat siap-kutip |
| Tabel perbandingan | Data terstruktur untuk penalaran opsi |
| Blok kode berlabel bahasa | Contoh konkret yang dapat diadaptasi |
| Definisi eksplisit di awal konsep | Menghindari asumsi ambigu |
| Kotak peringatan (amber) | Sinyal anti-pola yang harus dicegah |
Program harus ditulis agar dibaca manusia, dan hanya kebetulan bisa dijalankan mesin.
Harold Abelson, SICP
Semangat kutipan Abelson meluas ke buku ini: ditulis agar dibaca manusia, dan — kebetulan yang disengaja — terstruktur agar dapat dicerna mesin. Keduanya menuntut kejelasan yang sama.
Poin Kunci Bab 16
- Struktur (heading, daftar, tabel, kode benar) adalah sinyal yang membantu AI membangun peta konteks.
- Daftar isi = peta pengetahuan; agent dapat menarik hanya bab relevan lewat struktur heading.
- Rute konseptual
/buku/vibe-coding-stack; blok "Poin Kunci" berfungsi sebagai ringkasan padat siap-kutip. - Agent sebaiknya menerapkan kerangka faktor yang sama, menjelaskan trade-off, dan menandai jebakan (kotak amber).
Penutup
Kita telah menempuh perjalanan dari pertanyaan sederhana — "dua sisi terpisah atau satu monolit Next.js?" — melalui framework, arsitektur, data, keamanan, deployment, hingga lisensi dan model distribusi. Jika ada satu pelajaran yang layak dibawa pulang, ia sederhana: mulai dari yang paling sederhana yang bisa bekerja, dan biarkan kompleksitas diperoleh, bukan diasumsikan.
Vibe coding memberi kekuatan luar biasa: Anda bisa membangun dalam jam apa yang dulu butuh minggu. Tetapi kekuatan itu netral. Ia memperbesar keputusan baik dan buruk. Peran Anda bukan menulis setiap baris — AI melakukannya — melainkan memegang kemudi arsitektur: memilih fondasi yang benar, menandai jebakan, dan tahu kapan menambah kompleksitas benar-benar berbayar. Buku ini adalah peta untuk peran itu.
Selera yang baik adalah tentang menghapus kompleksitas yang tidak perlu. Kode yang buruk melakukan hal yang sama dengan lebih banyak baris; kode yang baik membuat kasus khusus lenyap.
Linus Torvalds (parafrasa tentang "good taste")
Rekomendasi default buku ini, jika Anda hanya mengingat satu hal per topik: Next.js full-stack untuk PoC web, PostgreSQL untuk data, modular monolith untuk struktur, Vercel untuk go-live, argon2 + TLS + pustaka auth teruji untuk keamanan, dan pemisahan layanan hanya saat dipicu Python/AI berat, skala, atau tim besar. Menyimpang dari default ini sepenuhnya valid — asalkan Anda tahu mengapa.
Glosarium Teknis
| Istilah | Definisi |
|---|---|
| ACID | Jaminan transaksi database: Atomicity, Consistency, Isolation, Durability. |
| App Router | Sistem routing Next.js berbasis folder app/ dengan server components. |
| argon2 | Algoritma hashing password modern pemenang PHC; tahan serangan GPU. |
| BaaS | Backend-as-a-Service; DB, auth, storage siap pakai (Supabase, Firebase). |
| bcrypt | Algoritma hashing password matang & teruji; masih aman. |
| BFF | Backend-for-Frontend; lapisan server yang melayani kebutuhan UI spesifik. |
| CI/CD | Continuous Integration/Deployment; otomasi test, build, dan rilis. |
| CORS | Aturan browser untuk permintaan lintas-asal (beda domain). |
| CRUD | Create, Read, Update, Delete — operasi data dasar. |
| DNS | Domain Name System; menerjemahkan nama domain ke alamat IP. |
| ERD | Entity-Relationship Diagram; peta entitas & relasi database. |
| ESR / SSR / SSG | Rendering di server (SSR), pembangkitan statis (SSG) — strategi menyajikan HTML. |
| GraphQL | Bahasa query API; klien meminta persis data yang dibutuhkan. |
| Hukum Conway | Struktur sistem meniru struktur komunikasi organisasi pembuatnya. |
| Islands | Pola Astro: pulau interaktif JS di lautan HTML statis. |
| JWT | JSON Web Token; token bertanda-tangan untuk auth stateless. |
| Modular Monolith | Satu deploy dengan batas modul internal yang tegas. |
| Microservices | Aplikasi dipecah menjadi banyak layanan independen. |
| Multi-tenancy | Satu instans melayani banyak pelanggan dengan data terisolasi. |
| Manifest V3 | Standar terkini format & izin Chrome Extension. |
| ORM | Object-Relational Mapping; akses DB via objek (mis. Prisma). |
| OWASP Top 10 | Daftar sepuluh risiko keamanan aplikasi web paling kritis. |
| pgvector | Ekstensi PostgreSQL untuk menyimpan & mencari embedding (AI). |
| PII | Personally Identifiable Information; data pribadi teridentifikasi. |
| PoC | Proof of Concept; bukti konsep awal untuk memvalidasi ide. |
| RAG | Retrieval-Augmented Generation; LLM menjawab dari data yang diambil. |
| Rate limiting | Membatasi jumlah request per klien per waktu. |
| REST | Gaya API berbasis sumber daya & metode HTTP. |
| RLS | Row-Level Security; aturan akses per-baris di PostgreSQL. |
| RSC | React Server Components; komponen yang berjalan di server. |
| Serverless | Menjalankan fungsi tanpa mengelola server; skala & bayar per pemakaian. |
| Server Actions | Fungsi server Next.js yang dipanggil langsung dari komponen. |
| TLS | Transport Layer Security; enkripsi lalu lintas (HTTPS). |
| tRPC | API type-safe end-to-end untuk monorepo TypeScript. |
| Vibe coding | Membangun cepat berbantuan AI, mengarahkan maksud & menguji hasil. |
| VPS | Virtual Private Server; server virtual dengan kendali penuh. |
| WebSocket | Koneksi dua-arah persisten untuk real-time. |
Checklist Keputusan
Cetak atau salin daftar ini sebelum memulai proyek. Setiap "ya/tidak" mengarahkan Anda ke bab yang relevan.
Sebelum Menulis Kode
- ◻ Jenis proyek jelas (landing / PoC / SaaS / internal / AI)? → Bab 1, 15
- ◻ Butuh backend sama sekali? → Bab 3
- ◻ Ada kebutuhan Python/AI berat? Jika ya, rencanakan layanan terpisah. → Bab 3, 4
- ◻ Monolit Next.js cukup, atau perlu terpisah? → Bab 1, 4, 5
- ◻ Database dipilih (default: PostgreSQL) & ERD dirancang? → Bab 6
Saat Membangun
- ◻ Batas modul tegas (susun per domain, ekspor via index)? → Bab 5
- ◻ Gaya API dipilih (Server Actions / REST / tRPC / GraphQL)? → Bab 7
- ◻ Auth pakai pustaka teruji, token di cookie httpOnly? → Bab 7
- ◻ Password di-hash (argon2), TLS aktif, rahasia di env? → Bab 8
- ◻ Input tervalidasi, query terparameter (anti-injection)? → Bab 8
- ◻ UI aksesibel & responsif, design token konsisten? → Bab 9
- ◻ Lint/format/CI berjalan otomatis? → Bab 10
Sebelum & Sesudah Go Live
- ◻ Domain, DNS, HTTPS, env produksi siap? → Bab 11
- ◻ Rate limiting di endpoint sensitif? → Bab 8
- ◻ Model distribusi jelas (SaaS vs on-prem) & lisensi bila perlu? → Bab 12, 13
- ◻ Isolasi tenant diverifikasi (jika multi-tenant)? → Bab 13
- ◻ Rencana backup, pemantauan, & log (tanpa PII/rahasia)? → Bab 8, 11
FAQ
Kalau ragu, monolit atau microservices?
Monolit — hampir selalu, untuk PoC & produk awal. Microservices adalah solusi untuk masalah skala organisasi yang belum Anda miliki. Mulai monolit modular; pecah saat rasa sakitnya nyata (Bab 5).
Saya bikin "aplikasi AI" — wajib Python?
Tidak, jika Anda hanya memanggil API LLM (Claude, GPT) — cukup dari backend Node/Next Anda. Wajib Python bila Anda menjalankan/melatih model sendiri atau memakai pipeline ML/data science (Bab 3, 15).
Next.js full-stack, tapi nanti butuh scale — buntu?
Tidak. Karena Anda memelihara batas modul, Anda bisa mengekstrak bagian yang perlu diskalakan menjadi layanan tersendiri tanpa menulis ulang. Mulai monolit bukan jalan buntu; ia titik awal yang bijak (Bab 4, 5).
SQL atau NoSQL untuk proyek baru?
PostgreSQL (SQL) untuk 95% kasus. Ia mendukung JSON bila butuh fleksibilitas NoSQL, plus relasi & transaksi kuat. Pilih NoSQL hanya untuk kebutuhan spesifik yang jelas (Bab 6).
Aman menyimpan token di localStorage?
Tidak disarankan. localStorage terjangkau JavaScript apa pun di halaman (rentan XSS). Gunakan cookie httpOnly, Secure, SameSite (Bab 7, 8).
Perlu AWS dari awal?
Hampir tak pernah untuk PoC. Vercel + database terkelola jauh lebih cepat & sederhana. Pindah ke AWS saat ada kebutuhan konkret akan kendali/skala/kepatuhan (Bab 11).
Bagaimana melindungi produk on-premise dari pembajakan?
License manager dengan kunci bertanda-tangan & validasi offline/hibrida. Targetnya membuat pelanggaran cukup sulit bagi pelanggan bisnis jujur, bukan kesempurnaan yang mustahil (Bab 12).
Bangunlah. Kirimkan. Pelajari dari pengguna nyata. Arsitektur terbaik adalah yang membawa Anda ke tangan pengguna paling cepat dengan penyesalan paling sedikit — dan hampir selalu, itu lebih sederhana dari yang Anda kira. Selamat membangun.
