Akses kelas selamanya

Ambil Promo
flash sale
hamburger-menu

Tips All

Meningkatkan skills menjadi 1% lebih baik

Reset
Kelas Kesalahan Umum Saat Belajar React JS dan Cara Menghindarinya di BuildWithAngga

Kesalahan Umum Saat Belajar React JS dan Cara Menghindarinya

Bayangin kamu baru mulai belajar ngoding front-end. Setelah coba-coba HTML, CSS, dan JavaScript, kamu mulai kepo sama satu nama yang sering banget muncul di forum, video YouTube, sampai lowongan kerja: React JS. “Katanya sih, belajar React itu wajib kalau mau jadi front-end developer masa kini.” Dan emang bener, React bukan cuma populer—dia raja-nya library front-end yang dipakai banyak perusahaan besar kayak Facebook, Netflix, sampe Tokopedia. UI yang interaktif, cepat, dan modular—semua bisa dibuat dengan React. Gak heran kalau banyak pemula langsung lompat belajar React dengan semangat 45. Tapi di sinilah banyak orang mulai salah langkah. Karena semangatnya tinggi, kadang kita suka lewat jalur tikus—ngoding langsung tanpa ngerti konsep dasar. Akibatnya? Error gak jelas, komponen berantakan, dan akhirnya frustrasi sendiri. Nah, biar kamu gak ngalamin drama yang sama, di artikel ini kita bakal bahas kesalahan umum saat belajar React JS, lengkap dengan cara menghindarinya. Supaya proses belajarmu gak cuma cepat, tapi juga lebih seru dan gakk penuh stres. Siap? Yuk lanjut! 💻🔥 Kesalahan Umum Saat Belajar React JS (dan Cara Menghindarinya) Belajar React itu kayak naik roller coaster — seru, menegangkan, tapi kadang bikin mual juga kalau nggak siap. Banyak orang, termasuk saya dulu, datang ke React dengan ekspektasi tinggi: “Dengan React, gue bisa bikin aplikasi kece kayak Instagram!” Tapi kenyataannya? Baru nulis <div>Hello World</div> aja, udah bingung: Ini kenapa JSX mirip HTML tapi gak sepenuhnya HTML?Kenapa error cuma karena lupa return?Kenapa useEffect jalan terus-terusan kayak setan? Jangan khawatir. Semua yang belajar React pasti pernah ngerasain masa-masa frustrasi itu. Dan kebanyakan penyebabnya bukan karena kamu bodoh atau gak bakat ngoding — tapi karena ada pola kesalahan umum yang sering banget diulang para pemula. Makanya, di bagian ini, kita bakal bahas satu per satu kesalahan yang sering dilakukan saat belajar React JS — bukan buat nyalahin, tapi biar kamu bisa belajar dari kesalahan orang lain, dan gak harus jatuh di lubang yang sama. Setiap poin juga bakal dilengkapi dengan cara menghindarinya, jadi kamu bisa belajar React dengan lebih tenang dan percaya diri. Siap? Yuk kita mulai dari akar masalah paling sering: kurang kuat di dasar JavaScript. 1. Mengabaikan Dasar-Dasar JavaScript Mengabaikan Dasar-Dasar JavaScript Image by Freepik Ceritanya gini… Kamu baru kenal React, terus liat tutorial di YouTube. Judulnya catchy: “Bikin Aplikasi Todo List dengan React dalam 15 Menit!”. Kamu langsung klik, buka VSCode, dan mulai ngikutin step by step. Lalu di tengah jalan, muncul baris kayak gini: const { title, description } = props; Dan kamu mikir: “Eh… ini kenapa ada kurung kurawal di dalam const? Ini maksudnya apaan sih?” Lanjut lagi… const handleClick = () => { console.log("Clicked!"); }; Kamu mulai bingung lagi. “Kok function-nya gak pake function? Trus kenapa ada => kayak gitu?” Dan gak lama kemudian kamu menemukan ..., map, filter, dan hal-hal aneh lainnya yng belum pernah kamu lihat sebelumnya waktu belajar JavaScript dasar. 😬 Di sinilah banyak orang kepleset Banyak yang ngira: “React itu library, jadi gak perlu jago JavaScript buat mulai.” Padahal kenyataannya, React itu cuma cara lain untuk menulis JavaScript. Kalau dasarnya belum kuat, kamu bakal kebingungan terus tiap lihat syntax yang “kelihatannya React banget”, padahal itu murni fitur JavaScript modern—alias ES6 dan teman-temannya. Contohnya: Destructuring: bikin kode lebih singkat dan rapi.Arrow function: berguna banget di event handler.Spread & rest operator: wajib saat update state atau merge props.Array methods kayak map, filter, reduce: sering banget dipake buat render list. Kalau kamu belum paham fitur-fitur itu, belajar React bisa terasa kayak masuk hutan tanpa kompas. Setiap error yang muncul bakal bikin kamu panik, padahal cuma karena kamu belum kenal syntax-nya aja. ✅ Cara Menghindarinya Jangan buru-buru masuk ke React. Serius. Luangkan waktu buat benar-benar ngerti JavaScript dulu. Enggak harus jadi master, tapi pastikan kamu paham: Cara kerja function dan scopeBedanya var, let, constCara pakai arrow functionGimana destructuring itu bisa menyederhanakan kodeGunanya spread (...) dan rest (...)Perbedaan antara array vs objectCara kerja callback dan promisePaling penting: array methods kayak map(), filter(), find() Kamu bisa cari playlist “Modern JavaScript” atau “JavaScript ES6+” di BuildWithAngga, atau buka javascript.info buat belajar dari dokumentasi yang jelas dan step-by-step. 🧩 Ingat… React itu ibarat alat tukang. Tapi JavaScript? Itu fondasi rumahnya. Kalau fondasinya rapuh, secanggih apapun alatnya, rumahmu tetap gampang roboh. Jadi, jangan skip dasar. Pelan-pelan aja. Yang penting paham. 💪 📘 Mini Roadmap JavaScript ES6+ untuk Belajar React Belajar JavaScript modern itu bukan soal hapalan, tapi soal paham kenapa dan kapan dipakai — apalagi kalau tujuannya buat React. 🪴 1. Variabel dan Scope Kenapa penting? React sangt bergantung pada variabel yang predictable. 📌 Pelajari: var, let, const → kapan pakai let vs constBlock scope vs function scopeHoisting (biar paham kenapa kadang error undefined) 🧱 2. Arrow Function (=>) Kenapa penting? Arrow function sering dipakai buat event handler dan callback di React. 📌 Pelajari: Sintaks dasar arrow functionPerbedaan this di arrow function vs function biasaReturn implisit vs eksplisit 🧩 3. Destructuring Kenapa penting? Sering banget dipakai buat ambil props, state, dan array dalam React. 📌 Pelajari: Destructuring object: const { name, age } = user;Destructuring array: const [count, setCount] = useState(0); 📦 4. Spread dan Rest Operator (...) Kenapa penting? Wajib untuk update state tanpa mutate langsung (immutable). 📌 Pelajari: Spread object/array: const newArray = [...oldArray]; const newObj = { ...oldObj, name: "Updated" };Rest parameter: const sum = (...args) => args.reduce((a, b) => a + b); 🔁 5. Array Methods Kenapa penting? React serign render list pakai map(), dan manipulasi array lainnya. 📌 Fokus ke: map() → buat list komponenfilter() → menyaring datafind() → mencari item spesifikforEach() → iterasi non-returnsome() dan every() → kondisi data 📜 6. Template Literals Kenapa penting? Buat menyusun string lebih rapi, terutama di JSX atau className dinamis. 📌 Pelajari: const greeting = `Hello, ${name}!`; 🔒 7. Object & Array Manipulation Kenapa penting? State management di React sering melibattkan update object/array. 📌 Pelajari: Menyalin array/object tanpa mutasiMenambah, menghapus, dan mengubah isi array/objectObject.keys(), Object.values(), Object.entries() 🧠 8. Function & Callback Kenapa penting? React heavily depends on passing function as props (event handlers). 📌 Pelajari: Function declaration vs expression vs arrow functionCallback & higher-order functionClosures (optional tapi bagus dipahami) ⏳ 9. Promise dan Async/Await Kenapa penting? Berguna saat ambil data dari API (misal di useEffect atau fetch). 📌 Pelajari: Cara kerja promise dan chaining (.then, .catch)Penulisan async & awaitError handling ✨ Bonus: Optional Chaining & Nullish Coalescing Kenapa pentig? Menghindari error saat akses properti nested yang belum tentu ada. 📌 Pelajari: const name = user?.profile?.name ?? "Guest"; 📌 Tips Belajar Jangan buru-buru! Kuasai per topik dulu, baru lanjut.Bikin mini project kecil per topik, misalnya:Buat function filterData() sendiriRender list pakai map() di HTML biasaUbah object dengan spread dan log hasilnyaGunakan playground seperti CodeSandbox atau JSFiddle untuk latihan ringan. 2. Terlalu Fokus pada Framework, Lupa Konsep Terlalu Fokus pada Framework, Lupa Konsep Image by Freepik Waktu pertama kali belajar React, rasanya pegen langsung "gaspol". Begitu tahu ada useEffect, langsung dipakai. Begitu tahu ada useState, langsung klik-klik tutorial dan copas. Pokoknya asal jalan. Tapi kemudian mulai muncul tanda-tanda: Komponen ngerender berkali-kali dan gak tahu kenapa.Data dari API munculnya telat, terus error.State berubah tapi UI gak update.Atau lebih parah: infinite loop dari useEffect. Dan pas ditanya, “Kenapa kamu pakai useEffect di situ?” Jawabannya: “Soalnya di tutorial begitu, kak 😅.” 🤯 Kenapa Ini Bisa Terjadi? Banyak pemula dan saya dulu juga gitu terlalu fokus ke fitur React, tapi lupa konsep dasarnya. Maksudnya gini: kamu tau useEffect, tapi gak ngerti bahwa itu sebenarnya mirip dengan componentDidMount, componentDidUpdate, atau componentWillUnmount di React versi class component (alias: lifecycle method). Kamu tau useState, tapi gak ngerti bahwa setiap kali setState() dipanggil, React akan re-render komponen. Kamu tau bikin komponen, tapi gak ngerti bedanya controlled vs uncontrolled component. Jadi, karena gak paham “dalemannya”, akhirnya React jadi kayak kotak hitam — cuma bisa dipakai kalau niru. Tapi pas error muncul, bingung sendiri. 🧠 Gimana Cara Menghindari Ini? Belajar Konsep, Bukan Cuma Sintaks Sebelum pakai useEffect, cari tahu dulu: Apa fungsinya? Kapan dia dijalankan? Apa yang terjadi kalau depedency array-nya kosong? Kapan dia bakal dipanggil ulang? Contoh kecil: useEffect(() => { console.log("Komponen mount"); return () => { console.log("Komponen unmount"); }; }, []); Kalau gak ngerti konsep mounting dan unmounting, kode di atas bakal keliatan magis. Jangan Skip Pengetahuan Class Component Meskipun sekarang React pakai functional component + hooks, konsep dasarnya tetap berasal dari class component. Coba baca sekilas soal: componentDidMountcomponentDidUpdatecomponentWillUnmount Setelah itu, kamu bakal ngerti bahwa useEffect adalah cara functional component untuk menjalankan kode lifecycle tadi. Visualisasikan Proses Render React React itu kayak puzzle yang jalan dari atas ke bawah: Komponen direnderState atau props berubah → re-renderEffect dijalankan sesuai dependency Dengan visualisasi ini, kamu akan lebih hati-hati: Kenapa ini rerender terus?Kenapa efek ini jalan terus padahal aku gak mau? Tanya Diri Sendiri: “Kenapa aku pakai hook ini?” Setiap kali kamu nulis useEffect, useState, useRef, dll, coba stop sejenak dan tanya: "Apa yang ingin aku capai?Dan kenapa harus pakai hook ini?" Kalau kamu belum bisa jawab dengan yakin, mungkin kamu belum butuh hook itu. Atau kamu perlu eksplorasi konsepnya dulu. 🎯 Intinya? React itu bukan sekadar kumpulan hook dan component. Dia punya mekanisme internal yang keren banget. Tapi supaya kamu bisa maksimalkan kekuatannya, kamu harus paham "kenapa", bukan cuma "bagaimana". Framework boleh keren, tapi konsep lebih penting daripada fitur. Kalau konsepnya udah kuat, kamu gak cuma jadi pengguna React — kamu jadi developer yang ngerti React. 3. Tidak Memahami State dan Props dengan Benar Tidak Memahami State dan Props dengan Benar Image by Freepik Waktu awal belajar React, kita sering dengar istilah "state" dan "props". Awalnya kelihatan mirip, dan tutorial pun sering pakai keduanya tampa terlalu banyak penjelasan. Sampai akhirnya terjadi hal seperti ini: 😅 "Kak, kenapa aku gak bisa ganti nilai props ini ya?"😓 "Kenapa pas aku ubah state, datanya malah hilang semua?"🤯 "Kok data anaknya gak sinkron sama induknya?" Yup, itu semua adalah gejala dari belum paham benar perbedaan state dan props. 🧠 Bedanya State dan Props Biar gampang, coba bayangin komponen React kayak sebuah mesin kecil. State = memori internal mesin. Bisa berubah seiring waktu. ➤ Kita ubah pakai setState() atau useState().Props = seperti input dari luar. ➤ Gak bisa diubah dari dalam, cuma bisa diterima. Contoh analoginya: Kamu bikin komponen <KartuNama nama="Taufan" />Maka nama itu props — kamu kirim dari luar.Tapi misalnya komponen KartuNama punya fitur toggle untuk tampilkan/semmbunyikan detail, maka isVisible adalah state — karena disimpan dan diubah dari dalam. 💣 Kesalahan Umum yang Sering Terjadi Mencoba Mengubah Props Langsung function Komponen(props) { props.nama = "Ubah Nama"; // ❌ error! } Props itu readonly alias hanya bisa dibaca, gak boleh diubah dari dalam komponen. Kalau kamu ingin ubah data yang dikirim lewat props, kamu harus minta parent component-nya yang ubah. Semua Disimpan di State, Padahal Gak Perlu Kadang ada yang overthinking dan menyimpan data tetap ke dalam useState, padahal gak akan berubah. const [judul, setJudul] = useState("Artikel React"); // ❌ gak perlu state Kalau nilainya gak pernah berubah, cukup pakai variable biasa. Tidak Menyadari Alur Data Mengalir dari Atas ke Bawah (Top → Down) Data dari parent component mengalir ke child lewat props. Tapi kadang pemula berharap bisa "naik" atau ubah data dari bawah ke atas tanpa mekanisme khusus. Contoh: // Parent <Post judul="Belajar React" /> // Child function Post(props) { props.judul = "Judul Baru"; // ❌ Props gak boleh diubah } Solusinya? Harus pakai callback function via props untuk "naik" ke parent. ✅ Cara Menghindarinya Pahami Alur Data React React bekerja secara unidirectional data flow: Dari atas (parent) → ke bawah (child) Belajarlah untuk mengendalikan alur data lewat props dan mengubah data melalui state atau event handler di parent. Latihan Bikin Komponen Sederhana Coba bikin komponen seperti ini: Counter: dengan tombol + dan -Toggle text: klik tombol untuk tampilkan/sembunyikan teksForm input: dan tampilkan data yang diketik Lewat latihan kecil ini, kamu akan terbiasa: Kapan harus pakai stateKapan harus kirim data lewat propsBagaimana cara komunikasi antara parent dan child Jangan Asal useState, Tanya Dulu: “Apakah data ini perlu diubah di dalam komponen?”Jika iya → pakai stateJika tidak → cukup lewat props atau variable biasa ✨ Kesimpulan State dan props itu ibarat jantung dan pembuluh darahnya React. Kalau gak paham cara kerjanya, aplikasi kamu bisa bingung alur datanya, sulit di-debug, atau malah gak jalan seperti yang diharapkan. Dengan latihan dan pemahaman konsep, kamu akan mulai "merasakan" alur data React dan tahu harus ngapain ketika butuh simpan atau kirim data antar komponen. 4. Menulis Komponen Tanpa Struktur atau Konsistensi Menulis Komponen Tanpa Struktur atau Konsistensi Image by Freepik Waktu pertama kali belajar React, kita biasanya semangat banget. Langsung bikin komponen besar… semua logic, tampilan, dan styling disatuin. Hasilnya? 🎩 Komponen 500 baris, isinya campur aduk.🤯 Susah dipahami.🛠️ Mau edit dikit, takut rusak semua. Kalau kamu pernah bikin komponen <Dashboard> yang isinya: sidebar, navbar, konten utama, tabel, dan modal dalam satu file... berarti kamu pernah melewati fase ini 😅 🧱 Masalah Umum: Komponen Gede dan Acak-Acakan Beberapa masalah yang sering terjadi: Semua komponen ditaruh di folder components/ tanpa aturan.Komponen kecil dan besar campur di satu file.Tidak ada pemisahan antara tampilan, logika, dan utilitas.Tidak konsisten dalam penamaan dan struktur. Hasilnya? Saat proyek makin besar, kita jadi bingung sendiri: “Tombol ini ada di mana ya? Kok form-nya rusak pas diganti?” 🧩 Contoh: Komponen Tanpa Struktur // Dashboard.js function Dashboard() { const [users, setUsers] = useState([]); const [isOpen, setIsOpen] = useState(false); useEffect(() => { fetchUsers(); }, []); return ( <div> <h1>Dashboard</h1> <button onClick={() => setIsOpen(true)}>Add User</button> {isOpen && ( <div className="modal"> <form>...</form> </div> )} <table>...</table> </div> ); } Kelihatannya masih oke… tapi bayangin kalau file ini tumbuh jadi 700 baris. 😵 ✅ Cara Menghindari: Terapkan Struktur yang Jelas Kamu bisa mulai dari struktur sederhana tapi rapi, misalnya pakai pendekatan Atomic Design atau minimal punya pemisahan seperti: components/ ├── atoms/ │ └── Button.jsx ├── molecules/ │ └── FormGroup.jsx ├── organisms/ │ └── UserForm.jsx ├── templates/ │ └── DashboardLayout.jsx pages/ └── dashboard.jsx Atomic Design membagi komponen berdasarkan level kompleksitas: Atoms = komponen paling kecil, seperti <Button>, <Input>Molecules = gabungan beberapa atom, seperti <FormGroup>Organisms = bagian kompleks, seperti <UserForm>Templates = layout halamanPages = file halaman utama 💡 Alternatif: Struktur Folder Berdasarkan Fitur Kalau proyek kamu sudah cukup besar dan fokus pada fitur, kamu bisa pakai pendekatan feature-based folder: features/ └── users/ ├── components/ │ └── UserTable.jsx ├── hooks/ │ └── useUsers.js ├── api.js └── index.jsx Pendekatan ini memudahkan kamu mengelola logika dan UI per fitur — cocok banget buat tim yang kerja bareng. 🧰 Tips Tambahan untuk Konsistensi Gunakan konvensi penamaan yang sama (misal: PascalCase untuk komponen, camelCase untuk function)Pisahkan styling (CSS, Tailwind, atau CSS-in-JS) agar tidak campur aduk dengan logicPisahkan helper function ke folder utils/ atau lib/Bikin komponen reusable kalau muncul lebih dari 1x ✨ Kesimpulan React memang fleksibel, tapi tanpa struktur dan konsistensi, proyek bisa jadi monster yang sulit dikendalikan. Dengan menerapkan struktur folder yang rapi, membagi komponen berdasarkan tanggung jawabnya, dan menjaga konsistensi penulisan, kamu akan lebih mudah scaling, debugging, bahkan berkolaborasi bareng tim. Ingat: “Code is read more than it is written.” Jadi bikinlah struktur yang bikin kamu (dan orang lain) betah baca dan ngoprek. 5. Salah Menggunakan useEffect Salah Menggunakan useEffect Image by Freepik Di antara semua hook yang disediakan React, mungkin useEffect adalah yang paling banyak bikin kepala pusing — terutama saat masih awal belajar. Masalahnya bukan karena useEffect itu susah, tapi karena kita belum benar-benar memahami kapan dan bagaimana dia bekerja. 🌀 Contoh Kesalahan Umum: Infinite Loop Tanpa Sadar Coba kamu lihat kode ini: import { useState, useEffect } from "react"; function Example() { const [count, setCount] = useState(0); useEffect(() => { setCount(count + 1); }, [count]); return <p>Count: {count}</p>; } Kelihatannya simpel ya? Tapi pas dijalankan... 🚨 “Why is my app crashing?”💥 Karena ini bikin infinite loop! Kenapa? Efek jalan setiap kali count berubah.Di dalam efek, kamu memanggil setCount(), yang bikin count berubah lagi.Karena count berubah → useEffect jalan lagi.Balik lagi ke step 2. 🎢 Selamat datang di loop tak berujung. 🧠 Penyebab Umum Kesalahan dengan useEffect Dependency array tidak sesuaiTerlalu banyak atau terlalu sedikit dependensi bisa bikin efek jalan terus-menerus atau malah nggak jalan sama sekali.Memasukkan fungsi yang berubah-ubah (non-stable) ke dependencyMisalnya, bikin fungsi inline di dalam komponen, lalu masukin ke dependency. Ini bisa bikin useEffect jalan terus setiap render.Mengupdate state dari dalam efek tanpa kondisi yang jelasKalau kamu ngubah state di dalam efek, pastikan itu tidak memicu efek yang sama berulang kali. 🛠️ Cara Menghindari Kesalahan di useEffect ✅ Pahami Kapan useEffect Dipanggil Tanpa dependency array → dijalankan setiap render.Dependency array kosong [] → dijalankan sekali saat mount.Dengan [someVar] → dijalankan saat someVar berubah. ✅ Gunakan console.log untuk debug Contoh: useEffect(() => { console.log("Effect jalan karena count berubah:", count); }, [count]); Ini bisa bantu kamu lihat kapan dan kenapa efek dijalankan. ✅ Jangan Update State Secara Langsung Tanpa Kondisi Kalau butuh update state dalam useEffect, pastikan kamu memberi kondisi eksplisit: useEffect(() => { if (count < 5) { setCount(count + 1); } }, [count]); Ini mencegah efek jalan terus. ✅ Simpan fungsi di luar useEffect kalau tidak perlu berubah-ubah Contoh salah: useEffect(() => { const doSomething = () => console.log("doing..."); doSomething(); }, [doSomething]); // padahal setiap render, fungsi berubah Solusi: Pindahkan doSomething ke luar useEffect atau gunakan useCallback. 🧪 Studi Kasus: Fetch Data useEffect(() => { const fetchData = async () => { const res = await fetch("/api/data"); const data = await res.json(); setData(data); }; fetchData(); }, []); ✅ Ini contoh yang benar: efek hanya jalan sekali saat komponen mount, dan setData() tidak memicu efek baru karena dependensinya kosong. ✅ Solusi: Pahami Kapan dan Bagaimana useEffect Digunakan dengan Benar Oke, jadi gimana sih caranya biar nggak “terjebak nostalgia” alias infinite loop terus saat pakai useEffect? Jawabannya sederhana: pahami kapan dan bagaimana useEffect itu dijalankan. useEffect adalah semacam "asisten pribadi" yang siap ngerjain sesuatu buatmu setiap kali terjadi perubahan tertentu di komponen. Tapi kamu harus ngasih tahu: kapan dia harus kerja, dan kapan cukup diam aja. 🔍 1. Kenali 3 Pola Dasar Penggunaan useEffect 🟦 A. Tanpa Dependency Array useEffect(() => { console.log("Selalu jalan setiap render"); }); Efek akan dijalankan setiap kali komponen dirender ulang.Jarang dibutuhkan, kecuali kamu memang pengen efek itu selalu jalan terus. 🟩 B. Dengan Dependency Kosong [] useEffect(() => { console.log("Cuma jalan sekali (saat mount)"); }, []); Cocok untuk efek yang hanya perlu jalan sekali, seperti fetch data awal, set event listener, dll. 🟨 C. Dengan Dependency Spesifik [something] useEffect(() => { console.log("Jalan saat something berubah"); }, [something]); Efek hanya akan dijalankan saat nilai dalam dependency array berubah.Ini yang paling sering dipakai dalam praktik — dan juga paling rawan kesalahan kalau tidak hati-hati. 🧠 2. Pahami Alur Hidup Komponen (Lifecycle) Versi Function Component useEffect itu mirip gabungan antara componentDidMount, componentDidUpdate, dan componentWillUnmount di React versi class. Contoh: useEffect(() => { console.log("Mount atau update"); return () => { console.log("Cleanup: sebelum unmount atau sebelum efek jalan ulang"); }; }, [data]); Di awal: jalan saat komponen pertama kali dimount.Setiap data berubah: efek lama dibersihkan (cleanup), lalu efek baru dijalankan.Saat unmount: efek dibersihkan satu kali terakhir. 🛡️ 3. Tips Aman Gunakan useEffect 💡 Selalu pikirkan apakah efek ini perlu jalan setiap render, hanya sekali, atau hanya saat sesuatu berubah.🧪 Gunakan console.log() atau React DevTools untuk melacak render dan efek.🧠 Kalau kamu update state di dalam useEffect, pastikan efek itu tidak tergantung state tersebut secara langsung (tanpa kontrol).🔁 Hati-hati dengan fungsi inline dalam dependency, karena mereka dianggap “baru” di setiap render. ✍️ Rangkuman Gampangnya Kalau kamu pakai useEffect tapi hasilnya aneh:Cek dependency array-nya.Kalau dia kosong tapi efek jalan berkali-kali → mungkin ada Strict Mode.Kalau dia isi [state] dan efek update state itu → siap-siap infinite loop.Solusinya? Tambahin kondisi, atau ubah logika update-nya. ✨ Penutup useEffect itu powerful, tapi juga sensitif. Dia bekerja setiap kali ada perubahan dependensi, jadi kamu harus hati-hati banget dengan apa yang kamu masukkan di dalam []. Cara terbaik menghindari jebakan useEffect adalah paham konsep re-render dan dependency, bukan sekadar copy-paste dari StackOverflow. Kalau kamu belajar cara kerjanya dari balik layar, kamu akan lebih percaya diri saat nulis efek-efek kompleks nantinya. 6. Mengabaikan Key Saat Render List Mengabaikan Key Saat Render List Image by Freepik Kamu mungkin pernah lihat kode seperti ini waktu belajar React: {data.map((item) => ( <li>{item.name}</li> ))} Terlihat sederhana, ya? Tapi tunggu dulu — di balik layar, ini bisa bikin React sedikit "bingung" saat harus mengatur ulang elemen-elemen tersebut di DOM. Masalahnya terletak pada tidak adanya key. 🤔 Kenapa key Itu Penting? React menggunakan key sebagai identitas unik untuk setiap elemen dalam list. Ini penting banget saat: Data berubahElemen ditambah/dihapusAtau posisi elemen berubah Tanpa key, React nggak tahu mana item lama dan mana yang baru. Jadi, dia akan merender ulang semuanya dari nol, bahkan ketika kamu hanya mengubah satu elemen kecil. Ini bisa bikin performa drop dan, yang paling sering terjadi: UI jadi aneh, seperti input yang ter-reset, animasi glitch, dan lainnya. 💥 Contoh Masalah Tanpa Key Misalnya kamu punya form dinamis: {fields.map((field) => ( <input value={field.value} onChange={...} /> ))} Kalau kamu gak pakai key, dan user hapus satu field di tengah-tengah, React bakal salah deteksi posisi input — dan nilai input bisa tiba-tiba pindah ke field lain. Auto bikin frustasi! 😩 ✅ Cara Pakai Key dengan Benar Gunakan key yang: Unik untuk setiap itemKonsisten (tidak berubah-ubah) {users.map((user) => ( <li key={user.id}>{user.name}</li> ))} Kalau kamu pakai data dari database, ID biasanya sudah cukup bagus. 🚫 Jangan Gunakan Index Sebagai Key (Kalau Bisa) {items.map((item, index) => ( <li key={index}>{item}</li> ))} Kenapa? Karena kalau urutan list berubah, index akan berubah juga — dan ini menghancurkan performa serta merusak logika React. Gunakan index hanya kalau: Daftarnya statis (tidak bisa diubah)Tidak bisa punya ID unik (misalnya array hasil input user manual) ✨ Bonus Tips Kalau kamu pakai map() untuk render elemen list, ingat: wajib kasih key.Kalau kamu pakai komponen <TransitionGroup> atau animasi, key yang salah akan bikin animasi jadi kacau. 📝 Kesimpulan key itu kayak KTP untuk elemen di list — bantu React mengenali siapa-siapa yang masih sama, siapa yang baru, dan siapa yang udah nggak ada. Tanpa key yang bener, React akan nebak-nebak, dan tebakannya bisa salah. Hasilnya? UI kamu bisa error, performa jadi lambat, dan kamu jadi bingung sendiri. Jadi, next time kamu pakai .map() — jangan lupa kasih key, ya! 💡 7. Tidak Menangani Error dan Loading State Tidak Menangani Error dan Loading State Image by Freepik Bayangin kamu lagi buka aplikasi cuaca buat cek apakah perlu bawa payung hari ini. Tapi pas klik tombolnya... nggak ada apa-apa yang muncul. Diam. Sunyi. Padahal di balik layar, aplikasi lagi fetching data dari API. Nah, itulah kenapa handling loading dan error state itu penting banget. Tanpa ini, pengguna bakal merasa aplikasi “gagal” atau “bermasalah”, padahal kodenya cuma belum kasih tahu apa yang lagi terjadi. 💢 Contoh Kesalahan Umum Misalnya kamu bikin fetch data begini: useEffect(() => { fetch("<https://api.example.com/data>") .then((res) => res.json()) .then((data) => setData(data)); }, []); Selesai? Belum! 🚨 Kalau koneksi lambat? Nggak ada loading spinner. Kalau API error? Pengguna malah bengong ngeliat layar kosong. 🤕 Dampaknya? UX jelek → Pengguna bingung, ngira aplikasi nge-hang.Debugging susah → Kamu juga nggak tahu kalau ternyata API error.Aplikasi nggak kelihatan profesional. ✅ Solusi: Tambahkan Error & Loading State Yuk ubah contoh tadi jadi lebih manusiawi: const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const fetchData = async () => { try { setLoading(true); const res = await fetch("<https://api.example.com/data>"); if (!res.ok) throw new Error("Gagal mengambil data"); const json = await res.json(); setData(json); } catch (err) { setError(err.message); } finally { setLoading(false); } }; fetchData(); }, []); Dan di render-nya: if (loading) return <p>Loading data...</p>; if (error) return <p>Error: {error}</p>; return <DisplayData data={data} />; 🧠 Penjelasan: setLoading(true) → kasih tahu aplikasi bahwa kita mulai fetch data.try/catch → kalau ada error (misal: server down, salah URL, dsb), kita bisa tangani dengan baik.finally → bagian ini akan selalu dijalankan, entah berhasil atau gagal, jadi aman buat setLoading(false). ✨ Bonus Tips Kamu bisa bikin komponen <Loader /> atau <ErrorMessage /> agar bisa digunakan ulang di banyak tempat.Gunakan indikator visual yang familiar, seperti spinner, skeleton loader, atau teks sederhana.Untuk UX yang lebih baik, hindari tampilan loading kosong lebih dari 3 detik tanpa feedback apapun. 📝 Kesimpulan React bukan sulap.Kalau kamu nggak bilang “lagi loading”, dia nggak akan tahu.Kalau kamu nggak tangkap error-nya, dia nggak akan kasih peringatan. Sebagai developer, tugas kita bukan cuma bikin kode yang jalan, tapi juga bikin aplikasi yang nyaman dan terduga. Jadi, jangan skip handling loading & error ya! Kesimpulan Belajar React itu nggak instan. Nggak ada yang langsung jago setelah satu malam ngoding—bahkan developer berpengalaman pun masih suka buka dokumentasi dan debugging berjam-jam hanya untuk satu bug kecil. 😅 Tapi justru di situlah serunya. React ngajarin kita untuk berpikir dalam komponen, memahami alur data, dan lebih sabar menghadapi error. Dan seperti yang udah kita bahas tadi, ada beberapa jebakan yang sering bikin frustrasi di awal—dari lupa dasar JavaScript, terlalu fokus pada tools, sampai nggak nanganin loading state. Semua itu bukan tanda kamu gagal, tapi bagian alami dari proses belajar. Dengan tahu kesalahan-kesalahan umum ini, kamu udah selangkah lebih siap daripada kebanyakan orang. Kamu bisa ngelangkah lebih cepat, lebih mantap, dan lebih tenang. Nggak lagi panik pas useEffect bikin infinite loop, atau bingung kenapa props nggak bisa diubah. 💡 Penutup: Jangan Takut Salah React itu luas, dan kamu akan terus belajar seiring waktu. Jangan minder kalau kadang masih harus googling hal-hal “sepele”. Yang penting bukan soal salah atau bener, tapi soal mau belajar dan terus memperbaiki diri. “Jangan takut salah, asal tahu cara memperbaikinya.” Simpan kalimat itu baik-baik. Karena dalam dunia React — dan dunia coding pada umumnya — itulah skill paling berharga yang bisa kamu punya. Semangat terus belajar! 💪🚀

Kelas Cara Membuat Form Sederhana di React + Validasi Dasar di BuildWithAngga

Cara Membuat Form Sederhana di React + Validasi Dasar

Formulir adalah salah satu komponen yang paling sering kita temui di sebuah website. Entah itu form pendaftaran, login, komentar, atau sekadar form kontak sederhana — hampir semua aplikasi web butuh yang namanya form. Tapi meskipun terlihat sepele, form bisa jadi momok yng bikin pusing kepala, apalagi kalau sudah bicara soal validasi data. Mulai dari "harus diisi", "format email salah", sampai "password minimal 8 karakter" — semua itu perlu dicek biar data yang masuk ke sistem bersih dan valid. Kalau tidak, bisa kacau urusannya: data berantakan, user bingung, dan kita sebagai developer yang kena getahnya 😅 Nah, di artikel ini, kita akan bahas cara membuat form sederhana di React menggunakan Next.js 15, versi terbaru yang sudah memakai App Router dan punya struktur file modern. Selain itu, kita juga akan pakai Zod untuk validasi — ini adalah library validasi schema-based yang simpel tapi powerfull banget. Dan supaya proses input jadi lebih smooth, kita juga akan gabungkan dengan React Hook Form, salah satu library form handling terbaik di dunia React. Kenapa Zod? Karena validasi dengan Zod itu: Gampang ditulisJelas error-nyaBisa dipakai bareng React Hook Form dengan integrasi super mudah Jadi, kalau kamu: Masih baru di dunia React atau Next.jsSering bingung gimana cara validasi input form yang rapiPengen bikin form yang sederhana tapi tetap profesional ...artikel ini cocok banget buat kamu. Kita akan mulai dari nol — setup project, bikin UI form sederhana, pasang validasi dasar, sampai submit dan menampilkan data yang sudah diverifikasi. Tenang aja, semuanya akan dijelaskan pelan-pelan dan step by step. Yuk, kita langsung mulai dari instalasi proyek Next.js-nya! 🚀 Persiapan Proyek Sebelum kita mulai ngoding form dan validasinya, tentu kita harus siapin dulu proyek Next.js-nya. Di sini kita pakai Next.js 15 — versi terbaru yang sudah full power dengan App Router, Server Actions, dan banyak fitur keren lainnya. Kita juga bakal pakai TypeScript biar kodenya lebih aman dan terstruktur. Inisialisasi Proyek Next.js 15 Pertama, buka terminal (atau Command Prompt kalau kamu pakai Windows), lalu jalankan perintah berikut: bunx create-next-app@latest bwa-form Nanti kamu akan ditanya beberapa hal. Jawaban yang disarankan: ✔ Would you like to use TypeScript? › Yes ✔ Would you like to use ESLint? › Yes ✔ Would you like to use Tailwind CSS? › Yes (Opsional, tapi bikin form lebih cakep) ✔ Would you like to use `src/` directory? › Yes ✔ Would you like to use App Router? › Yes ✔ Would you like to use Turbopack for `next dev`? › Yes ✔ Would you like to customize the default import alias (@/*)? › No Setelah selesai, masuk ke folder proyek: cd bwa-form Lalu jalankan server: bun run dev Kalau semua berjalan lancar, kamu bisa buka browser dan akses http://localhost:3000 untuk melihat project Next.js kamu tampil dengan halaman default. Tampilan awal Next.js 15 Install Zod + React Hook Form Sekarang kita install library yang dibutuhkan untuk validasi form dan pengelolaan input: bun add zod react-hook-form @hookform/resolvers Penjelasan singkat: zod: untuk bikin schema validasi yang readable.react-hook-form: buat ngatur input form, handle submit, dan baca error dengan efisien.@hookform/resolvers: ini semacam "jembatan" antara Zod dan React Hook Form, jadi validasi Zod bisa langsung dipakai di form React. Membuat Form Sederhana Sekarang kita akan membuat sebuah form sederhana yang terdiri dari dua input: NamaEmail dan satu tombol submit. Belum ada validasi dulu ya, kita fokus ke tampilan dan logika submit dasar dulu. Validasi Zod-nya akan kita bahas di bagian berikutnya. Buat Halaman Register Buat file page.tsx pada direktori src/app/register/page.tsx seperti pada gambar berikut: Buat halaman register Ubah kode jadi seperti berikut ini: import RegisterForm from "@/components/register-form"; function RegisterPage() { return ( <main className="flex items-center justify-center min-h-screen"> <div className="flex flex-col gap-4 w-1/4"> <h1 className="text-2xl font-bold">Register</h1> <RegisterForm /> </div> </main> ); } export default RegisterPage; Kemdian buat file register-form.tsx padaa direktori src/components. Kalo direktorinya nggak ada, tinggal buat aja. Buat komponen form register dan tambahkan kode berikut: "use client"; import { useState } from "react"; const RegisterForm = () => { const [result, setResult] = useState(""); const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); const formData = new FormData(e.currentTarget); const name = formData.get("name"); const email = formData.get("email"); setResult(`Nama: ${name}, Email: ${email}`); }; return ( <> <form onSubmit={handleSubmit} className="space-y-4"> <div> <label htmlFor="name" className="block font-medium"> Nama </label> <input id="name" name="name" type="text" className="w-full border border-gray-300 p-2 rounded" /> </div> <div> <label htmlFor="email" className="block font-medium"> Email </label> <input id="email" name="email" type="email" className="w-full border border-gray-300 p-2 rounded" /> </div> <button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700" > Kirim </button> </form> {result && ( <div className="mt-4 bg-green-100 text-green-800 p-3 rounded"> {result} </div> )} </> ); }; export default RegisterForm; Penjelasan Singkat Kita pakai useState buat nampung hasil submit.handleSubmit akan dijalankan saat form disubmit, dan kita ambil nilai input dari FormData.Setelah itu, kita tampilkan hasilnya di bawah form.TailwindCSS dipakai buat styling dasar biar form-nya enak dilihat. Kalau kamu buka http://localhost:3000/register, sekarang kamu udah bisa isi form dan lihat hasilnya muncul setelah submit. Tapi ingat, belum ada validasi apa-apa. Jadi kalau kamu isi kosong atu email ngaco, tetap aja dianggap valid. Nah, di bagian berikutnya, kita akan atasi itu dengan Zod + React Hook Form. Register Form Menambahkan Validasi dengan Zod Form udah tampil, bisa diisi, bisa disubmit — tapi belum ada validasi sama sekali. Ini kayak pintu yang dibuka lebar tanpa filter. Sekarang kita akan integrasikan Zod untuk validasi input, dan sambungkan dengan React Hook Form biar prosesnya efisien dan nyaman. Setup Schema dengan Zod Pertama-tama, kita bikin schema validasi menggunakan Zod. Misalnya kita pengen: Nama wajib diisi dan minimal 2 karakterEmail wajib diisi dan harus format email yang benar Tambahkan ini di atas fungsi RegisterForm(): import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" // 1. Buat skema validasi dengan Zod const schema = z.object({ name: z.string().min(2, { message: "Nama minimal 2 karakter" }), email: z.string().email({ message: "Format email tidak valid" }), }) // 2. Tipe otomatis dari Zod type FormData = z.infer<typeof schema> Sehingga menjadi seperti berikut ini: "use client"; import { useState } from "react"; import { z } from "zod" import { useForm } from "react-hook-form" import { zodResolver } from "@hookform/resolvers/zod" // 1. Buat skema validasi dengan Zod const schema = z.object({ name: z.string().min(2, { message: "Nama minimal 2 karakter" }), email: z.string().email({ message: "Format email tidak valid" }), }) // 2. Tipe otomatis dari Zod type FormData = z.infer<typeof schema> const RegisterForm = () => { const [result, setResult] = useState(""); const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); const formData = new FormData(e.currentTarget); const name = formData.get("name"); const email = formData.get("email"); setResult(`Nama: ${name}, Email: ${email}`); }; return ( <> <form onSubmit={handleSubmit} className="space-y-4"> <div> <label htmlFor="name" className="block font-medium"> Nama </label> <input id="name" name="name" type="text" className="w-full border border-gray-300 p-2 rounded" /> </div> <div> <label htmlFor="email" className="block font-medium"> Email </label> <input id="email" name="email" type="email" className="w-full border border-gray-300 p-2 rounded" /> </div> <button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700" > Kirim </button> </form> {result && ( <div className="mt-4 bg-green-100 text-green-800 p-3 rounded"> {result} </div> )} </> ); }; export default RegisterForm; Dengan begini, kita udah punya aturan validasi dan juga tipe datanya. Pakai React Hook Form + Zod Selanjutnya kita ubah RegisterForm() agar pakai React Hook Form untuk handle form-nya: Ganti useState dan handleSubmit lama dengan ini: const { register, handleSubmit, formState: { errors }, } = useForm<FormData>({ resolver: zodResolver(schema), }) const onSubmit = (data: FormData) => { setResult(`Nama: ${data.name}, Email: ${data.email}`) } Kemudian ubah bagian <form> jadi seperti ini: <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> <div> <label htmlFor="name" className="block font-medium"> Nama </label> <input id="name" {...register("name")} className="w-full border border-gray-300 p-2 rounded" /> {errors.name && ( <p className="text-red-600 text-sm mt-1">{errors.name.message}</p> )} </div> <div> <label htmlFor="email" className="block font-medium"> Email </label> <input id="email" type="email" {...register("email")} className="w-full border border-gray-300 p-2 rounded" /> {errors.email && ( <p className="text-red-600 text-sm mt-1">{errors.email.message}</p> )} </div> <button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700" > Kirim </button> </form> Sehingga kode lengkapnya akan sepreti ini: "use client"; import { useState } from "react"; import { z } from "zod"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; // 1. Buat skema validasi dengan Zod const schema = z.object({ name: z.string().min(2, { message: "Nama minimal 2 karakter" }), email: z.string().email({ message: "Format email tidak valid" }), }); // 2. Tipe otomatis dari Zod type FormData = z.infer<typeof schema>; const RegisterForm = () => { const [result, setResult] = useState(""); const { register, handleSubmit, formState: { errors }, } = useForm<FormData>({ resolver: zodResolver(schema), }); const onSubmit = (data: FormData) => { setResult(`Nama: ${data.name}, Email: ${data.email}`); }; return ( <> <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> <div> <label htmlFor="name" className="block font-medium"> Nama </label> <input id="name" {...register("name")} className="w-full border border-gray-300 p-2 rounded" /> {errors.name && ( <p className="text-red-600 text-sm mt-1">{errors.name.message}</p> )} </div> <div> <label htmlFor="email" className="block font-medium"> Email </label> <input id="email" type="email" {...register("email")} className="w-full border border-gray-300 p-2 rounded" /> {errors.email && ( <p className="text-red-600 text-sm mt-1">{errors.email.message}</p> )} </div> <button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700" > Kirim </button> </form> {result && ( <div className="mt-4 bg-green-100 text-green-800 p-3 rounded"> {result} </div> )} </> ); }; export default RegisterForm; Apa yang Berubah? Kita pakai register() dari React Hook Form untuk menghubungkan input dengan state form.Semua validasi ditangani otomatis oleh Zod + zodResolver.Error ditampilkan tepat di bawah input dengan errors.nama?.message dan errors.email?.message. Sekarang kalau kamu isi form dengan kosong atau email ngawur, akan muncul pesan error. Dan kalau datanya valid, hasilnya akan tampil seperti sebelumnya. Contoh validasi gagal: Contoh validasi error Meningkatkan UX: Reset Form dan Loading State Setelah validasi jalan, kita bisa kasih sentuhan UX tambahan: form bisa di-reset setelah berhasil dikirim, dan ada indikator loading pas proses submit berlangsung. Reset Form Setelah Submit React Hook Form sudah menyediakan fungsi reset() yang bisa langsung kita pakai buat membersihkan semua input. Update onSubmit seperti ini: const { register, handleSubmit, reset, formState: { errors }, } = useForm<FormData>({ resolver: zodResolver(schema), }) const onSubmit = (data: FormData) => { setResult(`Nama: ${data.name}, Email: ${data.email}`) reset() // ← bersihkan form setelah submit } Mudah banget kan? Cukup panggil reset() setelah submit sukses, dan semua input akan kembali kosong. Reset field Menambahkan Loading State Sekarang kita tambahkan indikator loading biar user tahu kalau form sedang diproses. Kita pakai state isSubmitting dari formState milik React Hook Form: const { register, handleSubmit, reset, formState: { errors, isSubmitting }, } = useForm<FormData>({ resolver: zodResolver(schema), }) Lalu ubah tombol submit jadi seperti ini: <button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 disabled:opacity-50" disabled={isSubmitting} > {isSubmitting ? "Mengirim..." : "Kirim"} </button> Dengan begini: Tombol akan menampilkan "Mengirim..." saat proses berlangsungTombol otomatis nonaktif supaya user nggak bisa klik berkali-kali Untuk testing kitaa perlu mengubah kode ketiak onSubmit menjadi seperti berikut: const onSubmit = async (data: FormData) => { setResult("") // clear result sebelumnya await new Promise((resolve) => setTimeout(resolve, 2000)) // ← delay 2 detik setResult(`Nama: ${data.name}, Email: ${data.email}`) reset() } Maka hasilnya akan seperti ini: Loading state Kenapa Ini Penting? Karena di dunia nyata, proses submit biasanya melibatkan request ke server (misalnya kirim ke Supabase, API Route, atau Server Action). Nah, selama proses itu, user perlu feedback visual bahwa aplikasi sedang "bekerja". Validasi Username: Biar Gak Ada "admin" Palsu 😎 Username adalah salah satu input penting yang sering dipakai buat identitas pengguna. Karena itu, kita perlu pastikan nilai yang dimasukkan: Nggak terlalu pendek,Nggak pakai karakter aneh-aneh,Dan yang paling penting: nggak nyamar jadi akun khusus seperti admin, root, atau superuser. Di bagian ini, kita tambahkan validasi lengkap untuk username menggunakan zod. Validasi ini mencakup: Panjang minimal 4 karakter Supaya nggak ada username kayak a, me, atau xy yang terlalu singkat dan susah dikenali.Hanya boleh huruf, angka, dash (-), dan underscore (_) Untuk menjaga format username tetap konsisten dan aman, tanpa karakter spesial seperti @, #, atau spasi.Larangan pakai kata-kata berbahaya seperti admin, root, dsb. Ini penting untuk menghindari penyalahgunaan identitas. Kita pakai refine() untuk mendeteksi apakah ada kata-kata yang seharusnya tidk boleh ada dalam username. Dengan kombinasi tiga aturan ini, kamu bisa menjaga kualitas dan keamanan input username sejak dari sisi klien — sebelum data dikirim ke server. Pertama, kita tentukan username yang dilarang dipakai, biasanya untuk alasan keamanan (menghindari user yang pura-pura jadi admin, root, dll). Buka file register-form.tsx lalu tambahkan kode berikut di atas schema: // list username yang dilarang const disallowedUsernamePatterns = ["admin", "superuser", "superadmin", "root"]; Lalu kita buat skema validasi untuk field username: username: z .string() .min(4, { message: "Username minimal 4 karakter" }) .regex(/^[a-zA-Z0-0_-]+$/, "Gunakan hanya huruf, angka, - dan _") .refine( (username) => { for (const pattern of disallowedUsernamePatterns) { if (username.toLowerCase().includes(pattern)) { return false; } } return true; }, { message: "Username terdapat kata yang dilarang" } ), Penjelasan Kenapa Ini Penting min(4): mencegah username yang terlalu pendek seperti a, ab, atau xyz.regex: memastikan karakter-karakter aneh (spasi, simbol, dll) tidak bisa masuk.refine: custom logic yang nggak bisa ditangani oleh validator bawaan Zod. Cocok untuk validasi yang butuh loop atau pengecekan substring seperti ini. Pada bagian onSubmit juga ubah jadi sepertii ini: const onSubmit = async (data: FormData) => { setResult(""); // clear result sebelumnya await new Promise((resolve) => setTimeout(resolve, 2000)); // ← delay 2 detik setResult( `Nama: ${data.name}, Email: ${data.email}, Username: ${data.username}` ); reset(); // ← bersihkan form setelah submit }; Terakhir tambahkn input form untuk username, seperti ini: <div> <label htmlFor="username" className="block font-medium"> Username </label> <input id="username" type="text" {...register("username")} className="w-full border border-gray-300 p-2 rounded" /> {errors.username && ( <p className="text-red-600 text-sm mt-1"> {errors.username.message} </p> )} </div> Maka kode lengkapnya akn menjadi seperti ini: "use client"; import { useState } from "react"; import { z } from "zod"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; // list username yang dilarang const disallowedUsernamePatterns = ["admin", "superuser", "superadmin", "root"]; const schema = z.object({ name: z.string().min(2, { message: "Nama minimal 2 karakter" }), email: z.string().email({ message: "Format email tidak valid" }), username: z .string() .min(4, { message: "Username minimal 4 karakter" }) .regex(/^[a-zA-Z0-0_-]+$/, "Gunakan hanya huruf, angka, - dan _") .refine( (username) => { for (const pattern of disallowedUsernamePatterns) { if (username.toLowerCase().includes(pattern)) { return false; } } return true; }, { message: "Username terdapat kata yang dilarang" } ), }); type FormData = z.infer<typeof schema>; const RegisterForm = () => { const [result, setResult] = useState(""); const { register, handleSubmit, reset, formState: { errors, isSubmitting }, } = useForm<FormData>({ resolver: zodResolver(schema), }); const onSubmit = async (data: FormData) => { setResult(""); // clear result sebelumnya await new Promise((resolve) => setTimeout(resolve, 2000)); // ← delay 2 detik setResult( `Nama: ${data.name}, Email: ${data.email}, Username: ${data.username}` ); reset(); // ← bersihkan form setelah submit }; return ( <> <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> <div> <label htmlFor="name" className="block font-medium"> Nama </label> <input id="name" {...register("name")} className="w-full border border-gray-300 p-2 rounded" /> {errors.name && ( <p className="text-red-600 text-sm mt-1">{errors.name.message}</p> )} </div> <div> <label htmlFor="email" className="block font-medium"> Email </label> <input id="email" type="email" {...register("email")} className="w-full border border-gray-300 p-2 rounded" /> {errors.email && ( <p className="text-red-600 text-sm mt-1">{errors.email.message}</p> )} </div> <div> <label htmlFor="username" className="block font-medium"> Username </label> <input id="username" type="text" {...register("username")} className="w-full border border-gray-300 p-2 rounded" /> {errors.username && ( <p className="text-red-600 text-sm mt-1"> {errors.username.message} </p> )} </div> <button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700" disabled={isSubmitting} > {isSubmitting ? "Mengirim..." : "Kirim"} </button> </form> {result && ( <div className="mt-4 bg-green-100 text-green-800 p-3 rounded"> {result} </div> )} </> ); }; export default RegisterForm; Dan hasilnya akan seperti ini: Validasi username Validasi Password: Minimal Aman, Gak Asal Asal Saat membuat form pendaftaran, bagian password itu penting banget. Gak cuma asal diisi, tapi juga perlu divalidasi supaya pengguna: Masukkan password yang cukup kuat (minimal panjangnya),Ada huruf besar (A–Z)Ada angka (0–9)Ada simbol (!@#$%^&* dsb.)Dan memastikan mereka mengetik ulang password dengan benar (konfirmasi password). Dengan begini, kita sudah membuat form-nya lebih aman dan lebih user-friendly. Nggak lucu kan, udah bikin akun, eh password-nya salah sendiri 😅 Tambahkan kode berikut pada zod schema: password: z .string() .min(8, { message: "Password minimal 8 karakter", }) .regex(/[A-Z]/, "Password harus mengandung huruf besar (A-Z)") .regex(/[0-9]/, "Password harus mengandung angka (0-9)") .regex(/[^a-zA-Z0-9]/, "Password harus mengandung simbol (!@#$, dll)"), confirmPassword: z.string().min(8, { message: "Password minimal 8 karakter", }), .string()→ Input harus berupa string (teks)..min(8, ...)→ Wajib minimal 8 karakter untuk mencegah password yang terlalu pendek dan mudah ditebak..regex(/[A-Z]/, ...)→ Harus ada setidaknya satu huruf besar (misalnya A, B, Z). Ini bikin password lebih bervariasi..regex(/[0-9]/, ...)→ Harus mengandung angka. Misalnya 1, 2, atau 9..regex(/[^a-zA-Z0-9]/, ...)→ Harus mengandung karakter khusus/simbol, seperti @, !, #, &, dll. Dan juga tambahkan ini untuk validasi kecocokan password: .refine((data) => data.password === data.confirmPassword, { message: "Password tidak cocok", path: ["confirmPassword"], }) Baris ini penting banget karena: .refine() digunakan untuk validasi lintas field (cross-field validation).(data) => data.password === data.confirmPassword → memeriksa apakah password dan konfirmasinya sama.Kalau nggak sama, maka akan muncul error "Password tidak cocok" khusus di bagian confirmPassword. Sehingga kode schema akan menjadi seperti ini: const schema = z .object({ name: z.string().min(2, { message: "Nama minimal 2 karakter" }), email: z.string().email({ message: "Format email tidak valid" }), username: z .string() .min(4, { message: "Username minimal 4 karakter" }) .regex(/^[a-zA-Z0-0_-]+$/, "Gunakan hanya huruf, angka, - dan _") .refine( (username) => { for (const pattern of disallowedUsernamePatterns) { if (username.toLowerCase().includes(pattern)) { return false; } } return true; }, { message: "Username terdapat kata yang dilarang" } ), password: z .string() .min(8, { message: "Password minimal 8 karakter", }) .regex(/[A-Z]/, "Password harus mengandung huruf besar (A-Z)") .regex(/[0-9]/, "Password harus mengandung angka (0-9)") .regex(/[^a-zA-Z0-9]/, "Password harus mengandung simbol (!@#$, dll)"), confirmPassword: z.string().min(8, { message: "Password minimal 8 karakter", }), }) .refine((data) => data.password === data.confirmPassword, { message: "Password tidak cocok", path: ["confirmPassword"], }); Tujuannya Apa? Validasi seperti ini mendorong pengguna membuat password yang: Tidak mudah ditebak,Sulit diretas lewat brute force,Dan lebih sesuai standar keamanan modern (mirip sistem perbankan atau layanan email besar). Tambahkan kode berikut ini utnuk input password: <div> <label htmlFor="password" className="block font-medium"> Password </label> <input id="password" type="password" {...register("password")} className="w-full border border-gray-300 p-2 rounded" /> <div className="mt-1 h-2 w-full bg-gray-200 rounded"> <div className="h-full rounded transition-all" style={{ width: `${(passwordStrength / 4) * 100}%`, backgroundColor: passwordStrength < 2 ? "red" : passwordStrength === 2 || passwordStrength === 3 ? "orange" : "green", }} /> </div> <p className="text-sm mt-1"> Kekuatan:{" "} {passwordStrength < 2 ? "Lemah" : passwordStrength === 2 || passwordStrength === 3 ? "Sedang" : "Kuat"} </p> {errors.password && ( <p className="text-red-600 text-sm mt-1"> {errors.password.message} </p> )} </div> <div> <label htmlFor="confirmPassword" className="block font-medium"> Konfirmasi Password </label> <input id="confirmPassword" type="password" {...register("confirmPassword")} className="w-full border border-gray-300 p-2 rounded" /> {errors.confirmPassword && ( <p className="text-red-600 text-sm mt-1"> {errors.confirmPassword.message} </p> )} </div> Sehingga kode lengkapnya akan menjadi seperti berikut ini: "use client"; import { useState } from "react"; import { z } from "zod"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; // list username yang dilarang const disallowedUsernamePatterns = ["admin", "superuser", "superadmin", "root"]; const schema = z .object({ name: z.string().min(2, { message: "Nama minimal 2 karakter" }), email: z.string().email({ message: "Format email tidak valid" }), username: z .string() .min(4, { message: "Username minimal 4 karakter" }) .regex(/^[a-zA-Z0-0_-]+$/, "Gunakan hanya huruf, angka, - dan _") .refine( (username) => { for (const pattern of disallowedUsernamePatterns) { if (username.toLowerCase().includes(pattern)) { return false; } } return true; }, { message: "Username terdapat kata yang dilarang" } ), password: z .string() .min(8, { message: "Password minimal 8 karakter", }) .regex(/[A-Z]/, "Password harus mengandung huruf besar (A-Z)") .regex(/[0-9]/, "Password harus mengandung angka (0-9)") .regex(/[^a-zA-Z0-9]/, "Password harus mengandung simbol (!@#$, dll)"), confirmPassword: z.string().min(8, { message: "Password minimal 8 karakter", }), }) .refine((data) => data.password === data.confirmPassword, { message: "Password tidak cocok", path: ["confirmPassword"], }); type FormData = z.infer<typeof schema>; const RegisterForm = () => { const [result, setResult] = useState(""); const calculatePasswordStrength = (password: string) => { let strength = 0; if (password.length >= 8) strength += 1; if (/[A-Z]/.test(password)) strength += 1; if (/[0-9]/.test(password)) strength += 1; if (/[^a-zA-Z0-9]/.test(password)) strength += 1; return strength; }; const { register, handleSubmit, reset, watch, formState: { errors, isSubmitting }, } = useForm<FormData>({ resolver: zodResolver(schema), }); const passwordValue = watch("password"); const passwordStrength = calculatePasswordStrength(passwordValue || ""); const onSubmit = async (data: FormData) => { setResult(""); // clear result sebelumnya await new Promise((resolve) => setTimeout(resolve, 2000)); // ← delay 2 detik setResult( `Nama: ${data.name}, Email: ${data.email}, Username: ${data.username}` ); reset(); // ← bersihkan form setelah submit }; return ( <> <form onSubmit={handleSubmit(onSubmit)} className="space-y-4"> <div> <label htmlFor="name" className="block font-medium"> Nama </label> <input id="name" {...register("name")} className="w-full border border-gray-300 p-2 rounded" /> {errors.name && ( <p className="text-red-600 text-sm mt-1">{errors.name.message}</p> )} </div> <div> <label htmlFor="email" className="block font-medium"> Email </label> <input id="email" type="email" {...register("email")} className="w-full border border-gray-300 p-2 rounded" /> {errors.email && ( <p className="text-red-600 text-sm mt-1">{errors.email.message}</p> )} </div> <div> <label htmlFor="username" className="block font-medium"> Username </label> <input id="username" type="text" {...register("username")} className="w-full border border-gray-300 p-2 rounded" /> {errors.username && ( <p className="text-red-600 text-sm mt-1"> {errors.username.message} </p> )} </div> <div> <label htmlFor="password" className="block font-medium"> Password </label> <input id="password" type="password" {...register("password")} className="w-full border border-gray-300 p-2 rounded" /> <div className="mt-1 h-2 w-full bg-gray-200 rounded"> <div className="h-full rounded transition-all" style={{ width: `${(passwordStrength / 4) * 100}%`, backgroundColor: passwordStrength < 2 ? "red" : passwordStrength === 2 || passwordStrength === 3 ? "orange" : "green", }} /> </div> <p className="text-sm mt-1"> Kekuatan:{" "} {passwordStrength < 2 ? "Lemah" : passwordStrength === 2 || passwordStrength === 3 ? "Sedang" : "Kuat"} </p> {errors.password && ( <p className="text-red-600 text-sm mt-1"> {errors.password.message} </p> )} </div> <div> <label htmlFor="confirmPassword" className="block font-medium"> Konfirmasi Password </label> <input id="confirmPassword" type="password" {...register("confirmPassword")} className="w-full border border-gray-300 p-2 rounded" /> {errors.confirmPassword && ( <p className="text-red-600 text-sm mt-1"> {errors.confirmPassword.message} </p> )} </div> <button type="submit" className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700" disabled={isSubmitting} > {isSubmitting ? "Mengirim..." : "Kirim"} </button> </form> {result && ( <div className="mt-4 bg-green-100 text-green-800 p-3 rounded"> {result} </div> )} </> ); }; export default RegisterForm; Dan hasilnya akan menjadi seperti berikut ini: Validasi password Penutup Wah, akhirnya sampai juga ya di ujung artikel ini. Kita udah bareng-bareng bikin form pendaftaran sederhana pakai React dan Next.js 15, terus kita kasih bumbu validasi dari Zod, dan ditambah sentuhan UX kayak loading state, reset, sampai indikator kekuatan password. Lumayan lengkap, kan? Kalau kita ibaratkan form ini kayak pintu masuk ke rumah aplikasi kita, maka validasi itu adalah sistem keamanan biar yang masuk beneran "orang baik-baik". Kita nggak cuma asal tampung data, tapi juga jaga kualitas dan konsistensi sejak dari form paling depan. Menariknya, meskipun form ini terlihat sederhana, banyak banget pelajaran penting yang bisa kita ambil — mulai dari logika validasi dasar, pengelolaan state di React, sampai bagaimana bikin pengalaman pengguna jadi lebih nyaman dan jelas. 🚀 Eksplorasi Lanjutan? Yuk Gas! Kalau kamu udah sampai sini, berarti kamu udah punya pondasi yang solid buat ngembangin form yang lebih kompleks. Beberapa ide buat eksplorasi selanjutnya: 🔢 Multi-step form: cocok buat form panjang biar nggak bikin user kabur⏳ Async validation: misalnya ngecek email/username udah dipakai atau belum📱 Optimasi mobile UX: fokus ke input UX dan auto-capitalize🧠 Integrasi ke backend (misalnya Supabase atau tRPC) Terima kasih udah ngikutin sampai akhir 🎉 Semoga artikel ini bisa bantu kamu bikin form yang lebih baik, lebih aman, dan lebih nyaman buat user kamu. Kalau ada pertanyaan, ide, atau mau share hasil implementasi, jangan sungkan buat ngobrol bareng. Sampai jumpa di tutorial selanjutnya ya! 👋

Kelas Perbandingan Platform Kerja Remote 2025: Upwork, Contra, Fiverr, dan Lainnya di BuildWithAngga

Perbandingan Platform Kerja Remote 2025: Upwork, Contra, Fiverr, dan Lainnya

Tahun 2025, kerja remote udah bukan tren sementara udah jadi gaya hidup. Banyak orang mulai sadar bahwa kerja dari rumah (atau dari mana aja) itu bukan cuma mungkin, tapi juga menyenangkan dan produktif. Apalagi setelah baca artikel sebelumnya, 25 Pekerjaan Remote yang Bisa Kamu Lakukan dari Rumah (Tanpa Harus Jago Coding), pasti kamu makin semangat nyari peluang kerja online yang sesuai dengan skill kamu. Tapi, setelah tahu jenis-jenis pekerjaannya, pertanyaan selanjutnya pasti muncul: “Platform mana yang paling cocok buat aku?” Yup, sekarang platform kerja remote jumlahnya makin banyak. Mulai dari yang sistemnya bidding kaya Upwork dan Freelancer, sampai yang simpel dan langsung to the point kayk Contra dan Fiverr. Masing-masing punya kelebihan, kekurangan, dan karakteristik sendiri. Nah, di artikel ini, kita bakal bahas dan bandingin beberapa platform kerja remote yang paling populer di tahun 2025. Tujuannya simpel: biar kamu nggak bingung lagi milih tempat buat mulai (atau upgrade) karier freelance-mu. Kriteria Perbandingan (Biar kamu gampagn nentuin mana platform yang paling pas) Sebelum kita masuk ke detail tiap platform, penting banget buat tahu kriteria apa aja yang kita pakai buat bandingin mereka. Jadi kamu nggak asal daftar karena ikut-ikutan, tapi bisa milih yang beneran cocok sama gaya kerja dan tujuan kamu. Berikut ini beberapa poin yang bakal kita pakai buat menalai dan membandingkan platform-platform kerja remote di 2025: Jenis Pekerjaan yang Tersedia Apakah platform ini fokus di pekerjaan kreatif kayak desain dan tulis-menulis? Atau justru banyak proyek teknis sepeti data entry, coding, atau virtual assistant? Penting banget buat tahu karena tiap platform punya “niche” masing-masing. Cara Kerja (Bidding vs Direct Hire) Ada platform yang pakai sistem bidding, di mana kamu harus bersaing dengan freelancer lain buat dapetin proyek (contohnya: Upwork). Tapi ada juga yang pakai sistem direct hire, klien tinggal pilih kamu dari profil atau katalog jasa yang kamu tawarkan (contohnya: Fiverr dan Contra). Tipe yang mana yang kamu suka? Proses Pendaftaran & Verifikasi Ada platform yang simpel banget cukup daftar, bikin profil, langsung bisa jual jasa. Tapi ada juga yang perlu verifikasi identitas, portofolio, bahkan sesi wawancara singkat. Kita bakal bandingin seberapa ribet (atau gampang) proses awalnya. Potensi Penghasilan Berapa kisaran harga proyek yang biasa muncul di sana? Apakah kamu bisa pasang tarif sendiri? Apakah klien di platform itu lebih suka harga murah atau kualitas tinggi? Ini penting buat kamu yang pengin dapet penghasilan sesuai skill dan waktu yang kamu keluarkan. Metode Pembayarana Bisa tarik ke rekening lokal? Butuh akun PayPal atau Wise? Berapa lama proses pencairannya? Kita bakal lihat platform mana yang paling fleksibel dan cepat buat urusan bayar-membayar. Kelebihan dan Kekurangan Setiap platform punya plus dan minusnya. Ada yang punya komunitas aktif, tapi fee-nya tinggi. Ada juga yang cocok buat pemula tapi proyeknya terbatas. Kita bahas dua sisi biar kamu bisa ambil keputusan yang adil. Cocok untuk Siapa? Terakhir, kita simpulkan: platform ini cocoknya buat siapa? Apakah buat pemula, pekerja kreatif, spesialis IT, atau orang yang baru pindah ke dunia freelance? Bagian ini bakal bantu kamu ngelihat “fit” antara platform dan profil kamu. Perbandingan Platform Populer 1. Upwork Tampilan website Upwork Upwork adalah “raksasa” di dunia kerja remote platform global yang sudah eksis sejak penggabungan Elance dan oDesk di 2015. Mulai dari pekerjaan entri data sampai analisis data tingkat lanjut, kamu bisa menemukan proyek dari seluruh penjuru dunia. Banyak perusahaan besar dan startup memilih Upwork sebagai tempat rekrutmen freelancer andal. Pokoknya, peluangnya luas banget, asal kamu tahu cara mainnya. Sistem Kerja: Bidding & Proposal Di Upwork, kamu harus “nawar” proyek alias bidding. Kamu bikin proposal yang menjelaskan kenapa kamu cocok untuk proyek itu. Tapi, kamu nggak bisa ngirim proposal sembarangan. Kamu butuh yang namanya Upwork Connects, semacam koin digital yang dibutuhkan setiap kali kamu melamar kerja. Biasanya dikasih gratisan tiapp bulan, tapi kalau habis, kamu bisa beli. Jadi, selain skill, kamu juga butuh strategi buat menonjol di antara banyaknya pelamar. Kelebihan: Pasar global luas: ribuan proyek anyar setiap hari dari berbagai industri.Pembayaran aman: escrow memastikan kamu dibayar sesuai kesepakatan.Peluang jangka panjang: klien loyal bisa menghasilkan income stabil.Badge & reputasi: Top Rated & Expert-Vetted bikin profilmu makin unggul upwork.com.Spesialisasi moncer: area seperti AI, data analytics, atau generative AI sedang naik daun .Perusahaan besar membuka job: Microsoft, Airbnb, Glassdoor, GoDaddy aktif post di Upwork Kekurangan: Persaingan super ketat, terutama di kategori umum seperti penulis, desain, atau VA.Butuh waktu bangun reputasi—mulai dari tarif masuk rendah dan review minim.Fee freelancer hingga 10%; ada tambahan biaya untuk withdraw.Connects bisa bikin boros kalau kamu kirim banyak proposal tanpa strategi.Proyek bisa tiba-tiba ditutup, walaupun kamu sudah submit proposal; kadang bikin frustasi. Cocok untuk: Profesional remote full-time, yang siap fokus bikin karier.Pemula serius yang ingin investasi waktu untuk reputasi jangka panjang.Strategic thinkers, yang mau riset klien dan bikin proposal menarik.Spesialis niche (AI, data, bahasa, legal) yang bisa tawarkan keahlian spesifik.Freelancer yang hype dengan badge Top Rated & Expert-Vetted Profil Sukses: Jacqueline Ann DeStefano‑Tangorra (AS) Profil Jacqueline Ann DeStefano‑Tangorra Mantan auditor di PwC yang hijrah ke Upwork selama pandemi 2020. Dia membangun jasa data analytics & AI lewat platform ini, launching agensi Omni BI Solutions, dan berhasil meraup ≈ US $470.000 dari 131 proyek dalam 3,5 tahun. **Kurniawan S.** (Indonesia) Profil Kurniawan S. Translator & content writer Indonesia–Inggris, dengan profil: 235 jobs, +9.600 jam kerja, rating 5.0, rate US 25/jam. Konsisten, rapi, dan banyak melayani klien besar. Stephan B. (Indonesia) Profil Stephan B. Top Rated Translator & Data Specialist, menyelesaikan 75+ jobs dengan rating 4.9 dan rate US 8–20/jam. Kalau kamu termasuk orang yang tekun, suka riset, dan nggak takut bersaing, Upwork bisa jadi jalan panjang yang menguntungkan. Tapi kalau kamu tipe yang lebih suka ditawari proyek langsung tanpa ribet, jangan khawatir di bagian selanjutnya kita bahas Contra, platform yang lebih simpel dan cocok buat kreator masa kini. 2. Contra Tampilan website Contra Kalau Upwork itu kayak pasar kerja global yang rame dan kompetitif, Contra lebih kayak cozy studio kreatif yang modern dan rapi. Contra adalah platform kerja remote yang tanpa potongan fee, jadi kamu dapet 100% dari bayaran klien. Nggak ada sistem bidding di sini. Semuanya langsung dari klien ke freelancer, alias direct client. Platform ini memang didesain buat para kreator modern: desainer, penulis, content creator, UI/UX, bahkan video editor. Cara kerjanya lebih simpel dan minim drama. Sistem Kerja & Fitur Andalan: Direct hire: klien langsung menghubungi kamu lewat profil atau service catalog.Portofolio terintegrasi: kamu bisa tampilkan desain, studi kasus, dan hasil nyata dengan template yang estetis .Testimoni & Discover tab: review dari klien muncul di profil, membantu kamu tampil terpercaya.Kalendar booking & manajemen kontrak: atur jadwal pekerjaan langsung lewat platform.Payments escrow & invoice built-in: pembayaran aman tanpa potongan, langsung ke rekening kamu.Pro features (Premium $29/bulan): kustom domain, analytics lanjutan, visibilitas ekstra. Satu hal yang bikin Contra beda: kamu bisa kelihatan lebih profesional meskipun baru mulai, asal portofoliomu ditata rapi. Kelebihan: 0% commission fee—kamu dapat semua penghasilan, hanya dipotong biaya transfer/stripe.Profil keren & profesional berkat portofolio custom & testimoni.Prospek klien lebih berkualitas—Contra kurat job untuk hindari proyek “goceng”.Pembayaran cepat & aman: escrow aktif dan langsung cair ke rekening/invoice fitur .Komunitas progresif: sering ada event & dukungan dari tim, bahkan founder sendiri (Ben Huffman) aktif terlibat.Skalabilitas: kamu bisa tumbuh lewat portofolio dan pola pendapatan berulang tanpa mengurangi income. Kekurangan: Volume job masih terbatas, terutama untuk niche yang bukan kreatif; job list baru rilis berkali sehari .Kurang pas untuk pemula total; kamu butuh portofolio dulu untuk menarik klien .Payout belum tersedia di semua negara, tapi Stripe, PayPal, dan bank transfer sudah banyak didukung .Biaya Pro (premium) diperlukan untuk akses fitur seperti custom domain dan visibilitas di Discover.Marketplace masih berkembang, belum sebesar Upwork atau Fiverr. Cocok Untuk: Desainer grafis / UI‑UX yang ingin tampil profesional dan work‑based branding.Writer / Copywriter degan portofolio rapi dan klien ideal.Kreator digital seperti video editor, motion designer, atau brand strategist.Freelancer yang ingin kontrol penuh harga dan format kontrak.Orang yang care dengan branding, keamanan, dan profesionalisme—apoteker project‑by‑project. Profil Sukses: Julia Sit (Graphic Designer, Indonesia) Porfil Julia Sit Fokus di brand e‑commerce, ia mengungkapkan bahwa 99% income-nya datang dari Contra, dengan klien yang konsisten dan aman secara payment. Dengan kisah nyata ini, Contra jadi pilihan cerdas buat freelancer yang ingin tampil premium dan profesional. Bila kamu siap membangun branding lewat kualitas dan bukan kuantitas bidding, platform ini layak dicoba. 3. Fiverr Tampilan website Fiverr Kalau Upwork itu seperti kantor profesional tempat kamu harus ngelamar kerja, dan Contra seperti studio pribadi yang rapi, maka Fiverr itu ibarat pasar digital yang rame dan penuh warna. Di sini, kamu bisa jual jasa mulai dari yang umum sampai yang super niche—dari desain logo, voice over, penulisan artikel, sampe bikin jingle lucu buat ulang tahun. Uniknya, kamu nggak perlu melamar ke klien. Sebaliknya, kamu yang bikin "toko" sendiri dan pasang “produk” atau layanan yang bisa dibeli klien kapan aja. Fiverr berasal dari ide “semua bisaa dimulai dari $5”, tapi sekarang udah jauh berkembang. Banyak freelancer bisa dapet ratusan hingga ribuan dolar per project, tergantung skill dna reputasi. Sistem Kerja: Jualan Gigs ala Marketplace Di Fiverr, kamu akan membuat “Gig”—layanan yang kamu tawarkan, lengkap dengan harga, deskripsi, dan contoh hasil kerja. Misalnya: “Tulis artikel SEO 1000 kata dalam 3 hari”“Edit video TikTok profesional dengan transisi kekinian”“Desain logo minimalis + revisi tak terbatas” Kamu bisa bikin 3–7 paket layanan per kategori (Basic, Standard, Premium) dengan harga dan fitur berbeda. Klien tinggal klik, bayar, dan kamu langsung mulai kerja setelah sistem escrow Fiverr aktif. Semua komunikasi dan pembayaran terjadi di platform—jadi kamu nggak perlu kirim invoice atau negosiasi lewat email. Kelebihan: Nggak perlu kirim proposal, tinggal pasang gig dan tunggu orderan datangProses simpel dan cocok buat kamu yang suka jualan sistem paketCocok untuk layanan cepat dan project kecil-menengahAda fitur “Fiverr Pro” untuk freelancer top yang pengen dapet klien premiumTampilannya mirip marketplace, gampang dipahamiAda aplikasi mobile buat pantau order sambil rebahanBisa dijadikan passive client income kalau gig kamu udah mulai rame Kekuragan: Potongan fee cukup besar: 20% dari penghasilanPersaingan cukup ketat, apalagi di kategori populer seperti desain dan penulisanAlgoritma platform bisa berubah, mempengaruhi visibilitas gigKlien cenderung minta “banyak” dengan harga seminim mungkin (harus tegas & pintar atur deskripsi)Harus aktif dan fast response biar rating tetap bagus Cocok Untuk: Freelancer pemula yang mau langsung action tanpa proposal ribetKreator dengan layanan spesifik yang bisa dipaketkanVideo editor, voice over artist, penulis artikel, designer, hingga animatorOrang yang pengen bangun “toko jasa digital” secara konsisten Profil Sukses: Charmaine Pocek (AS) – Profil Fiverr Profil Charmaine Pocek Mantan recruiter yang jadi full-time resume writer di Fiverr ProUdah dapat lebih dari 15.000 review positifPenghasilannya tembus $300.000 per tahun hanya dari FiverrSering diwawancarai media seperti CNBC dan Forbes Fiverr itu cocok buat kamu yang suka sistem langsung jualan, nggak mau ribet proposal, dan punya layanan yang bisa dikemas seperti produk. Tapi tetap butuh strategi, branding, dan konsistensi buat bisa bersaing dan bertahan. Kalau kamu udah punya skill dan tinggal bingung “nawarin ke siapa ya?”, Fiverr bisa jadi tempat mulai yang menyenangkan. 4. Freelancer.com Tampilan website Freelancer.com Bayangin Freelancer.com seperti ajang global: kamu bisa ikut bidding project, ikutan lomba desain, atau pasang service—semuanya di satu tempat. Sejak 2009, platform ini tumbuh pesat dengan ~60 juta pengguna dari s***evarnya dunia. Pekerjaannya sangat beragam: IT, desain, penulisan, hingga engineering—semua ada, dan ga sedikit yang pakai sistem milestone untuk keamanan bayarannya . Kalau kamu suka tantangan, kompetisi, dan variety pekerjaan, Freelancer bisa jadi taman bermainmu—walau persaingannya lumayan sengit. Sistem Kerja & Fitur Unggulan: Bidding & Kontes: Lamar langsung ke proyek atau ikuti kontes (termasuk design & naming).Proposal & Milestone: Taruhan kayak Upwork, tapi kamu juga bisa minta dibayar sebagian sebelum mulai.Skill Test & badges: naikin trust klien lewat lencana Verified & Preferred Freelancer.Showcase & Jobs_feed: Menang lomba? Karyamu bisa tampil khusus di halaman.Keanggotaan Premium: Ada paket bulanan untuk bid lebih banyak & fitur tambahan. Kelebihan: Komunitas global besar = bukan hanya punya banyak klien, tapi juga banyak kategori project.Kontes bisa bikin portofolio cepat terpampang dan reputasi moncer.Milestone payments bikin payment process jadi lebih aman & sistematis freelancer.com.Tools lengkap: skill-test, showcase, preferred badge—semuanya untuk meningkatkan visibilitasmu.Pembayaran mendunia: dukungan multiple currency & withdraw ke banyak metode. Kekurangan: Persaingan sengit, terutama di kategori luas seperti design atau penulisan.Fee 10%, bisa turun dengan membership tapi tetap ada minimal $5.Bid terbatas: kamu butuh membership untuk bid lebih sering.Algoritma yang kadang sulit dipahami—gig kamu bisa saja tenggelam.Risiko proyek batal: kalau klien cabut, biddingmu bisa sia-sia. Ccocok Untuk: Freelancer yang siap bersaing habis-habisan, ikut bidding & kontes.Orang yang butuh exposure banyak project sekaligus.Freelancer ingin nyetart skill tanpa takut bayar upfront.Spesialis teknis (IT, engineering, data analysis) yang bikin bid kompetitif. Profil Sukses: Matt dari BrightDock LLC Matt dari BrightDock LLC Seorang freelancer skala enterprise, klaim sudah menghasilkan $1,5 juta lewat platform ini. **Andrea Reggio (Venezuela)** Andrea Reggio Jadi jurnalis freelance global tanpa repot, modal lulusan dan gig konsisten. 5. Sribulancer (sebelumnya Sribulancer/Sribu) Tampilan website Sribulancer Kalau Freelancer.com adalah pasar global, maka Sribu/Sribulancer adalah pasar lokal premium Indonesia sejak 2011. Fokus utamanya di design, branding, video, tulisan, dan digital marketing—dengan sistem kontes dan gig ala Shopify lokal. Didukung investasi dari East Ventures dan Mynavi Jepang, platform ini didesain buat mendekatkan antara brand/UMKM lokal dengan freelancer yang profesional. Sistem Kerja & Fitur: Gig dan kontes desain: upload portofolio & ikut kompetisi logo, packaging, dll.Level system (Newcomer–Grand Master): level kesuksesan freelancer otomatis naik berdasarkan rating & jumlah proyek.Platform lokal: pembayaran dalam Rp, support tim lokal, dan laporan sesuai regulasi Indonesia.Comunication selalu via platform: chat + milestone payments di sistem built-in Kelebihan: Sistem pembayaran lokal, nggak ribet konversi mata uang.Feedback & rating berbasis level, bikin freelancer lebih terlihat profesional.Komunitas lokal aktif, dengan support lebih personal.Kontes menarik: banyak UMKM minta desain logo, menjadikan ini tempat belajar sekaligus unjuk karya.Fee transparan antara 10–20% Kekurangan: Kurang terhubung ke klien global; job terbatas di pasar domestik.Kompetisi ketat di kategori populer seperti logo dan branding.Fitur gig kurang "product-based", lebih banyak proyek per-job.Pembayaran bulanan, tidak instan seperti escrow global. Cocok Untuk: Talenta kreatif lokal: desainer grafis, video editor, copywriter.Freelancer yang ingin awal mula dalam sistem lokal.Orang yang ingin portfolio kuat buat pasar Indonesia pusat.Freelancer yang nyaman dengan pembayaran Rupiah. Reviews: @dodpop8 – Graphic Designer: “Sribu provides opportunities … safe and reliable … communication … comfortable”@Hardianto81 – Graphic Designer: “By using Sribu, we can make a living as long as we are consistent …”@wiellyam – Web Developer: “As a freelancer … opportunity to find clients and gain direct trust from business owners.” Dengan dua platform ini, kamu bisa milih mau berkarya di panggung global (Freelancer.com) atau panggung nasional (Sribulancer)—keduanya lengkap dengan cerita sukses nyata dari freelancer yang gigh. 6. Projects.co.id Tampilan website Projects.co.id Kalau Series kita ini adalah cerita soal platform lokal Indonesia, Projects.co.id bisa dibilang versi “gabungan e-commerce dan freelance marketplace” yang unik. Sejak diluncurkan tahun 2014 oleh PT Panonpoe Media, platform ini memungkinkan kamu tidak hanya menerima proyek, tapi juga menjual produk digital seperti template, e-book, atau desain siap-pakai. Bayangin kamu buka toko dan studio sekaligus di satu tempat: klien datang, kamu bid proyek, selesai—atau klien langsung beli jasa atau produk yang sudah kamu pajang. Semua bisa di-handle di dashboard yang sederhana dan mudah dipahami. Sistem Kerja & Fitur Andalan: Bidding & Services hybrid: kamu bisa kirim penawaran untuk proyek tertentu, atau bikin produk/jasa fixed-price yang siap dibeli langsung.Escrow built-in: dana klien ditahan dulu sampai tugas selesai, lalu otomatis dialirkan setelah konfirmasi—aman buat freelancer dan klien .Marketplace digital products: kamu bisa jual asset seperti mockup, planner, atau e-book sambil freelance job.Integrasi chat & notifikasi real-time: langsung bisa komunikasi dengan klien lewat app.Laporan & riwayat transaksi: semua transparan, bisa dilihat dalam dashboard secara mudah. Kelbihan: Pembayaran dalam Rupiah dan transfer bank lokal → gampang dan hemat biaya.Hybrid job-dan-product marketplace membantu kamu diversifikasi pendapatan dengan cepat.Platform yang user-friendly → review di Play Store menyebut aplikasi “mudah dan legit”.Cocok untuk freelancer pemula karena pasar lokalnya mulai berkembang dan mudah dimengerti.Escrow terintegrasi bikin aman walau kontak langsung dengan klien.Peluang jual aset digital jadi nilai tambah yang unik dibanding tempat lain. Kekurangan: Kadang bugs & lag—menurut review di Play Store banyak yang mengeluhkan blank chat atau crash saat bidding.Iklan dalam aplikasi mengganggu menurut beberapa pengguna.Kasus penipuan pernah terjadi, terutama soal DP atau progress tak lanjut.Pasar lokal berarti akses ke proyek global lebih terbatas.Fiturnya belum selengkap platform global—adventure masih terasa untuk yang teknikal. Cocok Untuk: Freelancer digital asal Indonesia seperti penulis, penerjemah, desain grafis, virtual assistant, dan admin marketplace.Kreator asimetris yang juga ingin jual asset digital (template, e-book, mockup).Pemula freelance yang butuh latihan bidding dan interaksi lokal.Freelancer yang nyaman dengan pembayaran lokal dan aplikasi mobile.Orang yang ingin diversifikasi antara service dan produk digital. Dengan semua fasilitas dan potensi yang ditawarkan, Projects.co.id merupakan pilihan menarik bagi freelancer di Indonesia yang ingin mulai dari lokal, sambil belajar, dan punya ruang untuk tumbuh. Tips Memilih Platform yang Tepat Jadi, setelah lihat berbagai platform tadi, dari yang penuh strategi kayak Upwork, yang estetik kayak Contra, sampai yang lokal banget kayak Projects.co.id, mungkin kamu mulai mikir: “Terus, aku harus mulai dari mana dong?” Nah, sebelum asal daftar dan buang waktu (atau Connects 😅), ini beberapa tips yang bisa bantu kamu milih platform freelance yang paling pas buat kamu: 1. Kenali Dulu Skill & Gaya Kerjamu Setiap platform punya “ritme” kerja yang beda. Misalnya: Kamu suka ngobrol, nego, dan jago bikin proposal? ➤ Cocok banget main di Upwork.Kamu introvert yang pengen klien tinggal klik dan bayar? ➤ Contra atau Fiverr bisa jadi tempat nyaman.Kamu suka bantuin bisnis lokal, ngerti cara kerja orang Indonesia? ➤ Projects.co.id atau Sribulancer bisa jadi pintu awal. Dan yang paling penting, kamu harus jujur sama dirimu sendiri: Apakah kamu nyaman pitching? Atau lebih suka ditawari kerja berdasarkan portfolio? 2. Mulai dari yang Paling Sesuai dengan Pengalaman Kalau kamu: Belum punya klien sama sekali → Mulai dari platform lokal bisa lebih mudah masuk.Sudah pernah freelance tapi pengen serius → Coba platform global seperti Contra atau Upwork.Punya banyak portfolio digital (desain, tulisan, video) → Langsung listing service di Fiverr atau Contra. Jangan buru-buru nargetin platform “besar” kalau pondasimu belum siap. Mulai dari yang realistis lebih baik daripada burnout di tengah jalan. 3. Jangan Terpaku Satu Platform—Diversifikasi! Banyak freelancer pemula mikir, “Aku bakal all-in di satu platform biar fokus.” Nggak salah. Taapi, realitanya: Klien bisa naik-turun tergantung musim.Algoritma bisa berubah.Persaingan makin ketat setiap tahun. Solusinya? Pakai strategi multichannel: Bisa mulai dari Projects.co.id + Contra.Atau Fiverr untuk layanan cepat + Upwork buat project gede.Atau Contra buat portfolio + LinkedIn untuk networking langsung. Jangan taruh semua telur di satu keranjang. Diversifikasi itu penyelamat! 4. Portofolio & Profil = Senjata Utama Bayangin kamu masuk toko sepatu, terus nggak ada contoh sepatu yang dipajang. Males, kan? Sama halnya dengan klien: Mereka nggak peduli kamu lulusan mana—mereka cuma pengen tahu: “Kamu bisa bantu saya atau nggak?” Jadi: Susun portfolio yang fokus ke solusi: tampilkan hasil nyata, bukan cuma “desain bagus”.Kalau belum punya klien? Bikin dummy project, kerjain proyek fiktif, atau bantuin teman/UMKM lokal.Perbarui deskripsi diri di profil: siapa kamu, keahlianmu, gaya kerjamu, dan apa yang bikin kamu beda. Bonus Tips: Aktif di komunitas freelance bira nggak ketinggalan info dan dapet support mental.Belajar terus: soft skill (komunikasi, negosiasi) itu sama pentingnya dengan hard skill.Jangan bandingin perjalananmu sama orang lain. Semua butuh proses. Kesimpulan Kalau kamu udah nyimak dari awal sampai sini—keren banget! 🚀 Berarti kamu beneran serius pengen nyemplung (atau makin dalam) di dunia kerja remote. Dan satu hal yang pasti: Nggak ada platform freelance yang “terbaik untuk semua orang.”Yang ada, platform yang paling cocok buat kamu. Mau kamu ibu rumah tangga yang nyari penghasilan sambil jaga anak, fresh graduate yang baru lulus dan bingung mulai dari mana, atau pekerja kantoran yang pengen banting setir—masing-masing punya jalannya sendiri. Intinya… Upwork cocok buat kamu yang tahan uji, sabar bangun reputasi, dan jago bikin strategi proposal.Contra pas banget kalau kamu suka desain estetis, personal branding, dan kerjaan berbasis hasil akhir.Fiverr cocok buat yang pengen “jualan jasa cepat” tanpa ribet kirim proposal.Projects.co.id & Sribulancer bisa jadi batu loncatan pertama, apalagi kalau kamu lebih nyaman pakai Bahasa Indonesia dan paham pasar lokal. Di 2025 ini, kerja remote bukan lagi mimpi. Teknologi makin gampang diakses. Klien dari seluruh dunia buka peluang. Platform freelancing makin beragam. Tapi yang paling penting bukan platform-nya... Yang paling penting adalah: kesiapan kamu. Siap untuk terus belajar. Siap bangun portfolio. Siap gagal, bangkit, dan nyoba lagi. Karena freelance itu bukan sekadar cari uang—tapi juga soal membangun reputasi, relasi, dan rasa percaya diri. Dan kamu bisa mulai dari hari ini. Dari satu akun. Satu project. Satu klien. Terus belajar, terus melangkah, dan jangan lupa istirahat juga. Karena dunia remote nggak ke mana-mana—tapi kesehatanmu harus tetap dijaga 😄

Kelas 25 Pekerjaan Remote yang Bisa Kamu Lakukan dari Rumah (Tanpa Harus Jago Coding) di BuildWithAngga

25 Pekerjaan Remote yang Bisa Kamu Lakukan dari Rumah (Tanpa Harus Jago Coding)

Bayangin begini: pagi-pagi kamu bangun tanpa suara alarm yang bikin kaget, nggak perlu buru-buru mandi, dandan, atau rebutan kendaraan sama orang rumah. Sambil ngopi santai, kamu buka laptop, duduk di meja kerja favorit, dan mulai kerja dari ruang tamu, teras, atau bahkan dari kamar. Nggak ada bos yang ngawasin dari balik meja, nggak ada meeting dadakan di kantor yang bikin stres. Kedengarannya kayak mimpi, ya? Tapi nyatanya, kerja remote udah jadi kenyataan buat banyak orang. Apalagi sejak pandemi kemarin, dunia kerja berubah drastis. Banyak perusahaan sadar kalau karyawan tetap bisa produktif walaupun kerja dari rumah. Bahkan sekarang, banyak perusahaan luar negeri yang membuka peluang kerja remote untuk siapa aja, dari mana aja. Tapi mungkin kamu berpikir, "Kerja remote kan buat orang-orang yang bisa ngoding, ngerti IT, atau lulusan teknik komputer." Nah, ini dia kesalahan yang sering banget terjadi. Banyak orang merasa nggak cukup “pintar teknologi” buat kerja remote, padahal faktanya banyak pekerjaan remote yang bisa dikerjakan tanpa skill coding sama sekali. Aku pun dulu berpikir gitu. Ngerasa kerja remote itu cuma buat programmer. Tapi setelah cari tahu, ternyata ada begitu banyak peluang buat yang latar belakangnya non-IT. Mulai dari penulis konten, admin sosial media, sampai virtual assistant—semuanya bisa dikerjakan dari rumah, bahkan dari desa sekalipun, selama ada koneksi internet. Di artikel ini, aku bakal share ke kamu 25 jenis pekerjaan remote yang bisa kamu lakuin tanpa harus jadi ahli teknologi. Pekerjaan ini cocok buat kamu yang pengen ganti suasana kerja, mulai karier baru, atau sekadar cari penghasilan tambahan dengan cara yang lebih fleksibel. Siapkan cemilan dan kopi kamu, karena kita bakal bahas satu per satu—siapa tahu salah satunya cocok buat kamu. 😉 Apa Itu Kerja Remote & Kenapa Banyak Dicari? Apa itu kerja remote & kenapa banyak dicari? Image by freepik Sebelum kita bahas daftar pekerjaannya, yuk kenalan dulu sama istilah yang lagi naik daun ini: kerja remote. Kerja remote itu sederhananya kerja yang nggak harus dilakukan dari kantor. Artinya, kamu bisa kerja dari mana aja—rumah, warung kopi, coworking space, bahkan dari kota atau negara lain sekalipun. Yang penting kamu tetap bisa komunikasi sama tim dan menyelesaikan tugasmu tepat waktu. Dulu, kerja remote tuh dianggap “tidak normal”. Kalau bilang ke orang tua, “Aku kerja dari rumah aja,” mungkin dibalas dengan, “Lho, kok nggak ke kantor? Emang itu beneran kerja?” Tapi sekarang, kerja remote udah makin diterima, bahkan jadi pilihan utama banyak orang. Apalagi generasi sekarang makin sadar bahwa hidup itu bukan cuma soal kerja 9 to 5 dan terjebak macet setiap hari. Bukan cuma kita yang butuh fleksibilitas. Perusahaan juga mulai sadar bahwa dengan sistem remote, mereka bisa rekrut talenta dari mana aja tanpa harus nyiapin kantor fisik. Lebih hemat biaya, dan kadang justru lebih produktif. Nah, tren ini makin kuat sejak pandemi 2020. Banyak perusahaan akhirnya "dipaksa" buat coba kerja jarak jauh, dan ternyata... berhasil! Sejak saat itu, lowongan kerja remote terus meningkat, termasuk untuk pekerjaan non-IT. Dan yang menarik, sekarang banyak kerja remote yang nggak butuh kamu jadi expert teknologi atau lulusan informatika. Punya kemampuan dasar seperti komunikasi yang oke, manajemen waktu, dan sedikit skill digital udah cukup buat mulai. Tapi pertanyaannya: emangnya ada kerjaan kayak gitu? Jawabannya: ADA! Banyak malah. Yuk kita intip daftar 25 pekerjaan remote yang bisa kamu mulai dari sekarang—tanpa harus jadi jago ngoding atau ngerti IT tingkat dewa. 25 Pekerjaan Remote untuk Pemula, Ibu Rumah Tangga, dan Fresh Graduate (Tanpa Harus Jago Coding!) Kerjaan ini bisa kamu mulai walau belum punya banyak pengalaman. Bahkan banyak yang bisa dikerjakan paruh waktu atau fleksibel, cocok buat kamu yang masih kuliah, baru lulus, atau punya kesibukan di rumah. Pekerjaan Remote Buat yang Suka Nulis dan Komunikasi Content Writer Image by Freepik Content Writer Bayangin kamu duduk di teras rumah, ditemani secangkir teh hangat, dan mulai nulis artikel tentang tips menata dapur kecil biar tetap kece. Itulah kerjaan seorang content writer. Tugas utamanya adalah menyampaikan informasi lewat tulisan yang ringan dan menarik. Nggak perlu jadi sastrawan—yang penting kamu bisa riset, nulis dengan gaya yang asyik, dna tahu siapa yang baca. Rutinitas sehari-hari: Cek brief dari klien atau tim editorialRiset topik dan cari referensi dari berbagai sumberBuat kerangka atau outline artikelMenulis artikel sesuai gaya bahasa target audiensEdit tulisan agar lebih enak dibaca dan bebas typoTambahkan elemen pendukung seperti gambar, infografis, atau kutipanSubmit artikel ke Google Docs, CMS, atau langsung ke klien Copywriter Image by Freepik Copywriter Kamu pernah baca iklan simpel tapi langsung bikin pengen beli? "Diskon cuma hari ini!" misalnya. Nah, itu kerjaan copywriter. Tugasnya bikin tulisan singkat tapi "nendang" buat promosi produk. Bisa berupa slogan, email marketing, caption, atau landing page. Cocok buat kamu yang suka main kata dan mikir out-of-the-box. Rutinitas sehari-hari: Menganalisis brief dan tujuan iklan/tulisanRiset target audiens dan produkMenulis headline dan copy untuk iklan, landing page, email, dllMerevisi berdasarkan feedback klien atau timMenyesuaikan tone & voice sesuai brand Transcriber Image by Freepik Transcriber Bayangin kamu lagi dengerin podcast tentang parenting, sambil ngetik apa yang mereka omongin. Transcriber kerjaannya seperti itu: mendengarkan audio (kadang video), lalu mengetik ulang isi pembicaraannya dengan rapi. Cocok buat kamu yang teliti, sabar, dan nyaman bekerja sambil pakai headset. Rutinitas sehari-hari: Menerima file audio/video dari klienMendengarkan rekaman dan mengetik isi percakapanMenandai bagian tidak terdengar jelas (jika perlu)Memastikan ejaan dan tanda baca sesuai standarMengedit hasil transkrip sebelum dikirim Translator Image by Freepik Translator Kamu jago bahasa Inggris, Korea, Jepang, atau bahasa lain? Jadi translator remote bisa jadi ladang cuan! Misalnya, kamu nerjemahin artikel resep dari Bahasa Inggris ke Bahasa Indonesia. Atau subtitle drama Korea buat channel YouTube. Asal ngerti dua bahasa dan tahu konteks, kamu udah bisa mulai. Rutinitas sehari-hari: Menerima dokumen atau file dari klienMenerjemahkan teks sesuai konteks dan budayaMengecek akurasi terjemahan secara menyeluruhMemastikan konsistensi istilah teknisMengirim hasil akhir dalam format yang diminta Customrer Support Image by Freepik Customer Support (Live Chat/Email) Bayangin kamu jadi "penolong pertama" buat pelanggan toko online yang bingung soal pengiriman barang. Kamu bantu mereka lewat chat atau email, menjawab pertanyaan, dan bikin pengalaman mereka lebih nyaman. Cocok buat kamu yang sabar, komunikatif, dan suka bantuin orng. Rutinitas sehari-hari: Mengecek tiket pertanyaan pelangganMenjawab pertanyaan via chat, email, atau media sosialMenyampaikan laporan masalah ke tim teknisUpdate knowledge base atau FAQRekap interaksi harian ke sistem/CRM Pekerjaan Kreatif yang Bisa Dipelajari Cepat Desain Grafis Image by Freepik Desain Grafis Pernah iseng bikin quote pakai Canva terus dipuji temen karena estetik? Itu bisa jadi pintu masukmu ke dunia desain grafis. Banyak bisnis butuh desain buat poster, feed Instagram, sampai kemasan produk. Nggak harus jago Photoshop kok—mulai aja dari tool gratis kayak Canva atau Figma, lalu terus eksplor. Rutinitas sehari-hari: Menerima brief dari klien/tim marketingMembuat sketsa konsep visualMendesain konten visual (poster, feed IG, banner, dll)Melakukan revisi sesuai masukanMenyimpan file desain dalam format siap pakai Social Media Manager Image by Freepik Social Media Manager Bayangin kamu pegang akun Instagram sebuah brand makanan, terus tiap hari bikin konten, upload story, dan ngobrol sama followers. Seru, kan? Nah, kerjaan ini cocok buat kamu yang aktif di medsos dan ngerti tren. Kamu bisa bantu UMKM atau brand bikin strategi konten biar makin dikenal. Rutinitas sehari-hari: Menyusun kalender konten mingguan/bulananMenulis caption dan menjadwalkan postingMembalas komentar dan DM dari audiensAnalisis performa konten (engagement, reach)Kolaborasi dengan desainer atau tim kreatif Video Editor Image by Freepik Video Editor (Dasar) Kamu sering bikin video lucu buat status WA atau TikTok keluarga? Kamu udah punya modal jadi video editor! Banyak kreator butuh bantuan edit video ringan: potong klip, tambah musik, kasih teks. Pakai aplikasi kayak CapCut atau VN aja dulu, lalu pelan-pelan belajar software yang lebih kompleks. Rutinitas sehari-hari: Menerima footage mentah dari klien atau timMenyusun timeline dan mengedit video (potong, transisi, efek)Menambahkan backsound, subtitle, dan elemen grafisMengekspor video sesuai spesifikasi platformMenyimpan backup file proyek Illustrator/Digital Artist Image by Freepik Illustrator / Digital Artist Suka gambar digital? Kamu bisa jual jasa ilustrasi buat buku anak, komik, bahkan stiker WhatsApp. Nggak harus gambar realis kok—gaya kawaii, doodle, atau minimalis juga banyak peminatnya. Banyak platform seperti Fiverr atau Instagram yang bisa jadi etalase karyamu. Rutinitas sehari-hari: Membaca brief atau skrip dari klien/editorMembuat sketsa kasar untuk ilustrasiMelakukan revisi berdasarkan feedbackMenyelesaikan ilustrasi dengan detail warna dan shadingMengirimkan hasil dalam format digital UI/UX Designer Image by Freepik UI/UX Designer UI/UX Designer fokus bantu bikin tampilan dan pengalaman aplikasi atau website jadi mudah dan menarik. Meskipun ini bagian dari dunia IT, banyak orang belajar dari nol lewat kursus online. Kalau kamu suka ngulik aplikasi dan punya rasa ingin tahu tinggi, ini bidang yang menjanjikan dan bisa dipelajari step-by-step. Kalo kamu mau belajar UI/UX berikut beberapa rekomendasi kelas yang bisa kamu ikuti dari BuildWithAngga: Kelas Online Gratis UI UX Figma to No-Code Lovable AI: Bikin Landing PageUltimate UX Guide: Focus on User-Centered DesignMastering Mobile UI Design for Beginners with FigmaMastering Figma: Modern UI Dashboard Design Rutinitas sehari-hari: Menganalisis kebutuhan pengguna atau client briefMembuat wireframe dan prototipe (Figma/Adobe XD)Kolaborasi dengan developer dan stakeholderMelakukan usability testingMerevisi desain berdasarkan hasil testing Pekerjaan yang Butuh Skill Riset & Organisasi Data Entry Image by Freepik Data Entry Bayangin kamu bantuin satu usaha kecil buat masukin data penjualan mereka ke Excel. Kerjaan ini nggak ribet, asal kamu teliti dan rapi. Cocok banget buat kamu yang suka kerja sistematis dan nggak keberatan ngulang hal yang sama. Rutinitas sehari-hari: Menerima data mentah dari klienMemasukkan data ke sistem/spreadsheet dengan akuratMengecek ulang data untuk menghindari kesalahanMengelompokkan atau mengkategorikan dataBackup data secara rutin Virtual Asisstant Image by Freepik Virtual Assistant (VA) Kamu pernah bantuin temen ngatur jadwal arisan, bikin daftar belanja, atau cek email masuk? Kalau iya, kamu udah punya modal jadi VA. Tugas VA itu macam-macam: mulai dari ngatur kalender, balas email, sampai nyusun laporan ringan. Bisa bantuin pebisnis, freelancer, atau konten kreator. Rutinitas sehari-hari: Mengecek dan membalas email klienMenjadwalkan meeting dan pengingat tugasMengatur file dan dokumen digitalMembuat laporan sederhana (Excel, Google Docs)Koordinasi dengan tim atas nama klien Research Asisstant Image by Freepik Rersearch Assistant Suka penasaran sama sesuatu dan doyan cari info sampai ke akar? Jadi research assistant mungkin cocok buatmu. Misalnya, kamu bantuin influencer cari referensi buat konten edukasi, atau bantu startup riset tren pasar. Kerjaan ini fleksibel dan cocok buat kamu yang suka ngulik. Rutinitas sehari-hari: Mencari informasi dari sumber akademik atau webMerangkum dan menyusun hasil risetMenyusun daftar pustaka atau referensiMengisi spreadsheet riset dan insightPresentasi hasil riset ke tim atau atasan Project Coordinator Freelance Image by Freepik Project Coordinator Freelance Kalau kamu suka ngatur-ngatur, jadi project coordinator bisa cocok. Tugasnya bantu tim freelance agar kerjaan berjalan sesuai timeline. Meski nggak coding, kamu tetap berperan penting buat koordinasi antar anggota tim. Rutinitas sehari-hari: Membuat jadwal dan timeline kerja timMengecek progres tugas dari freelancer lainKomunikasi rutin dengan klien dan timMenyusun laporan proyekMengatur revisi atau penyesuaian kerja Moderator Komunitas Online Image by Freepik Moderator Komunnitas Online Bayangin kamu jadi penjaga ketertiban di grup parenting Facebook atau komunitas belajar online. Tugasnya ngejaga suasana tetap nyaman, bantu jawab pertanyaan anggota, dan lapor kalau ada postingan yang nggak sesuai aturan. Cocok buat kamu yang sabar dan suka berinteraksi di forum. Rutinitas sehari-hari: Memantau komentar dan postingan anggotaMenghapus konten yang melanggar aturanMenjawab pertanyaan umum anggota komunitasMenyusun peraturan komunitas atau FAQMelaporkan aktivitas harian ke tim admin Pekerjaan Remote di Dunia Edukasi & Kursus Online Tutor Online (Non-Akademik) Image by Freepik Tutor Online (Non-Akademik) Kamu jago main gitar, masak, atau bikin kerajinan tangan? Coba deh buka kelas online kecil-kecilan. Banyak orang nyari tutor buat skill non-akademik. Bisa mulai dari WhatsApp group, Zoom, atau platform kursus. Cocok buat kamu yang sabar dan seneng ngajarin. Rutinitas sehari-hari: Menyiapkan materi pembelajaran untuk sesi onlineMengajar lewat Zoom atau platform lainMenjawab pertanyaan murid di luar sesiMemberi tugas dan nilaiMenyimpan catatan perkembangan siswa Bantu Bikin Modul/Konten Belajar Image by Freepik Bantu Bikin Modul/Konten Belajar Kalau kamu suka bikin rangkuman atau presentasi, kerjaan ini cocok banget. Banyak guru, pelatih, atau institusi yang butuh bantuan bikin materi belajar. Misalnya, bikin slide Canva buat pelajaran matematika anak SD. Asal kamu rapi dan bisa riset, bisa banget dicoba. Rutinitas sehari-hari: Menentukan topik berdasarkan silabusMenulis materi pembelajaran dengan struktur jelasMenambahkan ilustrasi, gambar, atau video pendukungMembuat soal latihan atau kuisMenyesuaikan modul sesuai jenjang/tingkatan Proofreader Materi Belajar Image by Freepik Proofreader Materi Belajar Kamu suka baca dan jeli banget kalau ada typo? Jadi proofreader bisa jadi opsi menarik. Tugasnya ngecek tulisan—misalnya soal latihan, e-book, atau artikel—biar bebas dari salah ketik dan jelas dibaca. Cocok buat kamu yang perfeksionis dan detail. Rutinitas sehari-hari: Membaca ulang materi dari penulis/modulMemperbaiki typo, ejaan, dan tanda bacaMemastikan kalimat mudah dipahamiKonsistenkan gaya penulisanTandai bagian ambigu atau perlu direvisi Pengisi Kuis dan Latihan Soal Image by Freepik Pengisi Kuis dan Latihan Soal Pernah bikin kuis seru buat grup keluarga atau komunitas? Kamu bisa ubah itu jadi kerjaan, lho! Banyak platform belajar atau guru privat yang butuh bantuan bikin soal latihan, lengkap sama jawaban. Bisa untuk pelajaran SD sampai SMA. Rutinitas sehari-hari: Menyusun soal pilihan ganda, isian, atau uraianMenulis kunci jawaban dan pembahasanMemastikan soal sesuai standar/topikMengecek duplikasi atau kemiripan soalMengelompokkan soal berdasarkan level kesulitan Narator Konten Edukassi Image by Freepik Narator Konten Edukasi Bayangin kamu jadi suara di balik video pembelajaran anak-anak, atau jadi narator di podcast edukasi. Modalnya mirip kayak voice over—cukup suara jelas, artikulasi bagus, dan semangat ngajarin yang tinggi. Cocok buat kamu yang pengen tetap berkontribusi tanpa harus tampil langsung. Rutinitas sehari-hari: Membaca naskah konten dengan intonasi jelasMerekam suara dengan alat yang layakMengedit hasil rekaman untuk kejernihan audioMenyesuaikan durasi sesuai naskahMengirim hasil akhir dalam format audio Pekerjaan Remote Tambahan yang Fleksibel & Santai Microtask Worker (Pekerjaan Mikro) Image by Freepik Microtask Worker (Pekerjaan Mikro) Pernah denger soal kerjaan kecil seperti ngetik captcha, ngisi survei, atau nge-tag gambar? Ini disebut microtask. Cocok buat kamu yang pengen kerja santai, tanpa tekanan. Lumayan buat nambah penghasilan tanpa skill khusus. Rutinitas sehari-hari: Mengerjakan tugas-tugas kecil (labeling, tagging, dsb)Memastikan akurasi data sesuai petunjukSubmit pekerjaan dalam waktu singkat Tester Produk (Product Reviewer) Image by Freepik Tester Produk (Product Reviewer) Kamu bisa dibayar buat nyobain produk dan kasih review. Misalnya, coba skincare, alat rumah tangga, atau aplikasi baru. Bisa dalam bentuk tulisan atau video. Selain dapat produk gratis, kamu juga bisa dapet fee! Rutinitas sehari-hari: Mencoba produk digital atau fisikMencatat pengalaman penggunaan (user experience)Melaporkan bug atau errorMengisi form evaluasi produkMemberi saran perbaikan jika diminta Penjual Online (Reseller/Dropshipper) Image by Freepik Penjual Online (Reseller/Dropshipper) Kalau kamu suka jualan tapi nggak punya modal buat stok barang, jadi dropshipper bisa jadi solusi. Kamu tinggal pasarkan produk dari supplier dan mereka yang kirim ke pembeli. Bisa dikerjakan dari HP aja, cocok buat ibu rumah tangga. Rutinitas sehari-hari: Upload produk ke marketplace atau toko onlineBalas pertanyaan dan chat calon pembeliMengemas dan mengirim barang (jika bukan dropship)Cek stok dan update hargaBuat promo atau konten jualan Pengisi Kuesioner / Survey Online Image by Freepik Pengisi Kuesioner / Survey Online Cuma jawab pertanyaan dari laptop atau HP, kamu bisa dapat uang atau voucher. Memang bayarannya kecil, tapi kalau rutin bisa lumayan. Cocok buat pengisi waktu luang di sela aktivitas harian. Rutinitas sehari-hari: Mendaftar di platform surveiMengisi survei sesuai profil atau minatMenjawab jujur sesuai panduanMelengkapi survei untuk mendapatkan poin/imbalanMenyimpan riwayat survei selesai Penulis Ulasan (Review Writer) Image by Freepik Penulis Ulasan (Review Writer) Kamu suka nulis ulasan makanan, film, atau produk? Banyak platform yang nyediain tempat buat kamu berbagi review dan dapat imbalan. Cocok buat kamu yang suka nulis santai dan jujur dari pengalaman pribadi. Rutinitas sehari-hari: Mencoba produk, aplikasi, atau layananMenulis review jujur berdasarkan pengalamanMenyertakan kelebihan dan kekuranganUpload ulasan di blog, marketplace, atau platform reviewTambahkan foto atau tangkapan layar bila perlu Tips Memulai Kerja Remote Bayangin kamu lagi duduk di depan laptop butut yang udah menemani bertahun-tahun. Kopi hitam buatan sendiri masih mengepul, dan kamu lagi scroll lowongan kerja remote di HP. Rasanya campur aduk—penasaran, tapi juga ragu. “Bisa nggak ya aku mulai dari nol?” Jangan khawatir. Semua yang udah sukses kerja remote juga mulai dari titik itu. Mulailah dengan kenali apa yang kamu suka. Misalnya kamu ibu rumah tangga yang suka ngeblog resep masakan, berarti kamu udah punya modal untuk jadi content writer. Atau kamu fresh graduate yang jago desain feed Instagram? Itu bisa jadi tiket ke dunia desain grafis. Bikin portofolio sederhana. Nggak perlu ribet—cukup pakai Canva atau Notion. Upload hasil desainmu, tulisanmu, atau test project yang kamu bikin sendiri. Ini semacam “kartu nama digital” biar calon klien percaya. Coba bantu UMKM sekitar rumah. Bantuin mereka buat caption, desain, atau ngurus katalog. Ini bisa kamu masukin ke portofolio juga. Sambil bantu orang, kamu juga latihan. Terakhir, gabung komunitas. Di grup Facebook, Telegram, Discord—di sana kamu bisa nemu mentor, job listing, dan semangat baru dari teman seperjuangan. Tools yang Sering Dipakai Dulu kamu mungkin cuma tahu Microsoft Word dan WhatsApp. Tapi begitu masuk dunia kerja remote, kamu akan kenal sahabat baru. 📞 Kalau mau meeting, kamu akan sering buka Zoom atau Google Meet. Tapi jangan khawatir, nggak harus jago ngomong di awal—yang penting sopan dan jelas. 📝 Kalau mau nulis atau edit dokumen bareng tim? Google Docs bisa jadi penyelamat. Lengkap dengan fitur komen dan revisi. 📋 Butuh ngatur to-do list biar kerjaan nggak berantakan? Coba Trello atau Notion—kayak papan tempel digital buat otakmu. 🎨 Kamu orang desain? Canva bisa jadi sahabat terbaik untuk pemula. Tapi kalau mau naik level, coba Figma buat kolaborasi desain yang lebih rapi. 🤖 Suka ngulik dan riset? ChatGPT bisa bantu kamu nulis, ngide, atau cari jawaban cepat. Tinggal tanya, dia jawab. Cara Terhindar dari Penipuan Kerja Remote Bayangin kamu dapet pesan di WhatsApp, “Kamu terpilih jadi admin marketplace, gajinya 7 juta per bulan! Tapi transfer dulu Rp200.000 buat aktivasi akun.” Waspadalah! Ini modus yang sering kejadian. Kerjaan remote yang asli nggak akan minta kamu bayar di awal. Kalau mereka bilang “deposit dulu”, langsung tinggalkan. Sebelum daftar kerja, coba cari nama perusahaannya di Google. Kalau nggak ada jejak, atau banyak review negatif, mending cari yang lain. Jangan asal kasih KTP, nomor rekening, atau data pribadi lengkap sebelum ada perjanjian kerja resmi. Lebih aman kalau kamu pakai platform resmi seperti Upwork atau Fiverr yang punya sistem escrow—uang klien ditahan dulu, baru dibayar kalau kerjaan selesai. Dan ingat: kalau tawarannya terdengar terlalu indah, mungkin memang bohong. Kalau kamu ibu rumah tangga yang lagi nyuapin anak sambil riset lowongan kerja, atau fresh graduate yang bingung arah hidup, percayalah—selama ada niat dan koneksi internet, kamu bisa punya karier hebat dari rumah. Dunia kerja remote itu luas, dan kamu punya tempat di dalamnya. 💻🌏✨ Rekomendasi Kelas Buat Belajar Kerja Remote Kalau kamu masih bingung harus mulai dari mana, ini beberapa kelas online yang relevan, praktis, dan cocok buat pemula yang pengen kerja remote tanpa harus jago coding: Belajar Kerja Remote UI/UX Design & No-Code dengan Contra Cocok buat kamu yang pengen masuk ke dunia desain tanpa harus ngerti coding. Belajar tools no-code, cara bangun portofolio, sampai tips dapetin client luar negeri via Contra.Belajar Upwork 2024: Jadi Freelancer Profesional, Hasilkan Ribuan Dollar Buat kamu yang pengen serius mulai di platform Upwork, kelas ini ngajarin strategi dapetin proyek, bikin proposal yang dilirik, dan cara bangun reputasi.Ebook: Petunjuk Pro Freelance Web Developer & Kerja Remote Kalau kamu sedikit banyak udah ngerti web development (HTML, CSS, atau Next.js), ebook ini bantu kamu loncat ke tahap jadi freelancer pro dengan strategi yang terbukti.Upwork Freelancer Mastery: Strategi Terbukti Raih 100 Juta Pertama Buat kamu yang serius dan pengen fokus cari penghasilan besar lewat Upwork. Belajar dari yang udah terbukti berhasil—dari mindset, positioning, sampai closing. Semua kelas di atas pakai bahasa Indonesia, cocok banget buat pemula, dan bisa langsung dipraktikkan! Penutup: Mulai dari Sekarang, Bukan Nanti Kerja remote bukan cuma tren, tapi peluang nyata—terutama buat kamu yang mungkin belum punya pengalaman kerja formal, lagi di rumah, atau sedang cari cara baru untuk mandiri secara finansial. Kamu nggak harus langsung jago. Yang penting, mulai dulu. Bisa dari ikut webinar, gabung komunitas, atau bantuin teman/UMKM sekitar. Setiap langkah kecilmu hari ini bisa jadi batu loncatan buat karier remote yang stabil dan bikin bangga. Ingat: 📌 Nggak semua orang harus bisa ngoding buat kerja online. 📌 Setiap orang punya kelebihan—temukan dan asah itu. 📌 Kerja remote = kerja beneran. Bukan cuma main HP atau kerja iseng. Kamu bisa kerja dari rumah, tetap dekat keluarga, dan tetap produktif. Apapun latar belakangmu, peluang kerja remote itu bisa banget jadi jalan buat masa depan yang lebih fleksibel dan membanggakan.

Kelas Riset Platform Contra: Solusi Freelance Tanpa Fee untuk Frontend Developer di BuildWithAngga

Riset Platform Contra: Solusi Freelance Tanpa Fee untuk Frontend Developer

Daftar Isi Artikel PendahuluanBenefit Setelah Membaca Artikel IniPengertian ContraFitur Utama ContraPortofolio InteraktifServices (Jasa Freelance)Tanpa KomisiSistem Pembayaran & Kontrak OtomatisTestimoni & EndorsementMengapa Contra Relevan untuk Frontend DeveloperShow Your Work, Bukan Cuma Ngaku BisaCocok Buat Proyek Kecil Maupun BesarBuat yang Mau Bangun Brand PersonalLebih Enak KomunikasiKelebihan & Kekurangan Menggunakan ContraKelebihanBebas KomisiProfil Keren & Portofolio InteraktifBisa Buat Layanan SendiriWorkflow Lebih RapiKekuranganBelum Seramai Platform LainFokus ke Kualitas, Bukan KuantitasBelum Terlalu Familiar di IndonesiaTips Maksimalin Contra untuk Frontend DeveloperAnggap Profil Kamu Kayak CV + Landing PageBikin Service yang Jelas dan MenjualUpload Portofolio yang Real & TerbaikMinta Testimoni dari Klien LamaRutin Update dan AktifPromosiin Profil Contra KamuStudi Banding Singkat: Contra vs Platform Freelance LainnyaContra vs FiverrContra vs UpworkContra vs Freelancer.comKesimpulan SingkatRekomendasi Kelas Contra Gratis & PremiumFREEPremiumPenutup Pendahuluan Kalau kamu seorang frntend developer dan pernah nyemplung ke dunia freelance, kemungkinan besar kamu pernah ngerasain fase absurd ini: buka tab banyak-banyak, apply ke Upwork, Fiverr, LinkedIn, tapi yang ngehubungin malah scammer yang minta kamu ngerjain "tes kecil" gratis. Sakitnya tuh bukan cuma di wakktu yang kebuang, tapi juga di rasa percaya diri yang ikut luntur. Dunia freelance tuh emang luas, tapi kayak hutan belantara. Banyak peluang, tapi juga banyak jebakan. Dan masalah klasiknya: plattform besar sering banget ambil potongan fee yang rasanya kayak pacar posesif, kamu yang kerja keras, mereka yang motong hasilnya. Belum lagi tampilannya kadang ribet, dan kalau belum punya rating atau review, kamu cuma jadi semut kecil di tengah lautan freelancer lain. Nah, di sinilah kita mulai kenalan sama satu nama: Contra. Contra ini bisa dibilang plattform freelance rasa portfolio site, tapi dengan sistem backend yang udah ngurusin hal-hal teknis kayak kontrak, invoice, dan pembayaran. Bedanya? Contra nggak ambil komisi sepeser pun dari bayaran kamu. Jadi, kamu dapet klien → dapet duit → duitnya utuh. Simple, jujur, dan lumayan melegakan buat dompet yang sering kehausan. Artikel ini bakal ngebedah Contra dari sisi teknis, fitur, sampai strategi maksimalkan peluang di dalamnya, khususnya buat kamu yang main di jalur frntend, dari project Figma to HTML, bikin UI React, sampe ngerjain landing page yang kece. Karena di dunia yang makin visual ini, kamu butuh tempat buat nunjukin kemampuan kamu, bukan cuma sekadar CV dalam format PDF. Siapin kopi atau air putih, karena kita bakal bahas tuntas: apa itu Contra, kenapa dia relevan buat kamu, dan gimana caranya bisa bantu kamu dapet project tanpa drama fee yang nyakitin. Benefit Setelah Membaca Artikel Ini Riset - Benefits ✅ Paham apa itu Contra dan kenapa plaatform ini beda dari yang lain (nggak ada potongan fee sama sekali). ✅ Tahu fitur-fitur penting di Contra yang berguna banget buat kamu sebagai frntend developer, mulai dari portofolio digital sampai sistem kontrak dan invoice otomatis. ✅ Ngerti kenapa Contra cocok banget buat kamu yang pengin bangun personal branding sebagai spesialis di bidang frontend. ✅ Dapat insight tentang kelebihan dan kekurangan Contra dibandingkan platform lain, biar kamu bisa ambil keputusan lebih bijak. ✅ Dapat tips konkret buat mulai di Contra, termasuk cara bikin profil menarik, strategi dapat klien pertama, dan cara mainin keyword biar lebih mudah ditemukan. ✅ Tahu kapan wakktu yang tepat buat pakai Contra, dan kapan mungkin kamu butuh backup di plaatform lain kayak Fiverr atau Upwork. ✅ Punya sudut pandang baru soal dunia freelance, bukan cuma soal cari duit, tapi juga soal bangun reputasi dan karier jangka panjang. Pengertian Contra Riset - Contra.com Bayangin kamu lagi cari kerja, tapi bukannya masukin lamaran ke kantor HRD yang mukanya kayak lagi abis marah sama printer, kamu malah bikin mini-website kece yang isinya semua proyek keren yang pernah kamu kerjain. Nah, Contra itu platform yang ngebantu kamu bikin “etalase digital” kayak gitu, tempat kamu bisa pajang skill, portofolio, sampai nulis layanan yang bisa kamu tawarin ke calon klien. Serius, ini kayak LinkedIn ketemu Behance tapi ditambah fitur invoice. Biar nggak cuma denger dari omongan doang, nih link-nya kalau kamu mau kepoin langsung: https://contra.com/ . Yang paling bikin adem hati: beda sama platfform freelance lain yang sering potong fee kayak tukang parkir yang muncul entah dari mana, Contra tuh nggak ambil komisi sama sekali. Jadi 100% uang dari klien ya masuk ke kamu. Ibaratnya kamu kerja freelance langsung sama klien, ngopi bareng, ngobrol, deal, tapi semua urusan ribet kayak kontrak, invoice, sampe pembayaran udah disediain sistemnya. Udah kayak punya manajer pribadi tapi nggak minta persen. Contra ini juga bukan cuma tempat kamu ngelamar kerja, tapi lebih ke tempat kamu dipromosikan sebagai profesional. Serius, profil kamu bisa dibikin sekeren halaman "About Me" di website pribadi, lengkap sama bagian "Services", kayak daftar menu warung makan tapi isinya skill kamu. Bisa nambah testimoni klien juga, biar makin credible kayak warung yang udah viral di TikTok. Jadi kalau kamu udah capek ngelamar satu-satu tapi nggak dilirik-lirik, mungkin saatnya kamu ganti strategi. Bangun personal brand, tampil kece, dan biarin klien yang datengin kamu. Contra bisa jadi tempat mulai yang solid buat itu. Fitur Utama Contra Riset - Fitur Utama Contra tuh kayak toolkit lengkap buat kamu yang pengin kerja freelance tanpa ribet. Bayangin kamu punya satu tempat yang bisa ngatur semuanya, dari nunjukin portofolio sampai kirim invoice ke klien. Nah, fitur-fitur di Contra ini beneran didesain buat ngebantu kamu fokus ke kerjaan, bukan ke urusan administratif yang makan waktu. Jadi ini dia fitur utamanya Contra: 1. Portofolio Interaktif Kamu bisa bikin halaman portofolio yang keren dan gampang dibaca. Bisa masukin hasil kerja kamu kayak project frntend (misalnya desain UI, landing page, atau app React), dan bisa dikasih link langsung ke live project atau repo GitHub. Jadi klien bisa langsung lihat hasil nyatanya, bukan cuma janji-janji manis doang. 2. Services (Jasa Freelance) Di Contra, kamu bisa nulis jasa kayak kamu bikin menu jualan. Misalnya: “Convert Figma to Responsive Website” atau “Build Landing Page dengan Tailwind dan React”. Kamu juga bisa tentuin harga, durasi pengerjaan, dan deskripsi jelas. Klien tinggal klik dan hire kamu, kayak belanja di e-commerce. 3. Tanpa Komisi Ini yang paling bikin senyum: Contra nggak motong penghasilan kamu. Berapa pun yang dibayar klien, semuanya langsung masuk ke dompet kamu. Jadi kamu bisa lebih tenang pas pasang harga, nggak perlu markup cuma buat nutupin potongan platfform. 4. Sistem Pembayaran & Kontrak Otomatis Begitu ada klien yang mau hire kamu, sistemnya udah nyiapin kontrak otomatis dan metode pembayaran yang aman. Jadi kamu nggak perlu ribet bikin dokumen legal sendiri. Setelah kerjaan selesai, tinggal klik “Complete” dan dana langsung ditransfer. Praktis banget. 5. Testimoni & Endorsement Kalau klien puas, mereka bisa kasih testimonial di profil kamu. Ini bisa bantu banget ningkatin kredibilitas kamu, ibaratnya kayak dapet referensi kerja dari mantan bos, tapi versi online. Kalau kamu frntend developer yang pengin tampil profesional dan tetap simpel, fitur-fitur ini bisa bantu kamu kelihatan lebih meyakinkan di mata klien, walaupun baru mulai di dunia freelance. Mengapa Contra Relevan untuk Frontend Developer Riset - Mengapa Relevan Kalau kamu kerja di bidang frontend, kamu pasti ngerti pentingnya tampilan dan pengalaman pengguna, nggak cuma di website yang kamu bikin, tapi juga di cara kamu nunjukin skill kamu ke orang lain. Nah, Contra tuh cocok banget buat kamu yang mikir kayak gitu, karena platform ini ngasih ruang buat tampil sebagai profesional yang rapi dan berkelas, bukan sekadar “freelancer cari kerja”. Jadi ini dia mengapa relevan buat kamu: Show Your Work, Bukan Cuma Ngaku Bisa Di Contra, kamu bisa langsung pajang hasil kerja kamu, entah itu desain UI yang kamu ubah jadi halaman HTML/CSS yang smooth, atau landing page yang kamu bangun dari nol. Ini tuh lebih powerful dibanding cuma bilang “saya bisa bikin website”, karena klien bisa langsung lihat bukti nyata. Cocok Buat Proyek Kecil Maupun Besar Banyak klien di Contra nyari jasa yang pas banget sama skill frontend: Convert desain ke kodeBikin landing page interaktifBangun komponen dengan ReactOptimasi performa dan UI Dan kamu bisa bikin layanan yang spesifik sesuai keahlian kamu. Jadi nggak perlu nunggu lowongan muncul, kamu yang bikin tawarannya duluan. Buat yang Mau Bangun Brand Personal Kalau kamu pengin dikenal bukan cuma sebagai "orang yang bisa ngoding", tapi sebagai “frntend specialist yang ahli bikin UI clean dan mobile-friendly”, Contra bisa bantu kamu branding. Profil kamu itu kayak CV interaktif, semakin rapi, semakin dipercaya. Lebih Enak Komunikasi Karena Contra lebih berasa kayak platfform kolaborasi daripada marketplace ramai, komunikasi dengan klien terasa lebih personal. Kamu nggak harus bersaing sama ratusan orang lain cuma buat dapet satu project. Kalau kamu punya profil yang jelas dan service yang spesifik, klien bakal datang sendiri. Singkatnya, Contra itu tempat yang tepat buat kamu nunjuin kualitas kerjaan, bukan cuma ngejar rating dan bidding murahan. Cocok banget buat kamu yang pengin dikenal karena skill, bukan karena ngasih harga paling murah. Kelebihan & Kekurangan Menggunakan Contra Riset - Kelebihan & Kekurangan Nggak ada platform yang sempurna, dan Contra juga begitu. Tapi biar kamu bisa ambil keputusan dengan lebih yakin, yuk kita bahas sisi plus-minusnya, kayak lagi review tempat kerja baru sebelum masukin lamaran. Jadi kita mulai dari kelebihan dulu: Kelebihan 1. Bebas Komisi Ini yang paling kerasa: semua penghasilan kamu 100% masuk ke kamu, nggak dipotong fee platform. Ibaratnya kayak kamu digaji penuh tanpa potongan pajak kantor, nikmat banget buat freelancer. 2. Profil Keren & Portofolio Interaktif Contra bantu kamu tampil profesional. Profil kamu tuh kayak CV + website pribadi versi instan. Buat kamu yang nggak sempet bikin website portofolio sendiri, ini sangat membantu. 3. Bisa Buat Layanan Sendiri Kamu nggak perlu nunggu job ditawarkan. Kamu bisa pasang jasa kamu sendiri, lengkap dengan harga dan deskripsi. Klien tinggal pilih kayak beli jasa di e-commerce. 4. Workflow Lebih Rapi Kontrak otomatis, pembayaran aman, dan update project diatur semua dalam satu tempat. Nggak perlu bolak-balik ke Google Docs + email + invoice manual. Semua udah diringkas di satu dashboard. Kekurangan 1. Belum Seramai Platform Lain Karena masih tergolong baru, jumlah klien di Contra belum sebanyak di platfform besar kayak Upwork atau Fiverr. Tapi ini juga bisa jadi kelebihan: kompetisinya nggak segila di sana. 2. Fokus ke Kualitas, Bukan Kuantitas Contra lebih cocok buat kamu yang pengin dapet klien serius dan proyek proper. Kalau kamu nyari kerjaan harian/cepetan tiap hari kayak "kerjain logo 1 jam selesai", mungkin platform ini terasa lebih slow. 3. Belum Terlalu Familiar di Indonesia Mayoritas pengguna dan klien masih dari luar negeri. Jadi, komunikasi biasanya pakai bahasa Inggris. Tapi buat kamu yang pengin pasar global, ini justru jadi peluang. Contra itu bukan tempat buat "siapa cepat dia dapat", tapi lebih ke tempat buat “siapa yang niat dan punya kualitas, dia yang dilihat”. Jadi kalau kamu niat bangun karier freelance jangka panjang, platform ini worth banget buat dicoba. Tips Maksimalin Contra untuk Frontend Developer Riset - Tips Maksimalin Jadi kamu udah daftar di Contra, udah punya profil, tapi gimana caranya biar makin stand out dan dapet klien? Nah, berikut beberapa tips biar kamu gak cuma numpang lewat di Contra, tapi bisa benar-benar dimanfaatin buat bangun karier freelance kamu: 1. Anggap Profil Kamu Kayak CV + Landing Page Jangan asal isi profil. Bayangin klien itu HRD yang lagi buka portofolio kamu, cuma dalam bentuk digital. Gunakan foto profesional, bio yang singkat tapi ngejelasin kamu ahli di mana, dan highlight skill yang paling kamu kuasai (misalnya: “Frntend Developer fokus di React & Tailwind, pengalaman 3 tahun handle landing page dan dashboard UI”). 2. Bikin Service yang Jelas dan Menjual Daripada nulis “Frntend Developer untuk berbagai kebutuhan”, lebih baik spesifikin servicenya. Contoh: “Buat landing page responsif dengan Tailwind”“Convert Figma ke HTML/CSS + animasi GSAP”“Bangun UI React dari 0 (Next.js, Tailwind, HeadlessUI)” Gunakan bahasa yang dimengerti klien non-teknis juga, supaya mereka ngerti value-nya. 3. Upload Portofolio yang Real & Terbaik Masukin proyek-proyek yang beneran pernah kamu kerjain, walaupun itu side project atau latihan. Jelaskan context-nya: Tantangannya apa?Stack yang kamu pakai?Apa hasil akhirnya? Kalau kamu pernah ngebuat landing page untuk brand fiktif waktu latihan, itu pun tetap bisa ditulis, asal dijelasin sebagai “personal project”. Klien lebih suka lihat sesuatu daripada nol sama sekali. 4. Minta Testimoni dari Klien Lama Pernah kerja freelance di luar Contra? Hubungi klien lamamu dan minta testimoni. Kamu bisa masukin testimoni itu ke profil kamu di Contra. Trust factor naik banget kalau ada feedback real dari orang lain. 5. Rutin Update dan Aktif Contra punya algoritma juga, profil yang aktif, sering update, dan cepat respon ke calon klien itu punya peluang lebih besar buat muncul. Jadi jangan cuma daftar, terus ditinggal. Luangin wakktu seminggu sekali buat cek profil, bales pesan, atau update service. 6. Promosiin Profil Contra Kamu Contra kasih kamu URL profil khusus, kayak semacam portfolio link. Share itu di media sosial, di bio LinkedIn, atau kalau kamu join komunitas developer, bisa sekalian promosiin jasa kamu. Anggap aja kamu punya “mini website” sendiri, dan kamu lagi bangun traffic ke sana. Dengan strategi yang tepat, Contra bisa jadi alat bantu kamu bukan cuma buat dapet duit tambahan, tapi juga buat bangun reputasi profesional sebagai frontend developer yang terpercaya. Studi Banding Singkat: Contra vs Platform Freelance Lainnya Riset - Study Banding Biar kamu bisa lihat lebih jelas posisi Contra di antara platfform freelance lain, kita coba bandingin sama beberapa nama yang mungkin udah familiar kayak Fiverr, Upwork, dan Freelancer.com. Anggap aja ini kayak kamu lagi milih tools buat coding, semua bisa dipakai, tapi ada yang lebih cocok tergantung kebutuhan. Jadi yuk kita bandingin: 1. Contra vs Fiverr Fiverr itu lebih cocok buat job cepat dan sekali pakai. Klien datang cari jasa yang udah template-an.Contra kasih kamu ruang buat branding. Kamu bisa nyusun service-mu sendiri dan tampil sebagai independen professional, bukan cuma "penjual jasa". Analogi: Fiverr itu kayak kamu ngoding pakai plugin siap pakai, Contra itu kayak kamu bikin komponen custom sendiri biar scalable. 2. Contra vs Upwork Upwork banyak proyek, tapi persaingannya brutal. Kadang kamu harus ngebidding dengan harga rendah dulu biar dapet klien.Contra justru kasih kamu kendali penuh atas harga. Gak ada sistem bidding. Kamu pasang harga yang kamu rasa layak, dan klien bakal datang kalau mereka butuh kualitas. Analogi: Upwork itu kayak nyari kerjaan via job board, Contra lebih kayak kamu buka studio sendiri dan orang datang nyari kamu. 3. Contra vs Freelancer.com Freelancer.com seringkali terlalu umum dan rame. Banyak proyek murahan yang kurang cocok buat kamu yang punya spesialisasi frontend.Contra lebih curated, fokus ke kreator dan digital professionals. Lingkungannya lebih “adem” dan lebih profesional. Analogi: Freelancer.com itu kayak pasar loak, banyak pilihan tapi mesti pintar milih. Contra lebih kayak toko design premium, lebih spesifik dan tertarget. Kesimpulan Singkat Kalau ngomongin soal perbandingan, masing-masing platform punya karakteristik dan kelebihannya sendiri. Contra, misalnya, punya keunggulan utama karena nggak ngambil fee sama sekali. Kamu bisa pasang service sendiri dan fokus bangun personal brand. Ini cocok banget buat frontend developer yang serius pengin dikenal sebagai spesialis, bukan sekadar tukang ngoding. Sementara itu, Fiverr ngambil sekitar 20% fee, tapi cocok buat kamu yang pengin dapet job cepat dan praktis, karena sistemnya memang jual jasa sekali jadi. Upwork dan Freelancer.com biasanya ambil fee antara 10 sampai 20%, dan pakai sistem bidding, jadi kamu harus rebutan proyek sama freelancer lain. Dua platfform ini lebih pas buat kamu yang udah full-time freelance dan siap bersaing. Jadi, kalau kamu pengin jadi frntend developer yang bukan cuma "bisa ngoding", tapi juga pengin dikenal sebagai spesialis yang punya personal brand, Contra bisa banget jadi pilihan jangka panjang buat kamu. Rekomendasi Kelas Contra Gratis & Premium Buat kamu yang udah penasaran sama Contra dan pengin langsung ngulik lebih dalam, tenang... ada kelasnya! Bukan cuma asal tahu platform-nya, tapi kamu juga bakal diajarin cara ngatur profil, bikin layanan, sampe strategi dapetin klien. Jadi nggak cuma modal nekat, tapi ada ilmunya juga. FREE Riset - BuildWithAngga Free Online Course “Yang penting mulai dulu, walau gratisan. Ilmu tetep masuk!”. Kelas ini cocok banget buat kamu yang baru mau nyemplung ke dunia freelance dan pengin tau gimana cara kerja remote, bikin portofolio kece, dan dapetin klien via Contra, tanpa harus jago ngoding. Ini entry point yang pas buat pemanasan. Contra FREE Premium Riset - BuildWithAngga Premium Online Course “Kalau gratisan itu gerbangnya, premium ini jurus dewa-nya.”. Di kelas ini kamu bakal diajak mikir dan ngatur strategi kayak freelancer pro. Gimana caranya bangun branding pribadi, jual jasa yang laku keras, dan nyusun strategi pricing biar cuan maksimal. Cocok buat kamu yang udah punya sedikit pengalaman, dan sekarang pengin naik level. Contra Premium Penutup Riset - Penutup Masuk ke dunia freelance itu ibaratnya kayak pindah dari kantor tetap ke remote office milik sendiri. Kamu yang atur wakktu, kamu yang tentuin harga, dan kamu juga yang harus jaga reputasi. Nah, Contra hadir buat bantu kamu jadi frntend developer freelance yang gak cuma dapet klien, tapi juga bisa bangun personal brand tanpa harus ribet mikirin fee potongan. Platfform ini emang belum seramai nama-nama besar lain, tapi justru itu yang bikin peluangmu lebih kelihatan. Kalau kamu niat bangun portofolio, pasang layanan yang jelas, dan aktif promosiin diri kamu, Contra bisa jadi tempat kamu tumbuh secara profesional. Semangat!

Kelas Tutorial Node JS 22: Bikin API Fitur Upload Photo dengan Busboy di BuildWithAngga

Tutorial Node JS 22: Bikin API Fitur Upload Photo dengan Busboy

Buat kamu yang ingin membangun website sewa rumah dari nol, memilih vanilla Node.js sebagai fondasi backend adalah keputusan yang tepat. Tanpa bantuan framework seperti Express, kamu jadi benar-benar paham cara kerja HTTP server, gimana request dan response diproses, dan bagaimana data bisa ditransfer lewat API. Ini penting banget terutama kalau kamu ingin bikin backend yang ringan, cepat, dan bisa disesuaikan penuh sesuai kebutuhan bisnis kamu. Selain itu, vanilla Node.js juga cocok banget dipakai untuk proyek yang skalanya masih kecil sampai menengah. Kamu punya kontrol penuh terhadap routing, middlewaare, hingga pengolahan file. Jadi kalau nanti butuh scaling atau ingin migrasi ke arsitektur yang lebih besar, kamu sudah punya fondasi yang kuat. Manfaat Utama Vanilla Node.js: Maintainable dan Scalable Salah satu keuntungan paling jelas ketika membangun backend dengan vanilla Node.js adalah kemudahan untuk membuat struktur yang maintainable. Kamu bebas bikin arsitektur yang modular, misalnya pisahin logic per folder seperti controller, service, middleware, hingga utilitas umum. Karena enggak bergantung pada library pihak ketiga, kamu juga enggak perlu terlalu khawatir dengan masalah compatibility antar versi atau update mendadak. Dari sisi scalability, Node.js dikenal sangat efisien dalam menangani banyak koneksi secara bersamaan karena sifatnya non-blocking dan event-driven. Bahkan tanpa Express, kamu tetap bisa membuat server yang siap menangani beban trafik tinggi, selama struktur kodenya dirancang dengan baik. Artinya, aplikasi kamu tetap jalan mulus walau pengguna bertambah banyak, apalagi kalau nanti didukung dengan deployment modern seperti Docker atau load balancer. Fokus Artikel Ini: Upload Foto Menggunakan Busboy + Postman Nah, di artikel ini kita bakal bahas salah satu fitur penting dalam proyek website sewa rumah: upload foto properti ke backend. Dalam dunia nyata, pemilik rumah pasti ingin tampilkan gambar rumah mereka supaya calon penyewa bisa lebih yakin sebelum booking. Karena itu, fitur upload foto bukan lagi tambahan, tapi sudah jadi fitur utama. Kita akan menggunakan Busboy, yaitu library kecil di Node.js yang sangat efektif buat parsing form-data, terutama saat user mengirimkan file lewat HTTP POST. File foto yang dikirim akan kita simpan langsung ke file system dalam folder khusus, tanpa perlu database. Dan sebagai pengujian, kita akan pakai Postman untuk mencoba kirim file dan lihat apakah file-nya berhasil disimpan. Dari proses ini, kamu bisa belajar bagaimana backend menerima file, menyimpannya, dan memberikan respons yang sesuai. Cara Install Node.js di Windows dan Membuat Proyek Pertama Backend API Sewa Rumah Langkah pertama yang perlu kamu lakukan adalah menginstall Node.js di Windows. Silakan buka situs resmi https://nodejs.org, lalu pilih versi LTS (Long Term Support) dan klik download. Setelah file selesai diunduh, jalankan installer dan ikuti langkah-langkah instalasinya seperti biasa hingga selesai. Setelah instalasi selesai, buka Command Prompt lalu ketik perintah berikut untuk memastikan bahwa Node.js dan npm sudah terpasang dengan benar: node -v npm -v Jika muncul versi dari Node.js dan npm, artinya kamu sudah siap membuat project backend pertamamu. Sekarang kita buat folder baru untuk proyek sewa rumah: mkdir sewa-rumah-api cd sewa-rumah-api Inisialisasi project Node.js dengan perintah: npm init -y Setelah itu, buat file utama server dengan nama index.js: // index.js const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'API Sewa Rumaah berjalan lancar' })); }); server.listen(3000, () => { console.log('Server berjalan di <http://localhost:3000>'); }); Lalu jalankan server dengan perintah berikut di terminal: node index.js Jika tidak ada error, maka akan muncul tulisan Server berjalan di http://localhost:3000. Itu artinya kamu sudah berhasil menjalankan server backend pertama kamu menggunakan vanilla Node.js, dan backend API sewa rumah siap kamu lanjutkan pengembangannya. Struktur Folder Proyek Backend Sewa Rumah (Vanilla Node.js) Untuk menjaga proyek tetap rapi, scalable, dan mudah dikembangkan, sangat disarankan membuat struktur folder yang jelas sejak awal. Walaupun kita tidak menggunakan framework seperti Express, bukan berarti kita menulis semua logic di satu file. Kita tetap bisa menyusun kode secara modular menggunakan pendekatan berikut. Contoh Struktur Folder sewa-rumah-api/ ├── controllers/ │ └── house.controller.js ├── data/ │ └── houses.json ├── middlewares/ │ └── upload.middleware.js ├── models/ │ └── house.model.js ├── routes/ │ └── house.routes.js ├── schemas/ │ └── house.schema.js ├── services/ │ └── house.service.js ├── uploads/ │ └── (folder kosong untuk menyimpan file foto) ├── utils/ │ └── generate-id.js ├── index.js ├── package.json Penjelasan Masing-Masing Folder controllers/ Berisi file yang menangani request dari user dan mengatur response-nya. Contohnya house.controller.js untuk handle upload foto, mengambil daftar rumah, atau menambahkan rumah baru. data/ Digunakan untuk menyimpan data sementara dalam format JSON sebelum kamu pakai database. Misalnya houses.json menyimpan daftar rumah yang bisa disewa. middlewares/ Berisi fungsi middleware yang dijalankan sebelum request masuk ke controller. Misalnya upload.middleware.js untuk menangani proses upload file dengan Busboy. models/ Digunakan untuk mendefinisikan struktur data seperti house.model.js. File ini bisa berisi constructor class atau struktur awal jika kamu pakai database nanti. routes/ Berisi logic pemetaan path URL ke fungsi controller secara manual. Contohnya house.routes.js mengatur endpoint /api/houses dan arahkan ke controller yang sesuai. schemas/ Berisi validasi data menggunakan library seperti Zod. Misalnya house.schema.js untuk validasi saat user menambahkan rumah baru agar inputnya sesuai aturan. services/ Berisi logic utama aplikasi seperti membaca file JSON, menyimpan data, atau filtering. house.service.js contohnya untuk mengambil semua rumah dari file JSON atau menambah data baru. uploads/ Folder kosong yang digunakan untuk menyimpan file hasil upload dari user. Misalnya foto rumah, yang diunggah melalui Postman akan masuk ke sini. utils/ Berisi fungsi bantu umum, misalnya generate-id.js untuk membuat ID unik setiap kali data baru ditambahkan. index.js File utama yang menjalankan HTTP server dan mengatur permintaan masuk, seperti menentukan rute dan memanggil middleware. Struktur seperti ini akan sangat membantu kamu saat proyek mulai bertambah kompleks. Setiap folder punya tanggung jawabnya sendiri, sehingga tim kamu pun bisa bekerja secara paralel tanpa mengganggu bagian lain. Cocok banget buat kamu yang mau bikin backend sederhana tapi profesional tanpa framework. Penjelasan File-Based Database Menggunakan .json untuk Backend API Sewa Rumah Dalam pengembangan backend API, terutagma saat proyek masih di tahap awal atau skala kecil, kita belum tentu langsung membutuhkan database besar seperti MySQL, MongoDB, atau PostgreSQL. Sebagai gantinya, kita bisa menggunakan pendekatan file-based database. Artinya, data akan disimpan dalam bentuk file .json di dalam folder proyek. File .json ini berfungsi mirip seperti tabel dalam database, isinya berupa array of objects yang merepresentasikan data — misalnya daftar rumah yang tersedia untuk disewa. Kelebihannya: setup sangat sederhana, tidak perlu install database server, dan bisa langsung digunakan dengan fs module dari Node.js. Metode ini cocok banget untuk belajar, prototyping, atau membangun MVP (Minimum Viable Product). Tapi perlu diingat, untuk kebutuhan produksi dengan banyak user dan skala besar, sebaiknya tetap gunakan database yang sesungguhnya. Cara Menggunakan File-Based Database di Proyek Sewa Rumah Langkah pertama, kamu buat file JSON di dalam folder data. Misalnya nama filenya houses.json dengan isi awal seperti ini: [] Isi array kosong karena nanti kita akan menambahkan rumah lewat endpoint POST. Lalu buat file service house.service.js di dalam folder services/ untuk mengelola proses baca dan tulis ke file tersebut. // services/house.service.js const fs = require('fs'); const path = require('path'); const { v4: uuidv4 } = require('uuid'); // opsional, bisa buat id unik kalau pakai library ini const filePath = path.join(__dirname, '../data/houses.json'); function readHouses() { const fileContent = fs.readFileSync(filePath, 'utf-8'); return JSON.parse(fileContent); } function saveHouses(houses) { fs.writeFileSync(filePath, JSON.stringify(houses, null, 2)); } function getAllHouses() { return readHouses(); } function addHouse(newHouse) { const houses = readHouses(); const houseWithId = { id: uuidv4(), // buat ID unik ...newHouse }; houses.push(houseWithId); saveHouses(houses); return houseWithId; } module.exports = { getAllHouses, addHouse }; Selanjutnya, buat controller untuk handle request dari user. Misalnya kita buat house.controller.js di folder controllers/. // controllers/house.controller.js const { getAllHouses, addHouse } = require('../services/house.service'); function handleGetHouses(req, res) { const houses = getAllHouses(); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(houses)); } function handleCreateHouse(req, res) { let body = ''; req.on('data', chunk => { body += chunk; }); req.on('end', () => { const data = JSON.parse(body); const newHouse = addHouse(data); res.writeHead(201, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(newHouse)); }); } module.exports = { handleGetHouses, handleCreateHouse }; Terakhir, sambungkan semuanya lewat index.js: // index.js const http = require('http'); const url = require('url'); const { handleGetHouses, handleCreateHouse } = require('./controllers/house.controller'); const server = http.createServer((req, res) => { const parsedUrl = url.parse(req.url, true); const method = req.method; const pathname = parsedUrl.pathname; if (method === 'GET' && pathname === '/api/houses') { return handleGetHouses(req, res); } if (method === 'POST' && pathname === '/api/houses') { return handleCreateHouse(req, res); } res.writeHead(404, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Route not found' })); }); server.listen(3000, () => { console.log('Server berjalan di <http://localhost:3000>'); }); Kalau semuanya sudah kamu buat, kamu bisa uji coba endpoint ini di Postman. Lakukan GET untuk ambil semua rumah dan POST untuk menambah rumah baru. Data akan tersimpan otomatis di file houses.json. Dengan pendekatan ini, kamu bisa belajar alur lengkap backend API tanpa perlu mengatur database yang kompleks. Sederhaana tapi powerful buat latihan dan membangun proyek real yang kecil. Install dan Gunakan Busboy untuk Upload Foto Rumah di Backend API Sewa Rumah Setelah API backend kamu berhasil membaca dan menulis data ke file .json, sekarang kita akan menambahkan fitur baru: upload foto rumah. Dalam fitur ini, foto akan diunggah oleh user melalui Postman (atau frontend nantinya), lalu disimpan di folder uploads/, sedangkan file name dan path-nya akan disimpan di file .json sebagai referensi. Kita akan menggunakan Busboy, yaitu library ringan dan efisien untuk menangani multipart/form-data (khususnya saat user mengunggah file). Langkah 1: Install Busboy Buka terminal di folder proyek keamu, lalu jalankan perintah: npm install busboy Langkah 2: Buat Middleware Upload File Buat folder middlewares/ kalau belum ada. Di dalamnya, buat file baru bernama upload.middleware.js. // middlewares/upload.middleware.js const Busboy = require('busboy'); const fs = require('fs'); const path = require('path'); function handlePhotoUpload(req, res, callback) { const busboy = new Busboy({ headers: req.headers }); let fileName = ''; let uploaded = false; busboy.on('file', (fieldname, file, filename) => { const uploadPath = path.join(__dirname, '../uploads', filename); fileName = filename; uploaded = true; file.pipe(fs.createWriteStream(uploadPath)); file.on('end', () => { callback(null, fileName); }); }); busboy.on('finish', () => { if (!uploaded) { callback(new Error('No file uploaded')); } }); req.pipe(busboy); } module.exports = { handlePhotoUpload }; Langkah 3: Perbarui Service dan Controller Buka atau buat file house.service.js di dalam folder services/. Tambahkan logic untuk menyimpan nama file ke file JSON. // services/house.service.js const fs = require('fs'); const path = require('path'); const { v4: uuidv4 } = require('uuid'); const filePath = path.join(__dirname, '../data/houses.json'); function readHouses() { const data = fs.readFileSync(filePath, 'utf-8'); return JSON.parse(data); } function saveHouses(houses) { fs.writeFileSync(filePath, JSON.stringify(houses, null, 2)); } function addHouseWithPhoto(photoFileName) { const houses = readHouses(); const newHouse = { id: uuidv4(), title: 'Rumah Baru', photo: `/uploads/${photoFileName}` }; houses.push(newHouse); saveHouses(houses); return newHouse; } module.exports = { addHouseWithPhoto, readHouses }; Selanjutnya buka house.controller.js di folder controllers/ dan tambahkan logic untuk menangani upload foto. // controllers/house.controller.js const { addHouseWithPhoto, readHouses } = require('../services/house.service'); const { handlePhotoUpload } = require('../middlewares/upload.middleware'); function handleGetHouses(req, res) { const houses = readHouses(); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(houses)); } function handleUploadHousePhoto(req, res) { handlePhotoUpload(req, res, (err, filename) => { if (err) { res.writeHead(400, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify({ message: err.message })); } const newHouse = addHouseWithPhoto(filename); res.writeHead(201, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Rumah berhasil ditambahkan dengan foto', data: newHouse })); }); } module.exports = { handleGetHouses, handleUploadHousePhoto }; Langkah 4: Update index.js Buka file index.js di root proyek, lalu arahkan endpoint POST ke handler upload foto: // index.js const http = require('http'); const url = require('url'); const { handleGetHouses, handleUploadHousePhoto } = require('./controllers/house.controller'); const server = http.createServer((req, res) => { const parsedUrl = url.parse(req.url, true); const method = req.method; const pathname = parsedUrl.pathname; if (method === 'GET' && pathnamee === '/api/houses') { return handleGetHouses(req, res); } if (method === 'POST' && pathname === '/api/houses/upload-photo') { return handleUploadHousePhoto(req, res); } res.writeHead(404, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Route not found' })); }); server.listen(3000, () => { console.log('Server berjalan di <http://localhost:3000>'); }); Cara Uji Coba API Upload Foto Rumah dengan Postman (Multipart Form Data) Setelah backend kamu selesai dibuat menggunakan Node.js dan Busboy, sekarang saatnya kita menguji apakah fitur upload foto rumah berjalan dengan benar. Untuk itu, kita akan menggunakan Postman, sebuah tool populer untuk testing API. Tujuan dari uji coba ini adalah mengirim file gambar (misalnya foto rumah) ke endpoint /api/houses/upload-photo, dan memastikan backend menyimpannya ke folder uploads/, serta mencatat informasi file tersebut di file houses.json. Persiapan Sebelum Testing Pastikan kamu sudah melakukan hal berikut: Jalankan server dengan perintah node index.jsFolder uploads/ sudah ada di root proyekFile houses.json sudah tersedia di dalam folder data/ dan berisi array kosong [] Langkah Uji Coba Upload Foto Rumah di Postman Buka aplikasi Postman dan ikuti langkah berikut: Pilih metode POST Masukkan URL endpoint kamu, contoh: <http://localhost:3000/api/houses/upload-photo> Klik tab Body → pilih opsi form-data Tambahkan form field dengan key: Key: photo Type: File Value: [pilih gambar dari komputermu] Pastikan field type kamu adalah File, bukan Text Klik tombol Send Hasil yang Diharapkan Jika semuanya berjalan dengan benar, kamu akan menerima response JSON seperti ini: { "message": "Rumah berhasil ditambahkan dengan foto", "data": { "id": "3e2237b0-2b2e-4d5f-9a8b-d6bd3e8e456c", "title": "Rumah Baru", "photo": "/uploads/foto-rumah.jpg" } } Cek folder uploads/ — harusnya ada file foto-rumah.jpg atau sesuai dengan file yang kamu upload. Buka file data/houses.json — datanya akan bertambah seperti ini: [ { "id": "3e2237b0-2b2e-4d5f-9a8wwwb-d6bd3e8e456c", "title": "Rumah aaBaru", "photo": "/uploads/foto-rumaaah.jpg" } ] Penutup dan Saran untuk Backend Developer Pemula Belajar membangun backend dari nol dengan vanilla Node.js adalah langkah awal yang luar biasa. Kamu jadi paham cara kerja HTTP server, bagaimana cara upload file tanpa bantuan framework, serta bagaimana menyimpan data di file .json secara manual. Ini adalah pondasi penting sebelum kamu melangkah ke tahap yang lebih kompleks seperti menggunakan Express, database relasional, autentikasi JWT, hingga deployment ke cloud. Tapi kadang, belajar sendiri bisa terasa lambat dan membingungkan. Karena itu, belajar langsung bersama mentor expert di BuildWithAngga bisa jadi jalan pintas terbaik buat kamu yang ingin mempercepat karier sebagai backend developer—khususnya yang ingin bekerja remote. Di BuildWithAngga, kamu bisa belajar hal teknis langsung dari para engineer berpengalaman, tidak hanya teori tapi juga praktik proyek nyata seperti: API backend untuk aplikasi sewa rumah, POS system, dan marketplaceValidasi data profesional dengan ZodUpload file dengan keamananeeeStruktur folder yang scalable untuk kerja timSimulasi kerja remote seperti di startup beneran Dan yang paling penting, kamu akan dibimbing untuk menyiapkan portofolio dan kemampuan teknis yang dibutuhkan perusahaan luar negeri. Jadi bukan sekadar belajar ngoding, tapi benar-benar diarahkan supaya siap kerja remote dan punya penghasilan yang lebih besar dari rumah. Kalau kamu serius ingin jadi backend developer yang siap kerja remote, jangan hanya belajar sendirian. Yuk, gabung belajar bareng mentor expert di BuildWithAngga. Siapkan masa depanmu mulai hari ini. 🚀

Kelas Tutorial Node JS Pemula Belajar Menerapkan File Based Database Projek Website Sewa Mobil di BuildWithAngga

Tutorial Node JS Pemula Belajar Menerapkan File Based Database Projek Website Sewa Mobil

Di era digital seperti sekarang, hampir semua jenis bisnis dituntut untuk hadir secara online. Mulai dari toko kecil sampai perusahaan besar, semua berlomba-lomba membangun sistem digital untuk menjangkau pelanggan lebih luas, meningkatkan efisiensi operasional, dan tentu saja menaikkan pendapatan. Misalnya gini, bayangin kamu punya bisnis penyewaan mobil. Kalau kamu hanya mengandalkan pelanggan yang datang langsung ke kantor atau tahu dari spanduk di pinggir jalan, jangkauannya terbatas banget. Tapi kalau kamu punya sistem online yang memungkinkan orang booking mobil lewat website dari rumah, potensi pasarnya langsung meluas ke mana-mana. Bahkan orang luar kota yang mau liburan pun bisa pesan lebih awal. Ini otomatis bikin potensi revenue perusahaan naik. Nah, untuk bikin sistem seperti itu, kita butuh teknologi backend yang kuat, stabil, dan bisa berkembang seiring pertumbuhan bisnis. Di sinilah Node.js masuk sebagai pilihan yang tepat. Node.js adalah lingkungan runtime JavaScript yang cepat, ringan, dan punya ekosistem library yang luas banget. Karena sifatnya non-blocking dan event-driven, Node.js cocok digunakan untuk aplikasi yang butuh performa tinggi dan skalabilitas, seperti sistem booking online atau dashboard manajemen armada mobil. Selain itu, Node.js juga gampang dipelajari, terutama buat kamu yang sudah familiar dengan JavaScript di frontend. Jadi proses belajarnya lebih cepat dan konsisten dari sisi bahasa pemrograman. Belajar Menerapkan File Based Database untuk Backend Sewa Mobil Pada artikel kali ini, kita akan bahas gimana cara bikin backend sederhana untuk katalog sewa mobil menggunakan pendekatan file based database. Konsep ini cocok banget buat pemula yang baru belajar backend dan belum siap menggunakan sistem database yang kompleks seperti MySQL atau MongoDB. File based database artinya data akan disimpan di dalam file—biasanya dalam format JSON—dan kita akan membaca, menulis, serta mengubah file tersebut menggunakan kode program. Meskipun tidak sekuat database sunguhan dalam hal kecepatan dan fleksibilitas, metode ini sangat pas digunakan untuk kebutuhan skala kecil atau saat kita sedang membangun prototype. Misalnya kita ingin bikin website sewa mobil yang menampilkan daftar mobil yang tersedia, lengkap dengan nama, merek, tahun produksi, dan harga sewa per hari. Semua informasi ini bisa disimpan dalam satu file .json dan dibaca oleh sistem Node.js saat dibutuhkan. Keuntungan pendekatan ini adalah sederhana, tidak perlu setup database server, dan kita bisa langsung fokus memahami alur backend, seperti membaca data, memfilter berdasarkan query, dan mengembalikan respons ke client dalam format JSON. Tapi tentu ada juga keterbatasannya, misalnya performa yang menurun kalau datanya makin besar, atau data tidak bisa diakses secara paralel secara efisien. Intinya, file based database adalah titik awal yang bagus buat belajar struktur backend sederhana dan memahami dasar-daesar bagaimana data bekerja di dalam aplikasi web. Dari sini, kamu bisa lanjut ke tahapan yang lebih kompleks, seperti menggunakan database relasional atau NoSQL di proyek-proyek selanjutnya. Di bagian berikutnya nanti, kita akan coba bangun struktur backendnya secara bertahap. Tapi yang pasti, kamu bakal dapet pengalaman langsung gimana cara kerja sistem backend dari nol. Cara Install Node.js Framework Terbaru di Windows Sebelum kita mulai bikin proyek backend, hal paling pertama yang perlu dilakukan tentu aja install Node.js dulu di komputermu. Kalau kamu pengguna Windows, tenang aja—caranya cukup gampang dan bisa kamu selesaikan dalam beberapa menit. Langkah pertama, buka browser dan pergi ke website resmi Node.js di alamat https://nodejs.org/. Di halaman utama kamu akan lihat dua tombol besar—satu untuk versi LTS (Long-Term Support) dan satu lagi versi Current. Disarankan kamu pilih versi LTS karena lebih stabil untuk proyek jangka panjang. Setelah file installer (.msi) selesai diunduh, jalankan file tersebut. Proses instalasi akan memandu kamu lewat beberapa langkah. Tinggal klik "Next" saja sampai selesai. Pastikan kamu mencentang opsi yang menambahkan Node.js ke dalam PATH, agar bisa digunakan langsung dari Command Prompt atau terminal. Setelah instalasi selesai, buka Command Prompt dan ketik perintah berikut untuk memastikan bahwa Node.js dan npm (Node Package Manager) sudah berhasil diinstall: node -v Perintah ini akan menampilkan versi Node.js yang terpasang, misalnya v22.0.0. npm -v Ini akan menampilkan versi npm, seperti 10.2.0. Kalau dua perintah ini menampilkan versi dengan benar, artinya kamu sudah siap memulai proyek Node.js-mu. Cara Membuat Proyek Backend Node.js untuk Katalog Sewa Mobil Setelah Node.js berhasil kamu install, sekarang kita mulai bikin proyek backend sederhana. Proyek ini akan menjadi dasar dari sistem katalog sewa mobil, di mana nanti kita bisa menampilkan daftar mobil, membaca data dari file, dan memberikan respons berupa JSON. Tapi di tahap ini, kita fokus dulu bikin struktur awal proyeknya. Pertama, buat dulu folder kosong untuk menyimpan semua file proyek kamu. Misalnya kamu bisa kasih nama katalog-sewa-mobil. Kamu bisa buat lewat File Explorer, atau langsung dari terminal: mkdir katalog-sewa-mobil cd katalog-sewa-mobil Setelah masuk ke folder proyek, jalankan perintah berikut untuk membuat file package.json. File ini akan menyimpan informasi dasar proyek seperti nama, versi, dan dependensi yang dibutuhkan. npm init -y Tanda -y artinya semua pertanyaan default akan dijawab otomatis, jadi prosesnya cepat. Selanjutnya, kita butauh satu file utama untuk menjalankan server. Biasanya kita kasih nama server.js, karena fungsinya untuk menjalankan HTTP server: echo. > server.js Kalau kamu pakai text editor seperti VS Code, kamu juga bisa langsung klik kanan dan pilih "New File", lalu tulis server.js. Setelah itu, kita akan buat juga satu folder bernama data. Di dalam folder ini nanti kita simpan file .json yang berfungsi sebagai database sederhana—alias file based database: mkdir data Sampai tahap ini, struktur folder kamu seharusnya terlihat seperti ini: katalog-sewa-mobil/ ├── data/ ├── package.json └── server.js Struktur ini adalah pondasi awal dari proyek backend kamu. Di artikel selanjutnya, kita akan mulai menulis logika untuk membaca file JSON dan menampilkan data mobil melalui endpoint yang bisa diakses lewat browser atau API client seperti Postman. Tapi sejauh ini, kamu udah siap banget buat lanjut ke tahap coding. Struktur Folder dan File yang Best Practice dalam Proyek Node.js Dalam membangun aplikasi backend Node.js yang rapi, scalable, dan mudah dipelihara, penting banget buat kita menggunakan struktur folder yang tertata dengan baik. Meskipun pada awalnya proyek kamu sederhana, membiasakan diri menggunakan struktur yang clean sejak awal akan memudahkan kamu atau tim kamu saat proyek berkembang lebih besar nanti. Berikut ini adalah struktur folder yang umum digunakan dalam proyek Node.js, khususnya kalau kamu tidak menggunakan framework seperti Express Generator, tapi ingin tetap rapi dan terorganisir: katalog-sewa-mobil/ ├── controllers/ ├── routes/ ├── services/ ├── models/ ├── data/ ├── utils/ ├── server.js ├── package.json Penjelasan tiap folder dan file: controllers/: berisi logika untuk menangani permintaan (request) dan mengirim respons (response). Di sinilah tempat kamu menulis logika endpoint API seperti /cars.routes/: berisi definisi endpoint dan rutenya, biasanya dipisahkan per fitur agar modular.services/: tempat logika bisnis utama, seperti filtering data, menyimpan data baru, validasi sederhana, dan lain-lain. Biasanya digunakan oleh controller.models/: menyimpan struktur data atau skema sederhana jika tidak menggunakan database seperti MongoDB atau Sequelize. Bisa juga sebagai lapisan abstraksi file JSON.data/: menyimpan file-file .json yang berperan sebagai file-based database.utils/: berisi helper function, seperti format tanggal, generate ID, logging, dll.server.js: titik masuk aplikasi, tempat menjalankan server dan menghubungkan semua bagian.package.json: konfigurasi dan dependensi proyek. Contoh Koding Folder Dasar server.js const http = require('http'); const { handleCarRoutes } = require('./routes/car.routes'); const PORT = 3000; const server = http.createServer((req, res) => { // Routing dasar if (req.url.startsWith('/cars')) { return handleCarRoutes(req, res); } res.writeHead(404, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Route tidak ditemukan' })); }); server.listen(PORT, () => { console.log(`Server berjalan di <http://localhost>:${PORT}`); }); routes/car.routes.js const { getAllCars } = require('../controllers/car.controller'); function handleCarRoutes(req, res) { if (req.method === 'GET' && req.url === '/cars') { return getAllCars(req, res); } res.writeHead(404, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Endpoint cars tidak ditemukan' })); } module.exports = { handleCarRoutes }; controllers/car.controller.js const { readCarData } = require('../services/car.service'); function getAllCars(req, res) { const cars = readCarData(); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(cars)); } module.exports = { getAllCars }; services/car.service.js const fs = require('fs'); const path = require('path'); function readCarData() { const filePath = path.join(__dirname, '../data/cars.json'); const fileContent = fs.readFileSync(filePath, 'utf8'); return JSON.parse(fileContent); } module.exports = { readCarData }; data/cars.json [ { "id": 1, "name": "Toyota Innova", "year": 2021, "price_per_day": 450000 }, { "id": 2, "name": "Suzuki Ertiga", "year": 2020, "price_per_day": 380000 } ] Dengan struktur ini, kamu bisa lebih mudah memisahkan tanggung jawab antar bagian. Misalnya, controller hanya fokus pada req dan res, sedangkan service bertanggung jawab untuk baca data atau menjalankan logika tertentu. Kalau nanti mau tambah fitur seperti tambah mobil baru, tinggal tambahkan method baru di car.service.js dan car.controller.js tanpa merusak struktur yang ada. Struktur ini juga memudahkan untuk testing, debug, dan scale up—baik ketika kamu mau ganti dari file based ke database sesungguhnya, atau saat mau deploy ke production. Cara Menyiapkan 100.000 Data JSON secara Otomatis Menyiapkan 100.000 data secara manual jelas bukan pilihan yang masuk akal. Untungnya, kita bisa menggunakan script Node.js sederhana untuk membuat data dummy dalam jumlah besar dan menyimpannya langsung ke file cars.json. Kita akan menggunakan module fs bawaan Node.js untuk menulis file, dan membuat array berisi objek-objek mobil dengan data yang dibangkitkan secara otomatis. Langkah pertama, buat file baru misalnya generate.js di dalam folder proyek kamu. Isi dengan kode berikut: const fs = require('fs'); const path = require('path'); // Fungsi bantu untuk menghasilkan nama mobil acak function generateCarName(index) { const brands = ['Toyota', 'Honda', 'Daihatsu', 'Suzuki', 'Nissan', 'Mitsubishi']; const models = ['Avanza', 'Brio', 'Xenia', 'Ertiga', 'Livina', 'Xpander']; const brand = brands[index % brands.length]; const model = models[index % models.length]; return `${brand} ${model}`; } const cars = []; for (let i = 1; i <= 100000; i++) { const car = { id: i, name: generateCarName(i), year: 2015 + (i % 10), // tahun antara 2015-2024 price_per_day: 250000 + (i % 10) * 10000 // variasi harga dari 250rb sampai 350rb }; cars.push(car); } const filePath = path.join(__dirname, 'data', 'cars.json'); fs.writeFile(filePath, JSON.stringify(cars, null, 2), (err) => { if (err) { console.error('Gagal menyimpan file:', err); } else { console.log('Berhasil membuat 100.000 data mobil ke dalam cars.json'); } }); Penjelasan singkat: Fungsi generateCarName() membuat nama mobil berdasarkan array merek dan model, lalu digabungkan.Loop for membuat 100.000 objek mobeil dengan id, name, year, dan price_per_day yang variatif.Semua data disimpan ke dalam array cars lalu ditulis ke file cars.json menggunakan fs.writeFile(). Untuk menjalankan scrippt ini, buka terminal di folder proyek lalu jalankan: node generate.js Dalam beberapa detik (tergantung spek komputermu), file cars.json di folder data/ akan terisi dengan 100.000 data mobil siap pakai. Kamu bisa pakai file ini untuk testing, simulasi API, atau keperluan performance benchmarking. Cara Menambahkan Route CRUD Data Mobil ke File JSON Setelah kita berhasil menyiapkan file cars.json, sekarang waktunya menambahkan fitur CRUD (Create, Read, Update, Delete) untuk memanipulasi data mobil yang tersimpan di file tersebut. Kita akan melanjutkan dari struktur yang sudah kita buat sebelumnya. Langkah 1: Update routes/car.routes.js untuk mendukung semua method HTTP const { getAllCars, getCarById, createCar, updateCarById, deleteCarById } = require('../controllers/car.controller'); function handleCarRoutes(req, res) { if (req.method === 'GET' && req.url === '/cars') { return getAllCars(req, res); } if (req.method === 'GET' && req.url.startsWith('/cars/')) { return getCarById(req, res); } if (req.method === 'POST' && req.url === '/cars') { return createCar(req, res); } if (req.method === 'PUT' && req.url.startsWith('/cars/')) { return updateCarById(req, res); } if (req.method === 'DELETE' && req.url.startsWith('/cars/')) { return deleteCarById(req, res); } res.writeHead(404, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Endpoint cars tidak ditemukan' })); } module.exports = { handleCarRoutes }; Langkah 2: Update controllers/car.controller.js dengan semua operasi CRUD const { readCarData, writeCarData } = require('../services/car.service'); function getAllCars(req, res) { const cars = readCarData(); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(cars)); } function getCarById(req, res) { const id = parseInt(req.url.split('/')[2]); const cars = readCarData(); const car = cars.find(c => c.id === id); if (!car) { res.writeHead(404, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify({ message: 'Mobil tidak ditemukan' })); } res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(car)); } function createCar(req, res) { let body = ''; req.on('data', chunk => { body += chunk; }); req.on('end', () => { const newCar = JSON.parse(body); const cars = readCarData(); newCar.id = cars.length > 0 ? cars[cars.length - 1].id + 1 : 1; cars.push(newCar); writeCarData(cars); res.writeHead(201, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(newCar)); }); } function updateCarById(req, res) { const id = parseInt(req.url.split('/')[2]); let body = ''; req.on('data', chunk => { body += chunk; }); req.on('end', () => { const updatedData = JSON.parse(body); const cars = readCarData(); const index = cars.findIndex(c => c.id === id); if (index === -1) { res.writeHead(404, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify({ message: 'Mobil tidak ditemukan' })); } cars[index] = { ...cars[index], ...updatedData }; writeCarData(cars); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(cars[index])); }); } function deleteCarById(req, res) { const id = parseInt(req.url.split('/')[2]); let cars = readCarData(); const index = cars.findIndex(c => c.id === id); if (index === -1) { res.writeHead(404, { 'Content-Type': 'application/json' }); return res.end(JSON.stringify({ message: 'Mobil tidak ditemukan' })); } const deleted = cars.splice(index, 1)[0]; writeCarData(cars); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(deleted)); } module.exports = { getAllCars, getCarById, createCar, updateCarById, deleteCarById }; Langkah 3: Tambahkan helper writeCarData di services/car.service.js const fs = require('fs'); const path = require('path'); function readCarData() { const filePath = path.join(__dirname, '../data/cars.json'); const fileContent = fs.readFileSync(filePath, 'utf8'); return JSON.parse(fileContent); } function writeCarData(data) { const filePath = path.join(__dirname, '../data/cars.json'); fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8'); } module.exports = { readCarData, writeCarData }; Sampai tahap ini, kamu sudah memiliki CRUD lengkap: GET /cars untuk mendapatkan semua mobilGET /cars/:id untuk mendapatkan mobil berdasarkan IDPOST /cars untuk menambahkan mobil baruPUT /cars/:id untuk mengedit data mobilDELETE /cars/:id untuk menghapus mobil Kamu bisa menguji semua endpoint ini lewat Postman atau Insomnia. Pastikan kamu menyetel header Content-Type: application/json untuk request POST dan PUT. Cara Melakukan Uji Coba API Backend Node.js Menggunakan Postman Setelah kamu menyelesaikan pembuatan backend katalog sewa mobil berbasis file JSON, langkah selanjutnya adalah mengujinya menggunakan Postman. Postman adalah aplikasi yang sangat membantu untuk mencoba dan mengevaluasi API secara manual. Kamu bisa kirim request, lihat respons, dan memastikan setiap endpoint bekerja seperti yang diharapkan. Sebelum membuka Postman, pastikan server kamu sedang berjalan dengan menjalankan: node server.js Setelah itu, buka aplikasi Postman dan ikuti cara berikut untuk mencoba tiap endpoint: Menguji GET semua mobil Pilih metode GETMasukkan URL http://localhost:3000/carsKlik toambol SendRespons yang keluar harus berupa array mobil seperti: [ { "id": 1, "name": "Toyota Avanza", "year": 2020, "price_per_day": 350000 }, { "id": 2, "name": "Honda Brio", "year": 2021, "price_per_day": 300000 } ] Menguji GET mobil berdasarkan ID Pilih metode GETMasukkan URL http://localhost:3000/cars/1Klik SendRespons yang keluar: { "id": 1, "name": "Toyota Avanza", "year": 2020, "price_per_day": 350000 } Menguji POST untuk menambahkan mobil baru Pilih metode POSTMasukkan URL http://localhost:3000/carsKlik tab Body → pilih raw → pilih JSONIsi konten seperti ini: { "name": "Nissan Serena", "year": 2022, "price_per_day": 400000 } Klik SendRespons akan menampilkan data mobil baru yang sudah diberi ID: { "name": "Nissan Serena", "year": 2022, "price_per_day": 400000, "id": 100001 } Menguji PUT untuk mengupdate mobil Pilih metode PUTMasukkan URL http://localhost:3000/cars/1Klik tab Body → pilih raw → pilih JSONIsi konten: { "price_per_day": 375000 } Klik SendRespons: { "id": 1, "name": "Toyota Avanza", "year": 2020, "price_per_day": 375000 } Menguji DELETE untuk menghapus mobil Pilih metode DELETEMasukkan URL http://localhost:3000/cars/1Klik SendRespons: { "id": 1, "name": "Toyota Avanza", "year": 2020, "price_per_day": 375000 } Setelah kamu coba semua endpoint di atas dan hasilnya sesuai harapan, artinya sistem backend kamu sudah bekerja dengan baik. Pastikan untuk melakukan testing secara berkala saat menambahkan fitur baru agar tidak ada yang rusak. Postman juga memungkinkan kamu menyimpan request untuk digunakan ulang, jadi sangat berguna saat pengembangan jangka panjang. Penutup dan Saran untuk Backend Developer Pemula yang Ingin Kerja Remote Belajar membuat backend dari nol memang nggak instan. Tapi dengan konsistensi dan struktur belajar yang benar, kamu bisa banget jadi backend developer yang siap kerja secara remote, bahkan dari rumah sendiri. Project sederhana seperti sistem katalog sewa mobil berbasis file JSON ini adalah titik awal yang bagus banget. Kamu bisa belajar banyak hal mulai dari routing, struktur folder, cara kerja server, sampai CRUD API—semuanya real dan langsung dipraktikkan. Kalau kamu merasa belajar sendiri bikin bingung dan butuh arahan yang jelas, jangan khawatir. Di BuildWithAngga, kamu bisa belajar langsung bareng mentor expert yang sudah berpengalaman bertahun-tahun di dunia backend dan kerja remote. Kursus yang kami siapkan nggak cuma teori doang, tapi berbasis proyek nyata, dengan penjelasan yang mudah dipahami dan step-by-step. Benefit belajar bareng mentor di BuildWithAngga antara lain: Belajar dari mentor yang pernah kerja di startup besar dan luar negeriMateri project-based, bukan teori kosongSertifikat resmi yang bisa kamu pakai untuk melamar kerja remoteAkses ke komunitas belajar, tanya jawab, dan sharing job opportunityUpdate materi sesuai tren industri backend terbaruaaaAda latihan interview & review portofolio biar kamu lebih siap ke dunia kerja Dunia kerja remote itu real, dan terbuka lebar buat siapa aja yang siap. Jadi daripada cuma jadi penonton, mending kamu ikut mulai dari sekarang. Bangun skill-mu, buat portofolio backend-mu, dan persiapkan diri untuk masuk ke dunia kerja global bareng BuildWithAngga. 🚀

Kelas Panduan Memulai Proyek React, Tailwind CSS, dan TypeScript hingga Menjadi Satu Halaman Web di BuildWithAngga

Panduan Memulai Proyek React, Tailwind CSS, dan TypeScript hingga Menjadi Satu Halaman Web

Daftar Isi PendahuluanDownload Node JSDownload LaragonViteInstall React & TypescriptMasuk dan InstallTailwind CSSCara Memasukkan Tailwind ke ReactInstall Tailwind CSSKonfigurasiCSSHapusUbahTambahHasil Struktur Folder Setelah di TambahPastikan Sudah Download Dependency IniDownload Template HTML ShaynakitMasukin Template ke ReactCopy Gambar & IconConvert ke JSXAkses BrowserPenutup Pendahuluan Kalau kamu baru ingin mulai belajar membangun web modern, kombinasi React, Tailwind CSS, dan TypeScript adalah paket lengkap yang layak dicoba. Di artikel ini, kita akan bahas langkah-langkah praktis dari awal hingga kamu berhasil membuat satu halaman web yang rapi, responsif, dan mudah dikembangkan. Tenang, semuanya akan dijelaskan dengan sederhana dan jelas. Dimuali dari mendownload Node JS dulu. Download Node JS Browser - Node JS Node.js itu ibarat dapur tempat JavaScript bisa masak. Kalau biasanya JavaScript hanya bisa dipakai untuk mengatur tampilan di halaman web, dengan Node.js kamu bisa pakai JavaScript untuk bikin hal-hal di belakang layar, seperti menyajikan data dari database, membuat server sendiri, menjalankan React JS atau menjalankan alat bantu seperti Tailwind CSS. Dibangun di atas mesin cepat milik Google (V8), Node.js memungkinkan developer membangun aplikasi yang ringan dan responsif hanya dengan satu bahasa untuk frontend dan backend. Pastiin kamu sudah menginstall dan kalau mau cek hasilnnya ketik perintah ini di terminal kamu: node -v npm -v Kalau memang sudah terinstall bakal muncul kayak gini yang artinya udah siap di pake nanti : Download Laragon Browser - Laragon Laragon itu ibarat kotak perkakas praktis untuk ngoding PHP dan web development di Windows. Daripada repot install Apache, MySQL, PHP, dan lain-lain satu per satu, Laragon menyatukannya dalam satu aplikasi ringan yang siap pakai. Dengan antarmuka yang simpel, kamu bisa langsung buat proyek Laravel, WordPress, atau lainnya hanya dengan beberapa klik. Selain itu, Laragon juga cepat, portabel, dan nggak bikin sistem berat. Cocok banget buat kamu yang ingin mulai belajar backend tanpa ribet konfigurasi sana-sini. Pastiin kamu juga udah install Laragon ini, santai boleh pakai XAMPP karena sama aja, yang kita butuhin itu MySQL nya agar bisa nyambung React kita ke Database kita. Kalau udah berhasil install Laragon dan udah siap ciri-cirinya kayak gini: Result & Play Laragon Biar makin yakin udah bener, ketik http://localhost di browser kamu dan hasilnya harus gini: Second Test Laragon Vite Browser - Vite Vite adalah build tool modern yang bikin proses ngoding frontend jadi lebih cepat dan menyenangkan, terutama buat proyek React, Vue, atau lainnya. Saat kamu mulai ngoding, Vite langsung nyala dan tampilkan hasilnya tanpa loading lama, karena dia cuma memproses file yang benar-benar dibutuhkan. Pas udah siap dibuild untuk production, dia juga ngerapihin semuanya jadi ringan dan siap online. Selain itu, Vite didesain dengan arsitektur yang memanfaatkan kemampuan browser modern, jadi proses pengembangan terasa lebih responsif dan minim hambatan. Dengan fitur hot module replacement (HMR) yang super cepat, perubahan kode langsung terlihat tanpa perlu reload halaman penuh, membuat workflow kamu jadi jauh lebih efisien dan menyenangkan. Bisa dibilang, Vite itu seperti mesin kopi instan, sekali tekan, langsung jadi, beda dengan alat lama yang harus dipanaskan dulu dan bikin kamu nunggu lama sebelum bisa mulai ngoding. Vite ini bakal kita pake buat install React nya biar nanti jalannya lebih powerful. Install React & Typescript Nah, sekarang setelah kita udah ngerti apa yang dibutuhin dan alat-alatnya juga udah siap, tinggal gas bikin proyeknya! Buat dulu folder terserah kamu mau kasih nama apa, terus buka folder itu di VSCode atau text editor favorit kamu sampai tampilannya kayak gambar ini: VSCode - First Folder Untuk langkah selanjutnya, buka terminal di dalam VSCode dengan cara tekan tombol CTRL + ` (tombol backtick, biasanya di bawah Esc). Setelah terminal muncul, kamu bisa langsung jalankan perintah di bawah ini untuk mulai setup proyek kamu: npm create vite@latest Pilih aja kayak yang di gambar di bawah ini, pilih React, TypeScript + SWC, dan beri nama proyek terserah kalian: VSCode - Create Project Masuk dan Install Nah setelah itu tinggal masuk ke folder proyeknya lalu jalanin kayak gini: cd belajar npm install npm run dev Jadi, cd itu singkatan dari “change directory” alias masuk ke dalam folder. Nah, kalau kamu ketik cd belajar, artinya kamu lagi pindah masuk ke folder yang namanya “belajar”. Terus, npm install itu perintah buat ngunduh dan memasang semua paket atau library yang dibutuhin proyek kamu supaya bisa jalan dengan lancar. Kalau npm run dev, itu perintah buat ngejalanin proyek kamu dalam mode development, jadi kamu bisa lihat hasilnya langsung dan kalo ada perubahan, tampilannya bakal otomatis update tanpa perlu di-refresh manual. Lalu akses link dibawah ini, nanti proyeknya bakal tampil: VSCode - Ready to Appear Kalau sudah kamu akses link itu tampilannya bakal gini: Browser - Result Project Tailwind CSS Browser - Tailwind CSS Jadi, Tailwind CSS itu kayak kotak peralatan serbaguna buat desain website. Bayangin kamu lagi ngegambar dan biasanya harus bikin kuas dan cat sendiri dulu, nah Tailwind ini sudah sediain ratusan kuas kecil yang tinggal kamu pakai langsung buat bikin gambar sesuai keinginan. Nggak perlu ribet nulis kode CSS panjang-panjang, kamu cuma pakai kelas-kelas kecil kayak bg-blue-500 buat warna biru, p-4 buat padding, atau flex buat atur layout, langsung tempel di HTML kamu. Selain cepat dan praktis, Tailwind juga bikin tampilan website kamu gampang diatur dan konsisten karena semuanya seragam dari alat yang sama. Nah, kalau mau warna atau ukuran yang beda, tinggal atur di file konfigurasi, kayak nge-mix cat supaya warna yang kamu pakai pas banget. Intinya, pakai Tailwind itu kayak punya toolkit yang siap pakai buat bikin tampilan keren tanpa harus repot bikin semuanya dari nol. Cara Memasukkan Tailwind ke React Install Tailwind CSS Sekarang, tinggal jalanin perintah ini di terminal yang ada di dalam folder proyek React kamu. Cukup ketik aja perintahnya, terus pencet Enter, nanti prosesnya bakal jalan otomatis: npm install tailwindcss @tailwindcss/vite Perintah npm install tailwindcss @tailwindcss/vite ini fungsinya buat ngunduh dan pasang paket Tailwind CSS beserta plugin khusus yang bikin Tailwind bisa jalan lancar bareng Vite sebagai build tool-nya. Jadi, dengan perintah ini, kamu nggak cuma dapetin core Tailwind CSS buat styling, tapi juga integrasi yang mulus supaya Vite bisa proses Tailwind dengan cepat dan efisien saat kamu lagi develop proyek frontend-mu. Singkatnya, ini langkah penting supaya styling pakai Tailwind bisa berjalan sempurna di proyek React yang kamu bikin pakai Vite. Hasilnya VSCode Terminal - Install Tailwind CSS Konfigurasi Di dalam file vite.config.ts kamu beri kode ini import tailwindcss from '@tailwindcss/vite' Kalimat import tailwindcss from '@tailwindcss/vite' itu artinya kita lagi ngambil (import) plugin Tailwind CSS khusus yang dibuat untuk Vite ke dalam file konfigurasi atau skrip kita. Dengan nge-import ini, kita kasih tahu Vite supaya bisa pakai Tailwind CSS secara optimal dan nyatu banget sama proses build dan development yang lagi jalan. Jadi, plugin ini semacam jembatan yang bikin Tailwind dan Vite kerja barengan dengan mulus tanpa ribet. tailwindcss() tailwindcss() itu kayak kamu lagi memanggil atau ngejalanin fungsi Tailwind CSS di dalam konfigurasi Vite. Jadi, pas kamu tulis tailwindcss(), artinya kamu ngasih perintah supaya Vite aktifkan plugin Tailwind CSS yang tadi sudah di-import, supaya bisa langsung digunakan buat proses styling proyek kamu. Bisa dibilang, ini kayak tombol “ON” buat Tailwind di proyek kamu. Sampai hasilnya gini import { defineConfig } from "vite"; import react from "@vitejs/plugin-react-swc"; import tailwindcss from "@tailwindcss/vite"; // <https://vite.dev/config/> export default defineConfig({ plugins: [react(), tailwindcss()], }); CSS Di file src/index.css, hapus semua kode yang ada supaya kosong, lalu tinggal isi cuma dengan satu baris ini saja: @import "tailwindcss"; Sekarang Tailwind sudah nyantol ke proyek React kita, jadi tinggal ambil css nya terus pake. Hapus VSCode - Structure Project Hapus file App.css karena file tersebut enggak akan kita pake. Ubah Lalu hapus isi file ini : VSCode - App.tsx Isi dengan: VSCode - New Code Kode <BrowserRouter>, <Routes>, dan <Route> yang kamu taruh di file App.tsx di React itu fungsinya buat ngatur routing atau navigasi antar halaman di aplikasi kamu. BrowserRouter itu kayak pembungkus utama yang ngatur semua rute berdasarkan URL di browser, jadi React tahu harus nampilin halaman apa pas user akses URL tertentu.Routes adalah tempat di mana kamu naro semua daftar rute (alias halaman) yang mau kamu buat.Nah, Route itu satuan rute-nya. Di contoh kamu, pas user buka / (halaman utama), maka React bakal nampilin komponen <HomePage />. Jadi, kode itu intinya nge-set: "Kalau URL-nya adalah /, tampilkan halaman HomePage." Simple dan terstruktur banget buat aplikasi yang butuh lebih dari satu halaman. Itu error karna kita belum buat filenya dan belum download depedencynya, tapi santai aja nanti bakal kita lakuin. Tambah Buat sekarang tambahin dulu file dan folder-folder keperluannya kayak: .env File .env di React itu fungsinya buat nyimpen data rahasia atau pengaturan penting yang nggak mau kamu tulis langsung di dalam kode. Misalnya kayak API key, URL backend, token, atau config lain yang bisa beda-beda antara development dan production. Dengan begitu, kamu bisa akses data itu lewat process.env.NAMA_VARIABEL di dalam kode kamu, dan nilai aslinya diambil dari file .env. Nah, di React (pakai Vite atau CRA), nama variabelnya harus diawali dengan VITE_ (kalau pakai Vite) atau REACT_APP_ (kalau pakai CRA), misalnya VITE_API_URL=https://api.example.com. Jadi, pakai .env itu bikin proyek kamu lebih aman, rapi, dan gampang diatur. Buat file ini di path terluar terus isi gini: VSCode - env VITE_REACT_API_URL = <http://127.0.0.1:8000/api> VITE_REACT_API_STORAGE_URL = <http://127.0.0.1:8000/storage> Nah, keduanya itu berfungsi buat nyimpen alamat URL yang bakal dipakai di dalam aplikasi React kita. VITE_REACT_API_URL biasanya dipakai buat ngarahin semua request API ke backend, misalnya ke Laravel atau server lokal kita yang lagi jalan di http://127.0.0.1:8000/api, sedangkan VITE_REACT_API_STORAGE_URL dipakai buat akses file atau gambar yang disimpan di direktori storage backend. Dengan naruh ini di .env, kita bisa panggil variabelnya lewat import.meta.env.VITE_REACT_API_URL atau import.meta.env.VITE_REACT_API_STORAGE_URL di file React, jadi nanti kalau mau ganti alamat server tinggal ubah di .env aja tanpa perlu utak-atik banyak file. api Folder api yang kita taruh di dalam folder src di proyek React (yang pakai Vite) biasanya dipakai buat nyimpen semua fungsi atau file yang berhubungan sama komunikasi ke backend atau API. Misalnya, di folder api ini kita bisa bikin file kayak auth.ts, user.ts, atau produk.ts yang isinya fungsi-fungsi buat ngirim request ke server, misalnya login, ambil data user, atau ambil daftar produk. Tujuannya biar kode kita lebih rapi dan terorganisir, jadi logika komunikasi ke server nggak nyampur sama komponen tampilan (UI). Jadi, tiap komponen cukup "minta data" dari folder api, dan nggak perlu tahu detail cara ambil datanya gimana. Kayak punya bagian khusus buat ngobrol sama server, biar semua rapi dan enak dikelola. components Folder components di dalam folder src di proyek React yang pakai Vite fungsinya buat nyimpen semua komponen UI yang kita bangun dan bisa dipakai ulang di berbagai bagian aplikasi. Komponen ini bisa berupa tombol, header, card, form, atau elemen-elemen kecil lainnya yang tampil di layar. Dengan memisahkannya ke dalam folder components, struktur proyek jadi lebih rapi dan modular, jadi kalau kita mau ubah tampilan tombol misalnya, tinggal edit satu file tanpa harus cari-cari di banyak tempat. Intinya, folder ini jadi tempat ngatur bagian-bagian kecil dari tampilan yang bisa disusun bareng untuk membentuk halaman yang utuh. context Folder context di dalam folder src di proyek React (yang pakai Vite) fungsinya buat nyimpen file-file yang berkaitan dengan manajemen state global pakai React Context API. Jadi kalau kita punya data atau state yang perlu diakses dari banyak komponen, misalnya data user yang sudah login, tema aplikasi (dark/light), atau status autentikasi, kita bisa simpan dan kelola datanya lewat Context. Dengan adanya folder context, kita bisa bikin file seperti AuthContext.tsx atau ThemeContext.tsx yang masing-masing isinya menyediakan Provider dan useContext supaya komponen lain bisa ikut "nebeng" data dari satu sumber. Jadi, folder ini membantu kita bikin manajemen state lebih terstruktur, konsisten, dan gampang di-maintain. hooks Folder hooks di dalam folder src di proyek React yang pakai Vite gunanya buat nyimpen custom hooks, yaitu fungsi-fungsi buatan sendiri yang memanfaatkan fitur React Hooks (kayak useState, useEffect, dll) untuk menangani logika tertentu yang bisa dipakai ulang di berbagai komponen. Misalnya, kita bisa bikin useAuth.ts buat ngecek status login, useFetch.ts buat ambil data dari API, atau useWindowSize.ts buat deteksi ukuran layar. Dengan naruh semua custom hooks di folder hooks, struktur proyek jadi lebih rapi, dan logika yang sering dipakai bisa ditulis sekali lalu dipanggil di mana pun dibutuhkan. Intinya, folder ini bantu kita pisahin logika dari tampilan supaya lebih modular dan mudah dirawat. pages Folder pages di dalam folder src di proyek React yang pakai Vite fungsinya buat nyimpen file-file komponen yang mewakili halaman utama dalam aplikasi, seperti halaman beranda (HomePage.tsx), login (LoginPage.tsx), atau profil (ProfilePage.tsx). Berbeda dari folder components yang isinya bagian-bagian kecil UI, folder pages biasanya berisi komponen tingkat tinggi yang menyusun berbagai komponen jadi satu tampilan halaman utuh. Folder ini juga sering dikaitkan langsung dengan routing (pakai React Router), jadi setiap file di pages biasanya cocok dengan satu URL di aplikasi. Dengan begitu, struktur aplikasi jadi lebih teratur dan gampang diatur kalau proyek makin besar. providers Folder providers di dalam folder src di proyek React yang pakai Vite biasanya dipakai buat nyimpen komponen-komponen provider yang membungkus aplikasi atau bagian tertentu dengan konteks khusus. Provider ini biasanya berisi komponen yang menggunakan React Context API, Redux Provider, Theme Provider, atau library lain yang butuh “membungkus” komponen supaya data atau fungsi tertentu bisa diakses turun-temurun oleh komponen-komponen di bawahnya. Misalnya, AuthProvider buat ngatur status login, atau ThemeProvider buat ngatur tema warna aplikasi. Dengan punya folder providers, kita bisa kelola dan pisahkan logika penyedia data global secara rapi dan terstruktur, jadi saat mau pakai atau update provider, gampang ditemukan dan di-maintain. routes Folder routes di dalam folder src di proyek React yang pakai Vite fungsinya buat ngatur semua konfigurasi routing atau jalur navigasi aplikasi. Di sini kita biasanya bikin file yang mendefinisikan bagaimana URL di aplikasi kita dipetakan ke komponen halaman tertentu, misalnya menentukan kalau path / tampil HomePage, /login tampil LoginPage, dan seterusnya. Dengan naruh semua aturan routing di folder routes, kode jadi lebih terorganisir dan terpisah dari logika UI. Jadi kalau mau nambah, ubah, atau cek navigasi aplikasi, kita tinggal buka folder ini tanpa harus nyari di berbagai file. Ini penting banget supaya aplikasi React kita gampang dikelola, apalagi kalau sudah besar dan punya banyak halaman. schemas Folder schemas di dalam folder src di proyek React yang pakai Vite biasanya dipakai buat nyimpen definisi struktur data atau aturan validasi yang digunakan di aplikasi. Misalnya, kita bisa bikin schema untuk validasi form dengan library seperti Yup atau Zod, di mana schema ini menjelaskan aturan seperti “email harus valid”, “password minimal 8 karakter”, atau “nama tidak boleh kosong”. Selain itu, folder schemas juga bisa berisi tipe data atau interface TypeScript yang mendeskripsikan bentuk data yang kita pakai, supaya kode lebih terstruktur dan aman dari kesalahan tipe data. Dengan punya folder schemas, kita bisa mengatur aturan dan tipe data di satu tempat khusus, bikin aplikasi lebih rapi dan gampang dipelihara. services Folder services di dalam folder src di proyek React yang pakai Vite fungsinya buat menyimpan logika bisnis dan fungsi-fungsi yang berhubungan dengan interaksi ke luar aplikasi, seperti komunikasi dengan API, pengolahan data, atau fitur khusus yang butuh dipisah dari komponen UI. Misalnya, di sini kita bisa bikin file untuk fungsi-fungsi yang handle request ke backend, seperti userService.ts yang isinya fungsi untuk login, register, atau ambil data user, atau paymentService.ts yang urus proses pembayaran atau piService.ts untuk mengakses axios. Dengan menaruh semua logika ini di folder services, kode jadi lebih terorganisir dan komponen UI bisa fokus hanya pada tampilan dan interaksi pengguna tanpa kebingungan dengan logika bisnis. Jadi, folder services bantu kita pisahkan tanggung jawab kode supaya aplikasi lebih modular dan gampang di-maintain. Beri file ini dan isi ini: VSCode - Axios types Folder types di dalam folder src di proyek React yang pakai Vite itu tempat kita nyimpen semua definisi tipe data atau interface TypeScript yang dipakai di seluruh aplikasi. Jadi kalau kita mau jelasin bentuk data, properti apa saja yang ada, atau tipe dari variabel tertentu, kita taruh di sini supaya kode lebih terstruktur dan gampang dipakai ulang. Dengan begitu, kita bisa lebih aman dan terhindar dari error tipe data karena semua tipe sudah didefinisikan dengan jelas dan bisa dipanggil di mana saja dalam proyek. Intinya, folder types bikin pengelolaan tipe data jadi rapi dan efisien. Contohnya seperti ini: VSCode - TypeScript utils Folder utils di dalam folder src di proyek React yang pakai Vite itu tempat kita nyimpen berbagai fungsi kecil atau helper yang bisa dipakai ulang di banyak bagian aplikasi. Misalnya, fungsi buat format tanggal, hitung sesuatu, atau ngecek validasi sederhana yang nggak spesifik ke satu fitur tertentu. Dengan naruh fungsi-fungsi ini di folder utils, kita jadi nggak perlu nulis ulang kode yang sama berkali-kali, dan struktur proyek jadi lebih bersih karena fungsi-fungsi bantuan ini terpisah dari logika utama aplikasi. Jadi, utils itu kayak kotak alat kecil yang selalu siap dipakai kapan pun dibutuhkan. Hasil Struktur Folder Setelah di Tambah VSCode - Complete Structure Pastikan Sudah Download Depedency Ini Setelah memasukkan kode ini ke package.json langsung saja jalankan perintah npm install "dependencies": { "@hookform/resolvers": "^5.0.1", "@tailwindcss/vite": "^4.1.4", "@tanstack/react-query": "^5.74.4", "axios": "^1.9.0", "date-fns": "^4.1.0", "react": "^19.1.0", "react-dom": "^19.1.0", "react-router-dom": "^7.5.2", "tailwindcss": "^4.1.4", "zod": "^3.24.3" }, @hookform/resolvers: Plugin yang menghubungkan library validasi eksternal (seperti Zod atau Yup) ke React Hook Form, supaya kita bisa validasi form dengan aturan yang lebih kompleks.@tailwindcss/vite: Plugin resmi Tailwind CSS buat integrasi dengan Vite. Ini bikin proses build dan hot reload Tailwind jadi lebih cepat dan lancar.@tanstack/react-query: Library buat manajemen data fetching dan caching di React. Ngebantu kita ambil data dari API tanpa ribet urus loading, error, atau re-fetch otomatis.axios: Library populer buat melakukan request HTTP (GET, POST, dll). Dipakai buat komunikasi antara frontend dan backend secara lebih simpel dibanding fetch.date-fns: Kumpulan fungsi JavaScript buat memanipulasi tanggal. Mirip kayak Moment.js, tapi lebih ringan dan modular.react: Library utama untuk bikin UI berbasis komponen. Semua proyek React pasti butuh ini.react-dom: Library yang ngurusin gimana komponen React dirender ke dalam DOM browser. Jadi pasangan utamanya react.react-router-dom: Library untuk navigasi dan routing di aplikasi React berbasis web. Ngebantu kita bikin banyak halaman dalam satu aplikasi SPA (Single Page Application).tailwindcss: Framework CSS utility-first yang bikin styling jadi cepat dan konsisten langsung dari HTML atau JSX tanpa harus nulis CSS panjang-panjang.zod: Library validasi dan parsing data yang mirip Yup, tapi lebih ketat dan cocok banget dipakai bareng TypeScript karena integrasi tipenya yang solid. Download Template HTML Shaynakit Shaynakit - Ngekos Template HTML Di tutorial kali ini, kita bakal pakai proyek dari Shaynakit buat ngubahnya ke React. Kabar baiknya, proyek ini gratis dan kodenya juga udah disediain. Jadi kamu bisa langsung pakai, atau modif-modif dikit biar sesuai sama kebutuhan. Nggak perlu mulai dari nol proses ngodingnya jadi jauh lebih gampang dan cepet. Shaynakit sendiri tuh semacam website yang nyediain kumpulan desain bareng sama kodenya. Ada yang gratis, ada juga yang premium. Tapi tenang aja, yang gratis juga nggak pelit-pelit banget kok biasanya cuma dibatesin di jumlah halamannya aja. Nah, kalau yang premium, tentu lebih lengkap dan komplit, semua bagian udah siap pakai. Cara donwloadnya kayak gini: Buka situs utama ShaynaKit di https://shaynakit.com/landing.Klik menu atau tombol Register atau langsung buka https://shaynakit.com/register untuk membuat akun terlebih dahulu.Setelah berhasil mendaftar dan login, buka halaman template kode yang akan digunakan di https://shaynakit.com/details/ngekos-find-house-details-bokking-success-html-tailwind-css-template.Klik tombol Download, lalu pada opsi yang tersedia, pilih Free Trial.Klik tombol Start Today untuk memulai akses gratis.Setelah itu, kembali ke halaman yang sama: https://shaynakit.com/details/ngekos-find-house-details-bokking-success-html-tailwind-css-template, dan klik tombol Download sekali lagi.File template code akan terunduh dalam format .zip.Simpan file .zip tersebut ke dalam folder lokal proyek Anda, misalnya ./source-code/ngekos.zip. Masukin Template ke React Kalau udah download selanjutnya kita masukin 1 file ke proyek React. Copy Gambar & Icon buat pakai gambar dan icon dari template HTML yang udah kamu download tadi, kamu cukup cari folder yang namanya assets , biasanya isinya gambar, icon, dan file pendukung lainnya. Nah, tinggal klik folder assets itu, tekan Ctrl + C buat copy, lalu buka proyek React kamu, masuk ke folder public, dan paste di situ (Ctrl + V). Hasil akhirnya nanti folder assets itu bakal nongkrong di dalam public, jadi kamu bisa akses gambarnya langsung dari path kayak /assets/nama-file.png . Letaknya kayak gini: VSCode - Moving the assets Folder Convert ke JSX Setelah kamu download file .zip-nya, jangan lupa klik kanan → Extract All, biar semua isi file-nya bisa kita akses. Nah, abis itu buka folder hasil ekstrak-nya pakai VSCode. Begitu masuk, cari file yang namanya index.html, buka, dan salin dari tag <main> yang pembuka sampai tag </main> yang penutup, pokoknya seluruh isi <main> itu. Setelah itu, tinggal paste ke website yang ada di bawah ini: Convert HTML To JSX Lalu tombol “Copy” berwarna biru di pojok atas kanan itu klik untuk mengcopy tag jsxnya, lalu kembali ke VSCode, paste ke dalam HomePage.tsx kayak gini: Result Paste Akses Browser Lalu jalankan perintah npm run dev Hasil Browser - Result Nah, kalau tampilannya sekarang kelihatan berantakan, tenang dulu, itu bukan berarti ada yang salah. Sebenarnya tampilannya cuma belum sempurna karena belum ada Swiper JS-nya yang dipakai buat fitur scroll-slide di template aslinya. Jadi wajar aja kalau elemen yang seharusnya bisa digeser (kayak carousel atau slider) sekarang malah numpuk ke bawah atau nggak bisa digeser sama sekali. Solusinya simpel: tinggal install Swiper JS untuk React dan terapin di komponen yang butuh scroll. Begitu Swiper-nya udah kepasang dan disetting, tampilannya bakal mirip persis sama template HTML awalnya. Jadi tenang, tinggal satu langkah lagi nih buat bikin semuanya kelihatan rapi dan interaktif. Dan agar kamu mahir pake Tailwind sekaranglah waktunya challenge coba install dan terapi Swiper JS nya biar React kamu makin gacor. Penutup Setelah kamu ikutin semua langkahnya, harapannya kamu nggak cuma berhasil bikin satu halaman web yang keren, tapi juga makin paham cara kerja proyek modern berbasis React, Tailwind CSS, dan TypeScript. Jangan takut buat eksplor lebih jauh, karena dari sini kamu udah punya pondasi kuat buat bangun proyek yang lebih besar dan kompleks ke depannya. Semangat ngoding, dan selamat mencoba! 🚀

Kelas Perbedaan useState dan useEffect: Panduan React Hook Dasar di BuildWithAngga

Perbedaan useState dan useEffect: Panduan React Hook Dasar

Kalau kamu baru terjun ke dunia React atau lagi transisi dari class component ke function component, pasti sering banget ketemu sama dua hook populer ini: useState dan useEffect. Hooks adalah fitur di React yang memungkinkan kamu “menyisipkan” fitur-fitur React seperti state dan lifecycle ke dalam functional component. Sebelum ada hooks, fitur-fitur ini cuma bisa dipakai di class component. Kenapa penting? Functional component lebih simpel, ringan, dan mudah ditulis.Dengan hooks, kamu bisa mengatur state dan efek samping tanpa harus repot-repot bikin class. Artikel ini cocok banget buat kamu yang masih bingung: "Ini kapan sih pakai useState, dan kapan pakai useEffect?" Persiapan Proyek Sebelum kita mulai ngulik komponen di React, tentu kita perlu siapkan dulu proyek React nya, biar bisa langsung praktek dan nggak cuma teori doang. Syarat Awal Pastikan kamu udah install Node.js di komputer kamu, minimal versi 14 ya. Buat ngecek, buka terminal atau command prompt terus ketik: node -v npm -v Ini versi yg saya gunakan: Terminal Windows Kalau keluar versinya berarti udah oke, kalo belum, kamu bisa download Node.js dari situs resmi nodejs.org. Instalasi React dengan Next.js Nah, buat mulai proyek React, kita bakal pake Next.js. Next.js ini keren banget karena selain React biasa, dia juga punya fitur kayak routing otomatis dan server-side rendering yang bikin performa aplikasi makin ngebut. Buka terminal terus ketik perintah ini buat bikin proyek baru: npx create-next-app@latest bwa-react Jika ada konfirmasi seperti ini tekan Enter di keyboard Terminal: Install Next.js √ Would you like to use TypeScript? ... Pilih Yes√ Would you like to use ESLint? ... Pilih Yes√ Would you like to use Tailwind CSS? ... Pilh Yes√ Would you like your code inside a src/ directory? ... Pilih Yes√ Would you like to use App Router? (recommended) ... Pilih Yes√ Would you like to use Turbopack for next dev? ... Pilih Yes√ Would you like to customize the import alias (@/* by default)? ... Pilih No Terminal: Install Next.js Jika proses intallasi sudah selesai, masuk ke folder proyeknya: cd bwa-react Terus jalankan development server dengan perintah: npm run dev Terminal: Menjalankan Next.js Biasanya bakal keluar alamat http://localhost:3000 di terminal. Kamu buka alamat itu di browser, dan… voila! Kamu udah punya proyek React dengan Next.js siap pakai. Tampilan awal Next.js Kalau kamu pake bun, tinggal ganti aja npm jadi bun di perintah-perintah tadi. Apa Itu useState? useState adalah hook buat nyimpen dan mengatur data (state) di dalam komponen. Ibaratnya kayak laci pribadi komponen buat nyimpan data yang bisa berubah. Bentuk Umum: const [count, setCount] = useState<number>(0); count: nilai sekarang.setCount: fungsi buat update nilai count. Contoh Penggunaan: Counter Sederhana: 'use client'; import { useState } from 'react'; export default function Counter() { const [count, setCount] = useState<number>(0); return ( <div> <p>Jumlah: {count}</p> <button onClick={() => setCount(count + 1)}>Tambah</button> </div> ); } Form Input 'use client'; import { useState } from 'react'; export default function InputForm() { const [name, setName] = useState<string>(''); return ( <input value={name} onChange={(e) => setName(e.target.value)} placeholder="Nama kamu" /> ); } Kapan pakai useState? Kalau kamu pengen nyimpan data yang: Bisa berubah (dinamis)Dibutuhkan saat render ulang Apa Itu useEffect? useEffect adalah hook buat ngejalanin efek samping (side effects). Maksudnya, hal-hal yang nggak langsung berhubungan sama proses render React, kayak: Ambil data dari APIManipulasi document.titleSimpan data ke localStorageTimer/intervalEvent listener Bentuk Umum: useEffect(() => { // efek samping di sini }, [dependency]); Jenis-jenis Dependensi: DependensiKapan JalanKosong []Cuma sekali, setelah komponen pertama kali muncul (mount)Tidak adaTiap kali renderAda nilai [x]Jalan kalau x berubah Contoh: Ubah Title Tab 'use client'; import { useEffect, useState } from 'react'; export default function TitleChanger() { const [count, setCount] = useState<number>(0); useEffect(() => { document.title = `Klik: ${count}`; }, [count]); return <button onClick={() => setCount(count + 1)}>Klik aku!</button>; } Kapan Pakai useState vs useEffect? SituasiPakai Hook Apa?PenjelasanNyimpen nilai input formuseStateKarena kita butuh update data saat user ketikFetch data dari APIuseEffectIni termasuk efek sampingHitung jumlah klik tomboluseStateKarena data klik disimpan di stateUpdate judul tab browseruseEffectKarena manipulasi DOM dilakukan di luar ReactSimpan data ke localStorage saat state berubahuseState + useEffectGunakan state buat nyimpen, efek untuk nyimpan ke localStorage Contoh Praktis: Simpan Nama ke localStorage Studi Kasus Kita mau: Ambil nama dari localStorage pas komponen pertama kali muncul.Update localStorage setiap kali nama berubah. Kode Lengkap: Buat file pada direktori src/components/InputName.tsx // src/components/InputName.tsx "use client"; import { useState, useEffect } from "react"; export default function UserForm() { const [name, setName] = useState<string>(""); // Ambil nama dari localStorage saat pertama render useEffect(() => { const savedName = localStorage.getItem("username"); if (savedName) { setName(savedName); } }, []); // Simpan ke localStorage setiap kali 'name' berubah useEffect(() => { localStorage.setItem("username", name); }, [name]); // Fungsi untuk menghapus nama dari localStorage dan state const handleDelete = () => { localStorage.removeItem("username"); setName(""); }; return ( <div className="flex flex-col w-3xs space-y-4"> <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Masukkan nama kamu" className="border px-4 py-2 rounded w-full" /> <button onClick={handleDelete} disabled={!name} className="ml-auto bg-red-500 text-white px-4 py-2 rounded hover:bg-red-600 transition-all duration-300 disabled:opacity-50" > Hapus Nama </button> </div> ); } 📌 Penjelasan: Saat pertama kali render, kita cek localStorage.Setelah user ngetik dan name berubah, kita simpan ulang ke localStorage.handleDelete() akan:Menghapus data dari localStorage dengan removeItem('username').Reset state name ke string kosong.Efek: input akan langsung kosong, dan tidak disimpan lagi ke localStorage sampai pengguna mengetik ulang. Buka page.tsx lalu ubah kode jadi seperti berikut: // scr/app/page.tsx import InputName from "@/components/InputName"; export default function Home() { return ( <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]"> <main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start"> <InputName /> </main> </div> ); } Hasilnya: Contoh kombinasi useEffect dan useState Kesalahan Umum yang Sering Dilakukan Belajar React Hooks itu seru, tapi banyak juga jebakan Batman-nya. Nah, biar kamu nggak jatuh ke lubang yang sama, ini dia beberapa kesalahan umum yang sering banget terjadi pas pakai useState dan useEffect: Lupa Menambahkan Dependency di useEffect Contoh salah: useEffect(() => { console.log(name); }, []); // name seharusnya masuk ke dependency Penjelasan: Kalau name nggak dimasukin ke dependency array, useEffect nggak bakal ngejalanin ulang efeknya meskipun name berubah. Ini bisa bikin bug yang susah dilacak. Solusi: useEffect(() => { console.log(name); }, [name]); Bikin Infinite Loop Tanpa Sadar Contoh salah: const [count, setCount] = useState(0); useEffect(() => { setCount(count + 1); // ini bakal terus-menerus nge-trigger re-render }, [count]); Penjelasan: Karena setCount di-trigger tiap kali count berubah, efek ini akan terus jalan, bikin infinite loop dan nge-crash aplikasi. Solusi: Hindari update state di dalam useEffect yang bergantung pada state itu sendiri, kecuali kamu tahu persis apa yang kamu lakukan (misalnya pakai kondisi). Naruh Logika Berat di useState const [result, setResult] = useState(() => { // ini dieksekusi setiap render return hitungLamaBanget(); }); Solusi: Kalau hitungannya berat, kamu bisa manfaatkan fungsi inisialisasi useState: const [result, setResult] = useState(() => hitungLamaBanget()); // cuma dieksekusi sekali Efek Samping Tanpa Cleanup Misalnya pakai timer atau event listener tapi nggak dibersihin. Contoh salah: useEffect(() => { window.addEventListener('resize', handleResize); }, []); Solusi: useEffect(() => { window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, []); Terlalu Banyak useEffect yang Redundant Kadang kita bisa gabungkan beberapa useEffect jadi satu daripada bikin 3 efek berbeda yang sebenarnya bisa dikelola bareng. Tips: Kelola efek yang berkaitan di satu useEffect, supaya lebih rapi dan terkontrol. Tips dan Best Practice ❌ Jangan pakai useEffect buat logika render biasa (misal if, map, dll).🔄 Hindari infinite loop: pastikan dependensinya benar.🧹 Pakai cleanup kalau ada efek yang harus dibersihkan (interval, event listener). Contoh Cleanup: useEffect(() => { const interval = setInterval(() => { console.log('Running...'); }, 1000); return () => { clearInterval(interval); }; }, []); Kesimpulan 🧠 useState: Buat nyimpen dan update data lokal di komponen.⚡ useEffect: Buat efek samping di luar React seperti API, localStorage, DOM.Kombinasikan keduanya buat bikin komponen interaktif dan dinamis. Kalau komponenmu butuh “ingat sesuatu” dan “ngelakuin sesuatu di luar React”, maka useState dan useEffect adalah senjata wajib kamu. 📚 Artikel Terkait Biar makin mantap belajar React, kamu bisa lanjut baca artikel-artikel berikut: Mengenal Komponen di React JS: Functional vs Class Pelajari perbedaan antara komponen class dan functional, serta kenapa sekarang banyak developer lebih memilih functional component + hooks!Cara Deploy Website Statis ke Vercel Lewat GitHub (Lengkap + Contoh) Setelah paham useState dan useEffect, saatnya publish proyek kamu ke internet. Artikel ini panduannya step-by-step! 🎓 Rekomendasi Kelas Gratis Mau langsung praktik dan bikin project beneran? Coba kelas gratis dari BuildWithAngga berikut: 🔗 Membuat Website Voucher Game dengan Terintegrasi API VocaGame Di kelas ini kamu bakal belajar cara ambil data dari API, pakai React Hooks (yes, termasuk useState dan useEffect!), dan bikin tampilan interaktif. Cocok banget buat pemula!

Kelas Tutorial Next JS 15 Mengatur Website Agar Lebih SEO Friendly di BuildWithAngga

Tutorial Next JS 15 Mengatur Website Agar Lebih SEO Friendly

Kalau kamu sedang ingin membangun website modern untuk keperluan bisnis online, Next JS 15 adalah salah satu pilihan paling make sense di zaman sekarang. Kenapa? Karena framework ini dirancang bukan cuma untuk kemudahan pengembangan, tapi juga untuk performa dan visibilitas website kamu di mesin pencari seperti Google. Di era digital seperti sekarang, punya website aja gak cukup. Website kamu harus bisa ditemukan dengan mudah oleh calon pelanggan, apalagi kalau kamu jualan lewat landing page atau punya katalog produk online. Nah, di sinilah peran SEO (Search Engine Optimization) jadi sangat penting. Banyak bisnis gagal bersaing karena mereka fokus ke tampilan, tapi lupa optimasi struktur dan performa teknis yang disukai mesin pencari. Untungnya, Next JS datang membawa solusi lengkap: selain powerful buat developer, dia juga paunya fitur bawaan yang siap bantu kamu bersaing secara organik di Google. Tanpa perlu terlalu banyak konfigurasi ribet seperti zaman pakai framework lama, di Next JS semuanya sudah disiapkan: mulai dari struktur folder yang SEO-friendly, rendering strategi yang bisa disesuaikan, sampai dukungan built-in untuk metadata dan optimalisasi gambar. Semua ini bikin website kamu bisa lebih cepat di-load dan lebih mudah dipahami oleh crawler-nya Google. Next JS Punya Fitur-Fitur yang Memperkuat SEO Website Bisnis Salah satu hal keren dari Next JS adalah dia ngerti banget kebutuhan pebisnis online. Framework ini bukan cuma mikirin gimana developer bisa kerja cepat, tapi juga mikirin hasil akhirnya: website yang cepat, stabil, dan SEO-friendly. Misalnya, Next JS bisa membantu kita menerapkan teknik rendering yang sesuai dengan halaman yang kita buat. Untuk halaman produk atau landing page, kita bisa pakai static rendering supaya kecepatan maksimal dan bisa di-crawl dengan baik. Untuk halaman yang sering berubah datanya, kita bisa pakai server rendering atau ISR (Incremental Static Regeneration) supaya tetap optimal di mata mesin pencari. Selain itu, Next JS juga punya sistem penulisan metadata yang rapi. Kamu bisa atur title, description, dan tag lain secara fleksibel di setiap halaman. Ini penting banget buat SEO, karena search engine butuh informasi ini buat menampilkan konten kamu dengan baik di hasil pencarian. Dan masih banyak lagi fitur menarik lainnya yang akan kita pelajari bersama di artikel ini: mulai dari penggunaan image yang otomatis teroptimasi, struktur URL yang bersih, sampai integrasi dengan berbagai alat analitik. Kalau kamu serius ingin websitemu tampil di halaman pertama Google dan membantu bisnis makin dikenal orang, maka pelajari SEO lewat Next JS ini bisa jadi keputusan penting yang membuka banyak peluang baru. Yuk kita lanjut kae bagian berikutnya dan bahas satu per satu fitur yang bisa kamu manfaatkan. Tata Cara Menggunakan generateMetadata() untuk SEO pada Proyek Next JS Di Next JS 15 dengan App Router, pengaturan SEO seperti title dan description halaman sekarang jadi lebih rapi dan terstruktur. Semua itu bisa dilakukan dengan menggunakan fungsi generateMetadata() yang disediakan khusus untuk digunakan di setiap file page. Fungsi ini memungkinkan kita untuk mengatur metadata secara dinamis atau statis, tergantung dari jenis halaman dan kebutuhannya. Hal ini sangat berguna saat kita ingin mengoptimalkan SEO berdasarkan konten yang muncul di halaman tersebut, seperti judul artikel, nama produk, atau informasi kota tertentu. Berikut adalah contoh penggunaan generateMetadata() secara lengkap di halaman detail kota: // app/city/[slug]/page.tsx import { Metadata } from 'next' import { cities } from '@/data/cities.mock' type Props = { params: { slug: string } } export async function generateMetadata({ params }: Props): Promise<Metadata> { const city = cities.find((item) => item.slug === params.slug) if (!city) { return { title: 'City Not Found – Angga Office', description: 'Sorry, the city you are looking for does not exist.', } } return { title: `${city.name} Office Spaces – Angga Office`, description: `Explore premium office space and coworking in ${city.name}. Book your space today and grow your business with Angga Office.`, openGraph: { title: `${city.name} Office Spaces – Angga Office`, description: `Explore premium office space and coworking in ${city.name}.`, images: [ { url: city.thumbnail, width: 1200, height: 630, alt: `${city.name} Office`, }, ], }, } } export default function CityDetailPage({ params }: Props) { const city = cities.find((item) => item.slug === params.slug) if (!city) { return <div className="text-center py-20">City not found</div> } return ( <div className="max-w-4xl mx-auto py-10"> <h1 className="text-3xl font-bold mb-4">{city.name}</h1> <img src={city.thumbnail} alt={city.name} className="rounded-xl" /> <p className="mt-4 text-gray-600"> Discover the best office spaces available in {city.name}. Choose your ideal location and get started today. </p> </div> ) } Penjelasan singkatnya begini: kita memanfaatkan generateMetadata() untuk mengambil data berdasarkan params.slug, lalu mengembalikan objek metadata seperti title, description, dan openGraph. Dengan begini, setiap halaman kota punya metadata yang unik dan sesuai isi kontennya, yang tentunya sangat bagus untuk SEO. Oh ya, kalau kamu pakai Next Image dan punya thumbnail yang tajam dan cepat dimuat, itu juga bantu banget memperkuat nilai SEO dan user expeerience. Fitur ini bisa kamu terapkan di berbagai jenis halaman dinamis lain, seperti halaman produk, artikel blog, atau detail kursus. Jadi metadata kamu selalu relevan dan mendukung ranking pencarian organik. Tata Cara Menggunakan Open Graph (OG) untuk SEO pada Proyek Next JS Open Graph (OG) adalah standar metadata yang digunakan oleh media sosial seperti Facebook dan LinkedIn untuk menampilkan preview yang menarik saat halaman website kamu dibagikan. Nah, di Next JS 15 dengan App Router, kita bisa menyisipkan data OG ini langsung dari fungsi generateMetadata(). Cara penggunaannya hampir sama seperti metadata biasa, kita cukup tambahkan properti openGraph dalam return dari generateMetadata(). Biasanya OG berisi informasi seperti title, description, url, dan images. Berikut adalah contoh implementasi openGraph untuk halaman detail sebuah produk atau kota: // app/city/[slug]/page.tsx import { Metadata } from 'next' import { cities } from '@/data/cities.mock' type Props = { params: { slug: string } } export async function generateMetadata({ params }: Props): Promise<Metadata> { const city = cities.find((item) => item.slug === params.slug) if (!city) { return { title: 'City Not Found – Angga Office', description: 'The city you are looking for does not exist.', } } return { title: `${city.name} Office Spaces – Angga Office`, description: `Explore premium office spaces in ${city.name}. Boost your team's productivity today.`, openGraph: { title: `${city.name} Office Spaces – Angga Office`, description: `Explore premium office spaces in ${city.name}. Book your location today.`, url: `https://yourdomain.com/city/${city.slug}`, siteName: 'Angga Office', images: [ { url: city.thumbnail, width: 1200, height: 630, alt: `${city.name} Office Thumbnail`, }, ], locale: 'en_US', type: 'website', }, } } Dengan cara ini, saat pengguna share halaman tersebut di media sosial, akan muncul preview lengkap dengan gambar, judul, dan deskripsi yang sesuai — tidak cuma tampil teks acak dari halaman kamu. Ini sangat membantu meningkatkan engagemeent dari media sosial ke website kamu. Tata Cara Menambahkan Twitter Card Support untuk SEO pada Proyek Next JS Selain Open Graph, Twitter punya format sendiri untuk menampilkan preview saat link dibagikan, yaitu Twitter Card. Untungnya, Next JS juga mendukkung hal ini lewat properti twitter dalam fungsi generateMetadata(). Kamu bisa mengatur jenis kartu, gambar, dan keterangan yang akan muncul saat link halaman dibagikan di Twitter. Berikut contoh implementasinya: // app/city/[slug]/page.tsx import { Metadata } from 'next' import { cities } from '@/data/cities.mock' type Props = { params: { slug: string } } export async function generateMetadata({ params }: Props): Promise<Metadata> { const city = cities.find((item) => item.slug === params.slug) if (!city) { return { title: 'City Not Found – Angga Office', description: 'Sorry, city data is not available.', } } return { title: `${city.name} Office Spaces – Angga Office`, description: `Get access to professional office spaces in ${city.name} with top-class facilities.`, twitter: { card: 'summary_large_image', title: `${city.name} Office Spaces – Angga Office`, description: `Get access to premium coworking and office rentals in ${city.name}.`, site: '@AnggaOffice', creator: '@AnggaOfficial', images: [city.thumbnail], }, } } Dengan menambahkan dukungan Twitter Card, kamu memberikan kesan profesional dan siap bersaing di dunia digital. Ketika pengguna membagikan halaman kamu di Twitter, akan muncul gambar besar, judul, dan deskripsi yang kamu atur — bukan sekadar link polos. Dua kombinasi antara Open Graph dan Twitter Card ini merupakan strategi yang sangat kuat untuk meningkatkan klik dan daya tarik website kamu dari social media, yang tentunya sangat berpengaruh terhadap SEO dan traffic jangka panjang. Tata Cara Mengatur Sitemap dan robots.txt untuk SEO pada Proyek Next JS Supaya website kamu lebih cepat dikenali dan diindeks oleh Google maupun mesin pencari lainnya, kamu perlu menyiapkan dua hal penating: sitemap.xml dan robots.txt. Keduanya bekerja sama membantu crawler mesin pencari menavigasi struktur website kamu dengan benar dan efisien. Di Next JS, khususnya versi terbaru dengan App Router, kamu bisa menggunakan fitur bawaan untuk membuat file-file ini secara dinamis lewat app/ directory. Untuk membuat sitemap, kamu bisa membuat file sitemap.xml/route.ts di dalam folder app/. Ini akan menghasilkan endpoint /sitemap.xml secara otomatis. Kamu bisa buat list URL dari data statis atau dinamis, lalu tampilkan sebagai XML. Berikut contoh pengaturannya: // app/sitemap.xml/route.ts import { cities } from '@/data/cities.mock' export async function GET() { const baseUrl = '<https://buildwithangga.com>' const staticPages = ['', '/about', '/contact'].map((path) => { return `<url><loc>${baseUrl}${path}</loc></url>` }) const dynamicCityPages = cities.map((city) => { return `<url><loc>${baseUrl}/city/${city.slug}</loc></url>` }) const xml = ` <?xml version="1.0" encoding="UTF-8"?> <urlset xmlns="<http://www.sitemaps.org/schemas/sitemap/0.9>"> ${staticPages.join('')} ${dynamicCityPages.join('')} </urlset> `.trim() return new Response(xml, { headers: { 'Content-Type': 'application/xml', }, }) } Dengan file ini, saat kamu buka https://yourdomain.com/sitemap.xml, akan muncul semua URL penting dalam format yang bisa dipahami Googlebot. Selanjutnya untuk robots.txt, kamu bisa buat file robots.txt/route.ts agar otomatis tersedia di URL /robots.txt. File ini memberi tahu crawler halaman mana yang boleh atau tidak boleh diakses. Berikut contohnya: // app/robots.txt/route.ts export async function GET() { const content = ` User-agent: * Allow: / Sitemap: <https://yourdomain.com/sitemap.xml> `.trim() return new Response(content, { headers: { 'Content-Type': 'text/plain', }, }) } Di sini, User-agent: * artinya aturaen ini berlaku untuk semua bot. Allow: / berarti semua halaman diizinkan untuk di-crawl. Baris terakhir menunjukkan lokasi sitemap agar bot bisa mengaksesnya dengan mudah. Kombinasi sitemap.xml dan robots.txt ini sangat penting untuk SEO teknikal. Google akan lebih cepat memahami halaman apa saja yang penting di website kamu, dan menghindari halaman yang tidak perlu, sehingga meningkatkan performa indexing dan ranking halamanmu di hasil pencarian. 10 Kesalahan yang Dapat Merusak SEO pada Proyek Next JS Meskipun Next JS punya fitur-fitur bawaan yang sangat mendukung SEO, tetap ada banyak kesalahan umum yang bisa bikin ranking website kamu jeblok di hasil pencarian. Di bawah ini adalah daftar kesalahan penting yang perlu kamu hindari, lengkap dengan contoh kasus nyata dalam proyek Next JS. Tidak Mengatur Metadata Secara Dinamis di Halaman Dinamis Banyak developer hanya fokus mengatur metadata di homepage atau halaman statis saja. Padahal, halaman dinamis seperti detail produk atau artikel juga butuh metadata yang unik agar bisa tampil optimal di hasil pencarian. // SALAH: Metadata tidak disesuaikan dengan data konten export const metadata = { title: 'Produk - My Store Angga', description: 'Detail produk di toko kami.', } // BENAR: Gunakan generateMetadata untuk metadata yang dinamis export async function generateMetadata({ params }) { const product = await getProduct(params.slug) return { title: `${product.name} - My Store`, description: product.description, } } Tidak Menggunakan Semantic HTML seperti , , , dan Penggunaan tag HTML biasa seperti <div> tanpa struktur yang jelas bisa menyulitkan mesin pencari memahami hierarki konten halaman kamu. // SALAH return ( <div> <div>Ini judul</div> <div>Konten utama</div> </div> ) // BENAR return ( <main> <header> <h1>Ini judul</h1> </header> <article> <p>Konten utama</p> </article> </main> ) Mengabaikan Alt Text pada Gambar Gambar tanpa alt membuat aksesibilitas berkurang dan SEO jadi turun karena mesin pencari tidak bisa memahami isi gambar. // SALAH <Image src="/product.jpg" width={500} height={300} /> // BENAR <Image src="/product.jpg" alt="Gambar produk A" width={500} height={300} /> Tidak Mengatur Robots.txt dan Sitemap.xml Tanpa dua file ini, crawler Google bisa kesulitan menjelajahi halaman penting, atau malah mengindeks halaman yang tidak perlu seperti /admin atau /checkout. // Sitemap dan robots telah dijelaskan di jawaban sebelumnya Menggunakan Client Component untuk Halaman Informasi Statis Client Component butuh JavaScrript untuk render halaman, yang bisa menunda proses indexing oleh mesin pencari. // SALAH 'use client' export default function AboutPage() { return <div>Tentang Kami</div> } // BENAR export default function AboutPage() { return <div>Tentang Kami</div> } Konten Halaman Muncul Terlambat karena Fetching di Client Kalau data penting seperti deskripsi produk diambil di client, mesin pencari bisa gagal membaca kontennya sebelum rendering selesai. // SALAH 'use client' useEffect(() => { fetch('/api/product').then(setData) }, []) // BENAR export async function generateMetadata() { const product = await getProduct() return { title: product.name } } Tidak Mengatur Canonical URL Tanpa canonical tag, halaman dengaan konten yang sama bisa dianggap sebagai duplicate content dan bikin ranking turun. // Contoh metadata dengan canonical export async function generateMetadata({ params }) { return { title: 'Detail Produk', alternates: { canonical: `https://yourdomain.com/product/${params.slug}`, }, } } Menggunakan Gambar dari Sumber Eksternal Tanpa Konfigurasi Kalau kamu pakai <Image> dari Next untuk gambar eksternal tanpa izin domain di next.config.js, gambar tidak akan muncul dan SEO jadi buruk. // next.config.js images: { domains: ['external-image.com'], } Struktur URL Tidak Konsisten dan Tidak Ramah Mesin Pencari Gunakan URL yang bersih dan deskriptif. Hindari penggunaan query string acak atau angka ID saja. // SALAH: /product?id=12345 // BENAR: /product/tas-kulit-original Tidak Menambahkan Social Sharing Metadata (OG & Twitter Card) Kalau metadata OG dan Twitter Card tidak tersedia, halaman kamu terlihat membosankan saat dibagikan di media sosial, dan itu bisa menurunkan CTR (click-through rate). export async function generateMetadata() { return { title: 'Kelas BWA Terbaik', openGraph: { title: 'Produk Terbaik', description: 'Dapatkan produk terbaik di toko kami.', images: ['/product.jpg'], }, twitter: { card: 'summary_large_image', title: 'Produk Terbaik', images: ['/product.jpg'], }, } } Dengan menghindari 10 kesalahan ini, kamu bisa memaksimalkan potensi SEO dari website Next JS kamu. Mesin pencari akan lebih mudah memahami, merayapi, dan menampilkan konten kamu di hasil pencarian yang tepat. Penutup dan Saran untuk Web Developer Pemula Hingga Expert Belajar Next JS untuk SEO memang bukan hal yang instan, tapi percayalah — ini investasi jangka panjang yang akan sangat menguntungkan. Dengan menguasai praktik-praktik SEO seperti metadata, Open Graph, Twitter Card, sitemap, robots.txt, hingga struktur konten yang ramah crawler, kamu tidak hanya menjadi developer yang bisa bikin website, tapi developer yang ngerti strategi bisnis digital. Untuk kamu yang masih pemula atau sudah menengah tapi ingin naik level jadi web developer expert, saran terbaiknya: belajarlah langsung dari mentor yang sudah berpengalaman dan pernah menjalankan proyek nyata. Di BuildWithAngga, kamu bisa belajar bareng mentor expert yang akan bimbing kamu step-by-step, bukan cuma teori tapi langsung praktik di proyek profesional. Beberapa benefit unggulan yang kamu bisa dapatkan: Belajar dari studi kasus nyata, bukan hanya dari dokumentasiKelas berkualitas tinggi dengan sistem pembelajaran fleksibelAkses seumur hidup ke materi dan update terbaruKomunitas aktif untuk diskusi dan portfolio reviewSertifikat yang bisa menunjang karir profesional dan freelance Dan yang paling penting: semua ini didesain untuk mempersiapkan kamu bekerja secara remote. Artinya kamu bisa kerja dari mana aja, gabung di perusahaan internasional, atau jadi freelancer yang dibayar mahal — asalkan kamu punya skill dan mindset yang benar. Yuk mulai upgrade dirimu hari ini. Jangan cuma jadi web developer biasa. Jadi developer yang dicari karena bisa bangun website yang cepat, scalable, dan siap masuk halaman satu Google. Belajar bareng mentor expert di BuildWithAngga sekarang dan siapkan diri kamu buat karir digital yang sukses. 🚀