Akses kelas selamanya

Ambil Promo
flash sale
hamburger-menu

Tips All

Meningkatkan skills menjadi 1% lebih baik

Reset
Kelas Panduan Lengkap Animasi Tailwind CSS v4: Siap Pakai & Custom Sendiri di BuildWithAngga

Panduan Lengkap Animasi Tailwind CSS v4: Siap Pakai & Custom Sendiri

Lo pernah nggak sih ngerasa tampilan website lo itu... flat banget? Kayak hidup segan, mati tak mau. Nah, di era sekarang, tampilan UI yang dinamis dan interaktif tuh udah jadi kebutuhan, bukan sekadar bonus. Salah satu cara paling gampang buat bikin tampilan web lo lebih hidup adalah pakai animasi. Untungnya, kalau lo pakai Tailwind CSS v4, lo nggak perlu repot ngoding animasi dari nol. Tailwind udah nyediain berbagai animasi siap pakai yang tinggal comot. Bahkan, kalau lo ngerasa animasi default-nya kurang nendang, lo bisa bikin custom animasi versi lo sendiri dengan mudah lewat konfigurasi di TailwindCSS. Di artikel ini, gue bakal ajak lo ngulik bareng soal: Animasi bawaan (yang tinggal pakai)Cara bikin animasi custom sendiriTips dan best practice biar animasi lo nggak lebay tapi tetap kece Yuk, kita mulai ngebahas panduan lengkap animasi Tailwind CSS v4, dari yang siap pakai sampai lo bisa bikin animasi versi lo sendiri! Apa Itu Animasi di Tailwind CSS? Sebelum lo langsung terjun pakai animasi bawaan atau bikin yang custom, penting banget buat ngerti dulu konsep dasarnya. Soalnya, animasi di Tailwind itu ada dua jenis utama: transition dan animation. Keduanya punya fungsi beda, tapi sering dipakai barengan buat bikin efek yang mulus. Transition Transition itu lebih ke perubahan gaya secara halus. Misalnya lo mau bikin tombol berubah warna pas di-hover. Nah, transisi ini ngebuat perubahannya nggak langsung “jepret”, tapi pelan-pelan, lebih enak dilihat. Contoh simple: <button class="bg-blue-500 hover:bg-blue-700 transition-colors duration-300"> Klik Gue </button> Lihat kan? Di situ kita pakai transition-colors biar efek hover-nya smooth. Animation Kalau animation, ini lebih kompleks. Lo bisa bikin elemen muter (spin), mantul-mantul (bounce), muncul perlahan, atau bahkan efek masuk dari samping. Tailwind udah sediain beberapa utility animate-* yang bisa langsung lo pake. Contoh: <div class="animate-bounce w-6 h-6 bg-red-500 rounded-full"></div> Hasilnya? Si bulat merah bakal mantul-mantul kayak bola pingpong. Seru, kan? Singkatnya: Transition → buat efek perubahan gaya (warna, ukuran, opacity, dll).Animation → buat efek gerak yang lebih kompleks dan bisa diatur pakai @keyframes. Jadi sekarang lo udah ngerti, kan, perbedaan dasar antara dua jenis animasi di Tailwind CSS? Yuk, lanjut ke bagian yang paling ditunggu: animasi keren siap pakai yang langsung bisa lo comot! Animasi Siap Pakai di Tailwind CSS v4 Tailwind CSS v4 hadir bawa beberapa animasi built-in yang bisa langsung lo pake tanpa harus nulis @keyframes manual. Cukup tambahin class animate-* ke elemen lo, dan boom — elemen lo langsung punya efek gerak yang kece. Animasi Built-in Tailwind CSS v4 + Contoh Penggunaan Lengkap Di bawah ini gue rangkum empat animasi bawaan paling sering dipakai di Tailwind CSS v4, lengkap sama penjelasan “kapan dipakai” dan potongan kode siap copy-paste. Tinggal ganti teks, warna, atau ukuran sesuai selera—langsung hidupin UI lo! 🚀 animate-spin — ikon loading muter Kapan dipakai? Saat butuh indikator proses (loaders, refresher). Cara kerja: elemen diputar 360° terus-menerus. <!-- Loader bulat --> <div class="h-10 w-10 border-4 border-blue-500 border-t-transparent rounded-full animate-spin"></div> <!-- Loader pakai icon (Heroicons/Feather/FontAwesome, dll.) --> <svg class="h-6 w-6 text-blue-500 animate-spin" viewBox="0 0 24 24" fill="none"> <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" class="opacity-25"/> <path d="M4 12a8 8 0 018-8" stroke="currentColor" stroke-width="4" class="opacity-75"/> </svg> Hasilnya: animate-spin animate-bounce — elemen mantul-mantul Kapan dipakai? Buat narik perhatian (notifikasi, CTA). Cara kerja: elemen lompat naik-turun secara periodik. <!-- Badge notifikasi --> <span class="inline-flex items-center px-3 py-1 text-sm font-medium text-white bg-green-500 rounded-full animate-bounce"> ✔ Berhasil disimpan! </span> <!-- Panah scroll ke bawah --> <svg class="h-8 w-8 text-gray-700 animate-bounce mt-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/> </svg> Hasilnya: animate-bounce Tip: Kebanyakan bounce bikin pusing. Pakai di spot penting aja, lalu matikan setelah user interaksi (via JS → onClick /tambah animate-none). animate-ping — gelombang radar Kapan dipakai? Menandai posisi (online status, titik map). Cara kerja: muncul lingkaran membesar + memudar, terus mengulang. <!-- Titik lokasi dengan efek ping --> <span class="relative flex h-3 w-3"> <span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-red-400 opacity-75"></span> <span class="relative inline-flex rounded-full h-3 w-3 bg-red-500"></span> </span> Hasilnya: animate-ping Tip: Ping agak “berat” di banyak elemen. Batasi di satu-dua titik penting. animate-pulse — shimmer loading Kapan dipakai? Skeleton screen atau button “bernafas”. Cara kerja: opacity elemen naik-turun perlahan. <!-- Skeleton --> <div class="mx-auto w-full max-w-sm rounded-md p-4"> <div class="flex animate-pulse space-x-4"> <div class="size-10 rounded-full bg-gray-200"></div> <div class="flex-1 space-y-6 py-1"> <div class="h-2 rounded bg-gray-200"></div> <div class="space-y-3"> <div class="grid grid-cols-3 gap-4"> <div class="col-span-2 h-2 rounded bg-gray-200"></div> <div class="col-span-1 h-2 rounded bg-gray-200"></div> </div> <div class="h-2 rounded bg-gray-200"></div> </div> </div> </div> </div> Tip: Matikan pulse ketika data udah ready: ganti class ke warna final + hapus animate-pulse. Hasilnya: animate-pulse Bikin Animasi Custom Sendiri di Tailwind CSS v4 Di Tailwind v4 bikin animasi jadi lebih mudah cuma pakai @keyframesaja dijamin gak bakal ribet. Berikut kode untuk konfigurasi Tailwind, masukkan kode ini di tag <head> yaa! Langsung aja kita bikin..! animate-fade-in CSS: <style type="text/tailwindcss"> @theme { --animate-fade-in: fade-in 0.6s ease-out forwards; @keyframes fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } } </style> HTML: <button type="button" class="px-4 py-1.5 bg-blue-500 text-white rounded-md animate-fade-in"> Fade </button> Hasilnya: animate-fade-in animate-slide-in CSS: <style type="text/tailwindcss"> @theme { --animate-slide-in: slide-in 0.5s ease-out forwards; @keyframes slide-in { 0% { transform: translateX(100%); } 100% { transform: translateX(0); } } } </style> HTML: <button type="button" class="px-4 py-1.5 bg-blue-500 text-white rounded-md animate-slide-in"> Slide </button> Hasilnya: animate-slide-in animate-blur CSS: <style type="text/tailwindcss"> @theme { --animate-blur: blur 0.6s ease-out forwards; @keyframes blur { 0% { filter: blur(8px); opacity: 0; } 100% { filter: blur(0); opacity: 1; } } } </style> HTML: <button type="button" class="px-4 py-1.5 bg-blue-500 text-white rounded-md hover:animate-blur" > Blur </button> Hasilnya: animate-blur animate-expand CSS: <style type="text/tailwindcss"> @theme { --animate-expand: expand 0.4s ease-out forwards; @keyframes expand { 0% { transform: scale(0.8); } 100% { transform: scale(1); } } } </style> HTML: <button type="button" class="px-4 py-1.5 bg-blue-500 text-white rounded-md animate-expand"> Expand </button> Hasilnya: animate-expand animate-shrink CSS: <style type="text/tailwindcss"> @theme { --animate-shrink: shrink 0.4s ease-out forwards; @keyframes shrink { 0% { transform: scale(1.1); } 100% { transform: scale(1); } } } </style> HTML: <button type="button" class="px-4 py-1.5 bg-blue-500 text-white rounded-md animate-shrink"> Shrink </button> Hasilnya: animate-shrink animate-pop CSS: <style type="text/tailwindcss"> @theme { --animate-pop: pop 0.3s ease-out; @keyframes pop { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); } } } </style> HTML: <button type="button" class="px-4 py-1.5 bg-blue-500 text-white rounded-md animate-pop"> Pop </button> Hasilnya: aniimate-pop animate-shake CSS: <style type="text/tailwindcss"> @theme { --animate-shake: shake 0.6s ease-in-out both; @keyframes shake { 0%, 100% { transform: translateX(0); } 20%, 60% { transform: translateX(-6px); } 40%, 80% { transform: translateX(6px); } } } </style> HTML: <button type="button" class="px-4 py-1.5 bg-blue-500 text-white rounded-md animate-shake"> Shake </button> Hasilnya: animate-shake animate-wobble CSS: <style type="text/tailwindcss"> @theme { --animate-wobble: wobble 1s ease-in-out infinite; @keyframes wobble { 0%, 100% { transform: rotate(0deg); } 25% { transform: rotate(3deg); } 75% { transform: rotate(-3deg); } } } </style> HTML: <button type="button" class="px-4 py-1.5 bg-blue-500 text-white rounded-md animate-wobble"> Wobble </button> Hasilnya: animate-wobble animate-seesaw CSS: <style type="text/tailwindcss"> @theme { --animate-seesaw: seesaw 1.2s ease-in-out infinite; @keyframes seesaw { 0%, 100% { transform: rotate(0deg); } 50% { transform: rotate(8deg); } 60% { transform: rotate(6deg); } 70% { transform: rotate(8deg); } 80% { transform: rotate(0deg); } 90% { transform: rotate(2deg); } } } </style> HTML: <button type="button" class="px-4 py-1.5 bg-blue-500 text-white rounded-md animate-seesaw"> Seesaw </button> Hasilnya: animate-seesaw Rangkuman ✅ Kenapa butuh animasi custom? Karena lo bisa bikin efek sesuai karakter brand lo: masuk dari samping, zoom in, fade out, dll. ✅ Bisa digabung sama Tailwind utility lain? Bisa banget. Lo tetep bisa atur delay, duration, dan ease secara fleksibel. Tips & Best Practices 🚫 Jangan Berlebihan Animasi itu kayak bumbu. Kalau kebanyakan, malah bikin eneg. Pakai secukupnya buat highlight interaksi penting aja (kayak buka modal, hover tombol, dsb). 🧑‍🦯 Gunakan motion-safe Biar animasi nggak mengganggu pengguna yang pakai preferensi "reduce motion", kamu bisa tambahkan prefix ini: <div class="motion-safe:animate-fade">Aman buat semua</div> 📱 Cek Performa di Perangkat Low-End Beberapa animasi berat (seperti shadow blur + scale + opacity sekaligus) bisa bikin patah-patah di HP kentang. Coba tes di device real kalau bisa. Penutup Nah, sampai sini lo udah ngerti gimana powerful-nya animasi di Tailwind CSS v4. Mulai dari animasi siap pakai, bikin custom animasi sendiri pakai CSS, sampai nerapin di komponen kayak modal — semuanya bisa lo lakuin tanpa ribet. Dengan fitur baru di v4, lo bisa: Bikin animasi sekali, pakai di mana aja.Nggak perlu oprek tailwind.config.js.Lebih fleksibel buat trigger animasi via JavaScript. Intinya? UI lo bakal jadi lebih hidup dan interaktif, tanpa harus ngoding panjang-panjang. Kalau lo pengen explore lebih jauh, nih gue kasih beberapa referensi keren: 📘 Dokumentasi Resmi Tailwind CSS - Animation🧪 Tailwind Play - Coba Langsung di Browser Ini gue kasih juga rekomendasi kelas gratis dari BuildWithAngga buat memperdalam TailwindCSS: 1. CSS Tailwind Web Design Kelas ini cocok banget buat lo yang pengen ngedesain website modern dan clean pake Tailwind CSS. Cocok buat pemula maupun yang udah pernah nyoba Tailwind tapi pengen lebih rapi dan estetik. 2. Belajar Tailwind CSS untuk Pemula Website Designer Namanya juga buat pemula, jadi tenang aja, lo bakal dipandu dari nol. Cocok buat lo yang masih suka bingung bedain mt-4 sama mb-4 😆 3. HTML5 + Tailwind CSS: Creating Modern Eye-Catching Website Gabungan antara HTML5 dan Tailwind, lo bakal diajarin bikin website yang gak cuma fungsional tapi juga menarik secara visual. Pokoknya gak cuma ngoding asal tampil. 4. Vue 3 + Tailwind CSS: Membuat Komponen Autocomplete Khusus buat lo yang udah mainan Vue 3, kelas ini ngajarin cara bikin komponen autocomplete yang reusable dan stylish pake Tailwind. Keren buat portofolio lo juga nanti! Semangat eksplor, bro! Animasi itu bukan cuma estetika — tapi juga bagian dari komunikasi desain yang baik. Jangan takut bereksperimen! 💪

Kelas Cara Deploy Website Statis ke Vercel lewat GitHub (Lengkap + Contoh) di BuildWithAngga

Cara Deploy Website Statis ke Vercel lewat GitHub (Lengkap + Contoh)

Daftar Isi PendahuluanProyek Saya dari Shaynakit (FREE)Deploy GitHubPushAturan Online Website Statis di VercelAturan Default (Public)Konvensi Umum di Dunia WebOptimasi Tanpa KonfigurasiMembedakan Source Code & File Siap TayangMencegah Error & Akses File yang Gak PerluLangkah-Langkah PublicAturan Tailwind CSS (Src)Struktur FolderTambahkan file vercel.json di root projectOnline-kan di VercelStep 1: Upload ke GitHubStep 2: Daftar Akun VercelStep 3: Login ke Overview VercelStep 4: Klik “New Project”Step 5: Klik tombol import yang buildwithanggaStep 6: Klik DeployStep 7: HasilPenutup Pendahuluan Punya website statis udah jadi, tampilannya cakep, animasi smooth, warnanya pas... tapi masih ngumpet di folder, Wah, sayang banget dong. Daripada disimpan sendiri dan cuma kamu doang yang lihat, mending langsung naikin ke internet biar bisa dipamerin ke dunia. Caranya? Gampang banget! Cuma butuh dua alat andalan: GitHub buat naro proyeknya, dan Vercel buat nampilin ke internet. Kayak duo maut: satu nyimpen, satu nampilin. Di artikel ini, kita bakal bahas step by step-nya mulai dari upload ke GitHub, sampai proyek kamu tampil kece di Vercel. Nggak perlu ribet, nggak perlu coding aneh-aneh. Yuk, kita gas bareng-bareng. Proyek Saya dari Shaynakit (FREE) Shaynakit - Resto Di tutorial kali ini, kita bakal sru-seruan bareng ngebedah proyek keren dari Shaynakit. Kabar baiknya: ini 100% gratis, dan yang makin mantep, kodenya udah siap tempur. Jadi lo nggak perlu mulai dari nol, tinggal colok, modif dikit, langsung jalan. Nggak ribet, nggak bikin kening berkerut, pokoknya ngoding jadi fun banget! Shaynakit ini tuh kayak buffet buat front-end developer tinggal pilih desain yang lo suka, semua udah sepaket sama kodenya. Ada versi gratis, ada juga yang premium. Tapi santai, yang gratis pun udah cukup loyal kok. Biasanya yang dibatesin cuma jumlah halaman aja. Nah, kalau yang premium? Itu sih udah kayak pesta coding semua elemen tinggal comot, tinggal pakai, beres! Sekarang masuk ke inti dari semuanya: gimana cara dapetin template gratisnya. Gampang banget, nggak perlu mantra khusus. Cukup ikutin langkah-langkah ini: Buka situs utamanya di sini: https://shaynakit.com/landing.Klik menu Register atau langsung aja meluncur ke https://shaynakit.com/register buat daftar akun dulu.Setelah berhasil daftar dan login, buka halaman template yang mau dipakai di sini: https://shaynakit.com/details/resto-restaurant-landing-page-html-tailwind-css-template.Klik tombol Download, lalu pilih opsi Free Trial.Lanjut klik Start Today buat mulai akses gratisnya.Setelah itu, balik lagi ke halaman template tadi dan klik tombol Download sekali lagi.File-nya bakal langsung keunduh dalam format .zip.Simpan file .zip itu ke folder lokal kamu, misalnya ke: ./source-code/resto.zip. Udah, beres. Sekarang kamu punya satu paket desain + kode yang siap kamu eksplor. Tinggal buka, utak-atik, terus bawa ke proyek kamu. Deploy Github Github - My Github GitHub itu ibarat lemari kaca super aman tempat kita naro semua karya codingan kita, entah itu proyek pribadi, kerjaan kelompok, atau bahkan eksperimen tengah malam yang cuma kamu ngerti. Di sanalah para developer dari seluruh dunia numpuk kode mereka, jadi kalau suatu saat butuh, tinggal buka lagi, atau bahkan pamerin ke dunia. Bayangin kamu lagi bikin komik, dan tiap panel kamu simpan rapi satu-satu, lengkap dengan sejarah siapa yang gambar, ubah warna, atau nambah dialog. Nah, GitHub tuh kayak arsip digital yang nyatet semua itu otomatis. Kapan kita perlu? Ya setiap kali kita ngoding dan pengen nyimpen progress, kolaborasi sama temen, atau bahkan ngelamar kerja pakai portfolio. Caranya juga gampang banget, kayak ngirim file ke Google Drive, tapi lebih kece karena setiap versi bisa kamu rewind sesuka hati. Serunya lagi, semua orang bisa intip, bantuin, bahkan ikut kontribusi. Jadi bukan cuma tempat nyimpen, tapi juga tempat ngumpulnya semangat kolaborasi developer sejagat raya. Push Pertama, buka terminal atau Git Bash, dan pastiin kamu udah ada di dalam folder proyek kamu kayak gini misalnya: VSCode - Open Project cd path/ke/buildwithangga selanjutnya kayak ngasih tahu folder kamu: “Eh bro, sekarang kamu udah jadi proyek Git ya” VSCode - Initial Project git init selanjutnya ibarat kamu masukin semua file proyek ke dalam koper buat dibawa ke GitHub. VSCode - Add All Folder git add . selanjutnya commit yaitu kayak ngasih catatan, "Oke ini versi pertama gue ya!" VSCode - Add Comment For Push git commit -m "First commit buildwithangga" Sekarang buka https://github.com ➜ Login ➜ Klik tombol New Repository. Github - New Repository Masukkan nama repo (misal: buildwithangga) Github -Fill in the Input Pilih public/privateJangan centang "Initialize this repository with a README" (biar ga bentrok)Klik Create Repository GitHub bakal kasih kamu URL repo kayak gini: Github -Create Repository <https://github.com/tegarfauzan/buildwithangga.git> Sekarang kita kasih tau Git: “Bro, ini lho alamat rumah barunya di GitHub, simpen di sana ya.” VsCode -Add Remote git remote add origin <https://github.com/tegarfauzan/buildwithangga.git> Waktunya terbang. Kirim proyek kamu ke GitHub, perintahnya gini: git push -u origin master Buka repo GitHub kamu, akhirnya tadaaa! Proyek kamu udah tampil manis di sana, siap dipamerin, dibagikan, atau dideploy ke Vercel. Seperti ini bila sudah berhasil: Github -Result Aturan Online Website Statis di Vercel Vercel - Homepage Bayangin kamu punya laptop yang nyala 24 jam, koneksi internetnya super cepat, dan bisa diakses siapa aja, kapan aja. Nah, Vercel itu ibarat laptop online yang bisa menyimpan dan menjalankan website kamu tanpa ribet. Vercel ini platform hosting yang fokus banget buat front-end dan static site mulai dari HTML biasa, CSS, sampai framework modern kayak Next.js. Kalau kamu punya website statis, artinya website kamu cuma butuh file HTML, CSS, JS, tanpa database atau server dinamis, maka Vercel ini bener-bener sahabat sejati. Misalnya kamu pakai Tailwind CSS via CLI, atau pakai CSS biasa yang ditulis manual. Vercel bakal menyajikan semua file statis itu secepat kilat. Gak perlu server-side processing, cukup upload file-nya dan... BOOM! langsung online. Aturan Default (Public) Kalau kamu deploy atau online-in proyek ke Vercel, biasanya ada cara default yang harus kamu ikutin, yaitu dengan punya folder public. Nah, di bawah ini aku jelasin kenapa sih folder public itu penting banget buat proses deploy kamu di Vercel. 1. Konvensi Umum di Dunia Web Di banyak framework modern kayak Next.js, Vue, atau React, folder public/ itu udah jadi tempat langganan buat nyimpen file-file statis yang langsung bisa diakses browser—misalnya index.html, style.css, gambar .png atau .jpg, file JavaScript, sampai favicon. Nah, karena itu udah jadi kebiasaan umum di dunia web, Vercel juga ngikutin pola itu. Jadi kalau kamu gak bilang apa-apa soal folder mana yang mau ditayangin, Vercel bakal otomatis mikir: “Oh, pasti maksudnya folder public/ nih.” 2. Optimasi Tanpa Konfigurasi Vercel emang didesain biar proses deploy itu semudah klik upload aja. Makanya, mereka bikin folder public/ jadi default. Jadi kalau kamu udah pake public/, kamu gak perlu ribet bikin vercel.json, gak usah ngatur output directory manual, tinggal masukin aja semua file HTML, CSS, JS kamu ke dalam public/, terus deploy, langsung tayang! Ini sejalan sama filosofi mereka yang namanya zero-config, alias: “Kalau kamu gak ngatur apa-apa, tenang aja, kami udah siapin jalur yang paling aman dan paling umum buat kamu.” 3. Membedakan Source Code & File Siap Tayang Misalnya kamu punya folder: src/ → tempat source code, Tailwind, JSX, dll public/ → hasil akhir / file yang siap tayang Nah, Vercel tuh paham banget alurnya developer. Mereka tahu kalau folder src/ itu biasanya isinya masih bahan mentah, perlu di-build dulu, belum siap tayang. Sedangkan folder public/ itu udah kayak etalase, tempat semua file final yang siap disajikan ke pengunjung. Jadi, berdasarkan asumsi itu, Vercel secara default langsung ngarahin domain kamu ke isi dari public/, tanpa kamu perlu ngatur-ngatur dulu. 4. Mencegah Error & Akses File yang Gak Perlu Dengan cuma nyajiin file yang ada di dalam folder public/, Vercel juga sekalian ngasih perlindungan ekstra. Jadi, file-file internal kayak .env, package.json, atau file config lainnya gak bakal ikut-ikutan tampil ke publik. Ini juga bikin performa website kamu lebih oke, karena yang disajikan cuma file statis yang memang dibutuhkan. Plus, kamu terhindar dari error aneh atau kebocoran file development yang sebenarnya gak perlu dilihat sama pengunjung. Aman, ringan, dan rapi. 5. Langkah-Langkah Public Bayangin kamu bikin website company profile semacam halaman resmi buat bisnis kamu. Atau mungkin kamu lagi bikin website portofolio buat nunjukin karya-karya kamu, landing page promosi produk, blog pribadi yang tampilannya simpel, atau sekadar playground buat ngoprek HTML & CSS Semua itu masuk ke dalam kategori website statis, karena isinya cuma HTML, CSS, dan JavaScript, tanpa backend atau database yang ribet. Kalau kayak gitu kamu perlu ikutin di bawah ini agar bisa online di Vercel: Folder public/ : Taruh semua file kamu di sini: index.html, style.css, main.js, gambar, dll. project/ └── public/ ├── index.html ├── style.css └── main.js Tipsnya simpel: pastikan kamu punya file index.html di dalam folder public/ dan semua path ke CSS atau JS menggunakan awalan / supaya pakai absolute path (contohnya /style.css bukan style.css), dan enaknya lagi, kamu gak perlu bikin file vercel.json kalau pakai cara ini, jadi lebih simpel, bersih, dan langsung bisa deploy tanpa ribet. Aturan Tailwind CSS (Src) Biasanya nih, kalau kamu pakai Tailwind CSS lewat Tailwind CLI, kamu bakal sering nemuin yang namanya folder src. Contohnya, kamu jalanin perintah kayak npx @tailwindcss/cli -i ./src/input.css -o ./src/output.css --watch, itu artinya Tailwind lagi nge-proses file yang ada di dalam folder src. Nah, cara pakai folder src ini nggak cuma buat Tailwind doang, kamu juga bisa terapin buat folder lain kalau mau. Aku bahas Tailwind karena secara default CLI-nya memang ngarah ke folder src, jadi supaya bisa lancar online di Vercel, kamu perlu trik khusus biar hasilnya bisa langsung dipakai tanpa ribet. Langsung aja pahami berikut : 1. Struktur Folder project/ ├── vercel.json ├── package.json ├── package.lock.json ├── .gitignore └── src/ ├── index.html ├── input.css ├── output.css └── script.js Misalkan kamu punya struktur proyek Tailwind kayak gini. Biasanya, di Tailwind versi 4, kamu nggak selalu butuh file tailwind.config.js secara default karena Tailwind udah makin pintar nangkep settingan dasar tanpa harus dikonfigurin manual. Nah, keuntungan dari versi 4 ini, kamu bisa dapetin struktur Tailwind yang lebih simpel dan bersih kayak yang kamu lihat sekarang, jadi nggak ribet harus bikin banyak file konfigurasi dulu sebelum mulai ngoding. 2. Tambahkan file vercel.json di root project { "builds": [ { "src": "src/**/*", "use": "@vercel/static" } ], "routes": [ { "src": "/(.*)", "dest": "/src/$1" } ] } Builds { "src": "src/**/*", "use": "@vercel/static" } Artinya semua file yang ada di dalam folder src/ beserta subfoldernya akan dianggap sebagai file statis oleh Vercel, karena plugin @vercel/static dipakai untuk langsung menyajikan file HTML, CSS, dan JS tanpa proses build, dan tanda */* menunjukkan semua file dan folder dalam src/ akan diproses dan disajikan langsung sebagai file statis oleh Vercel. Routes { "src": "/(.*)", "dest": "/src/$1" } Artinya, setiap permintaan ke URL apa pun (karena /(.*) itu wildcard) akan diarahkan ke file yang sama persis di dalam folder src/. Misalnya, kalau kamu akses /about.html, Vercel bakal sajikan file /src/about.html, atau kalau kamu akses /assets/input.css, dia akan ambil file /src/assets/input.css. Jadi, walaupun filenya ada di dalam folder src/, URL yang terlihat di browser tetap kelihatan dari root, bikin semuanya jadi rapi dan gampang diakses. Online-kan di Vercel Cara ng-online-in proyek statis ke Vercel dari folder public atau src, itu sebenarnya gampang banget, apalagi kalau konfigurasi yang tadi udah kamu terapin, ibaratnya kamu udah nyiapin "bekal" buat piknik, tinggal berangkat doang nih. Nah, sekarang, kalau bekalnya udah siap (alias konfigurasi beres), langkah selanjutnya tinggal eksekusi. Eksekusinya kayak gini: Step 1: Upload ke GitHub Github -Repository Project Pastiin dulu proyek kamu udah nangkring di GitHub. Anggep aja GitHub itu semacam cloud storage khusus developer, tempat nyimpen proyek biar bisa dijemput sama Vercel nanti. Kalau belum, upload dulu yaa, pakai Git, GitHub Desktop, atau upload manual langsung di GitHub. Step 2: Daftar Akun Vercel Sekarang buka https://vercel.com dan bikin akun Vercel. Ini kayak kamu harus punya akun ojek online dulu sebelum bisa mesen makanan. Step 3: Login ke Overview Vercel Vercel -Overview Udah punya akun? Mantap! Sekarang login ke Vercel, dan kamu bakal lihat dashboard-nya. Step 4: Klik “New Project” Vercel - Add New Langsung aja klik tombol “New Project”. Vercel akan minta akses ke akun GitHub kamu, karena dia pengin tau proyek mana yang mau kamu online-in. Step 5: Klik tombol import yang buildwithangga Vercel - Import Project Step 6: Klik Deploy Vercel - Klik Deploy Langsung klik Deploy, dan... Bumm! Proyek kamu langsung ngacir ke internet. Ibarat masak mie instan, air udah mendidih, bumbu udah masuk, mie udah mateng, tinggal sajikan. Step 7: Hasil Vercel - Deploy Success Kalau kayak gini artinya sudah berhasil. Kamu tinggal klik tombol continue aja nanti bakal di arahin untuk akses websitenya. Penutup Nah, itu dia langkah-langkah lengkap buat ngedeploy website statis ke Vercel lewat GitHub. Gampang banget, kan? Kayak lagi ngantar paket, asal alamatnya bener (GitHub), kurirnya siap (Vercel), tinggal tunggu aja nyampe ke internet. Sekarang website kamu udah bisa diakses siapa aja, kapan aja, dari mana aja. Tinggal kamu kembangkan lebih keren lagi, atau bahkan... kasih sentuhan backend dikit kalau udah siap naik level. Semoga artikel ini ngebantu kamu yang pengen tampil profesional dengan cara yang simpel. Sampai ketemu di tutorial selanjutnya, dan selamat berselancar di dunia web.

Kelas Contoh Web HTML dan Tailwind CSS yang Sudah Jadi (Siap Pakai) di BuildWithAngga

Contoh Web HTML dan Tailwind CSS yang Sudah Jadi (Siap Pakai)

Daftar Isi PendahuluanPreviewDownloadCara MenggunakanStruktur Folder & FileKode HTML & Tailwind CSSHeadBodyHeaderMainAds SectionWhy us?Popular restaurantNear you restaurantExpert chefKode JavaScriptcard.jsdropdown.jsmain.jstab.jsinput.css.gitignorepackage.jsonvercel.jsonCara MengeditBeragam Template HTML + Tailwind CSS (FREE) 🙌Penutup Pendahuluan Pernah nggak sih kamu pengen bikin website tapi bingung harus mulai dari mana? Rasanya kayak mau masak, tapi nggak punya resep bahan-bahan yang udah ada, dan nggak tahu urutannya gimana. Nah, artikel ini hadir buat bantu kamu yang baru belajar HTML dan Tailwind CSS biar nggak nyasar di awal. Di sini, kamu bakal nemuin contoh web sederhana yang udah jadi, lengkap sama struktur HTML-nya dan gaya-gaya dasarnya pakai Tailwind CSS. Serunya lagi, ini bukan cuma contoh doang, kamu bisa langsung pakai atau modifikasi sesuai gaya kamu. Jadi, daripada pusing bikin dari nol, mending mulai dari sesuatu yang udah siap santap. Siap? Yuk, kita bahas bareng-bareng. Preview Yuk, intip dulu tampilannya! Gambar di bawah ini semacam 'cuplikan trailer' dari proyek keren yang bakal kamu pelajari. Resto - Open in Browser Kalau kamu penasaran dan pengin lihat langsung hasil jadinya, tenang aja aku udah siapin link-nya di bawah ini ya. Tinggal klik aja. https://resto-rose.vercel.app/ Download Kamu nggak cuma bisa lihat aja, lho! Di sini aku juga udah sediain file proyeknya biar kamu bisa download dan cobain sendiri. Tinggal klik link Google Drive di bawah ini, terus buka pakai text editor favorit kamu. Aku sendiri sih pakai Visual Studio Code. Yuk klik di bawah ini: File Zip Proyek Resto Cara Menggunakan Biar proyeknya bisa kamu utak-atik, pastikan dulu kamu udah buka foldernya di text editor, ya. Di sini aku pakai Visual Studio Code. Terus, buka terminalnya dengan cara pencet Ctrl + backtick (``` yang di bawah tombol Esc itu, lho). Kalau udah, tinggal jalanin perintah di bawah ini: npm install Kalau kamu udah buka terminal dan ketik npm install, itu akan menjalankan proses buat ngedownload semua 'alat bantu' yang dibutuhin proyek ini. Ibaratnya kayak kamu baru pindah rumah, terus npm install itu tugas kamu buat masukin semua perabotan yang udah ada di daftar biar rumahnya langsung siap ditempati. Jadi, semua package yang dibutuhin bakal otomatis didownload ke folder node_modules. Kamu tinggal duduk manis nunggu prosesnya selesai. Setelah semua ‘perabotan’ alias package-nya udah masuk berkat npm install, sekarang saatnya kita ‘nyalain’ rumahnya biar bisa dipakai. Jalankan perintah di bawah ini buat mulai proyeknya. Anggap aja ini kayak kamu nyalain lampu dan buka pintu langsung keliatan deh isi websitenya di browser. Yuk jalankan perintah ini: npm run dev Struktur Folder & File Sekarang kita intip dulu isi ‘dalaman’ proyek ini, yuk! Jadi, di dalam folder utama bernama RESTO-MAIN, kamu bakal nemuin beberapa bagian penting kayak ini: /RESTO-MAIN ├── node_modules/ ├── src/ │ ├── assets/ │ │ └── images/ │ │ ├── icons/ │ │ │ ├── arrow_bottom.svg │ │ │ ├── arrow_right.svg │ │ │ ├── cost.svg │ │ │ ├── discount.svg │ │ │ ├── eat.svg │ │ │ ├── info_square.svg │ │ │ ├── Location.svg │ │ │ ├── logo.svg │ │ │ ├── search.svg │ │ │ ├── shield.svg │ │ │ ├── sign_right.svg │ │ │ ├── sparkle.svg │ │ │ └── star.svg │ │ └── thumbnails/ │ │ ├── ads-1.png │ │ ├── ads-2.png │ │ ├── chef-1.png │ │ ├── chef-2.webp │ │ ├── chef-3.webp │ │ ├── chef-4.webp │ │ ├── near-1.png │ │ ├── near-2.png │ │ ├── near-3.png │ │ ├── resto-1.png │ │ ├── resto-2.png │ │ ├── resto-3.png │ │ └── resto-4.png │ ├── js/ │ │ ├── card.js │ │ ├── dropdown.js │ │ ├── main.js │ │ └── tab.js │ ├── index.html │ ├── input.css │ └── output.css ├── .gitignore ├── package-lock.json ├── package.json └── vercel.json VSCode - Folder and File Structure Sidebar node_modules/ Ini semacam gudang besar berisi semua alat bantu (dependencies) yang tadi kamu download lewat npm install. Jangan diutak-atik manual ya, cukup diurus sama npm-nya aja. src/ Ini jantungnya proyek kita semua file inti buat tampilannya ada di sini. assets/ Tempat semua media kayak gambar dan ikon disimpan. images/ Nah, di sinilah seluruh gambar dikelompokkan jadi dua bagian: icons/ Berisi semua file SVG yang dipakai buat ikon-ikon kecil, kayak arrow_right.svg, search.svg, sampai logo.svg. Ibaratnya, ini koleksi stiker digital kamu buat dekor halaman. thumbnails/ Ini kumpulan gambar tampilan kayak iklan, chef, resto, dan lokasi. Bayangin ini kayak album foto buat mempercantik tampilan website. js/ Folder ini isinya semua file JavaScript yang ngatur interaksi di website kamu. Mulai dari card.js buat fitur kartu, dropdown.js buat menu turun, sampai tab.js buat navigasi tab. index.html File utama HTML yang jadi fondasi tampilan web kamu. input.css dan output.css input.css tempat kamu nulis style Tailwind, dan output.css adalah hasil akhirnya setelah diproses sama Tailwind. Anggap aja ini kayak nulis resep di input.css, dan ngeluarin masakan siap saji di output.css. .gitignore File ini bilang ke Git: "Hei, jangan ikutin file-file tertentu ya, kayak node_modules." package.json dan package-lock.json Ini dua file penting buat npm. package.json nyatet semua paket yang kamu butuhin dan script yang bisa dijalankan, sedangkan package-lock.json ngunci versi-versinya biar nggak berubah-ubah. vercel.json File ini buat ngasih tau Vercel (platform hosting) gimana cara ngejalanin dan build proyek kamu. Kode HTML & Tailwind CSS Head <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Resto - Landing Page</title> <link href="./output.css" rel="stylesheet" /> <!-- Swiper CSS --> <link rel="stylesheet" href="<https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css>" /> </head> Bayangin aja bagian <head> itu kayak ruang kontrolnya halaman web kamu, tempat kamu ngatur semuanya biar berjalan mulus. Di sini, kamu kasih tahu browser, “Hey, pakai karakter UTF-8 ya biar tulisan nggak aneh-aneh!” terus juga atur supaya tampilan web kamu bisa adaptasi dengan baik di semua gadget, dari HP sampai layar gede, lewat viewport. Nah, kamu juga kasih judul keren buat halaman kamu, misalnya “Resto - Landing Page,” biar pengunjung langsung tahu mereka di mana. Gak cuma itu, kamu sambungin file output.css supaya semua gaya kece dari Tailwind bisa nempel di halaman kamu. Terus ada juga link ke Swiper JS dari CDN, ini nih yang bikin slider kamu jadi asik dan interaktif. Jadi intinya, di ruang kontrol ini kamu siapin semua senjata dulu sebelum tampilan aslinya keluar ke layar. Body <body> <!-- Navbar --> <header class="px-[60px] mt-[60px]"> ... </header> <main> ... </main> <!-- Swiper JS --> <script src="<https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js>"></script> <script src="./js/main.js"></script> <script src="./js/tab.js"></script> <script src="./js/card.js"></script> <script src="./js/dropdown.js"></script> </body> Disini <main> ini spot utama buat semua konten keren kamu, entah itu gambar, teks, atau fitur-fitur yang pengen kamu pamerin. Pokoknya, semua yang pengunjung cari pasti ada di sini. Nah, jangan lupa, biar web kamu hidup dan gak cuma statis, kamu juga masukin beberapa file JavaScript di bawah sini. Ada Swiper JS dari CDN, yang tadi udah kita bahas buat bikin slider jadi keren dan interaktif. Terus, ada beberapa skrip lokal kayak main.js, tab.js, card.js, dan dropdown.js. Mereka ini kayak kru di balik layar yang jaga biar fitur-fitur di web kamu jalan mulus, mulai dari navigasi tab, interaksi kartu, sampai dropdown yang muncul pas kamu klik sesuatu. Jadi, semua bagian ini kerja barengan biar pengalaman kamu dan pengunjung makin asik dan dinamis! Header Resto - Navtop Section <header class="px-[60px] mt-[60px]"> <div class="flex justify-between items-center min-w-[1320px] h-14"> <nav> <ul class="flex gap-[30px]"> <!-- Home --> <li class="group flex flex-col justify-between h-[28px]"> <a href="#" class="text-[16px] leading-[24px] font-medium">Home</a> <span class="transition-all duration-300 h-0.5 w-full rounded-full bg-secondary opacity-0 group-hover:opacity-100"></span> </li> <!-- Category Dropdown --> <li class="dropdown relative flex flex-col cursor-pointer"> <div class="flex items-center h-6 w-full"> <button type="button" class="dropdown-button text-[16px] leading-[24px] font-medium cursor-pointer w-full text-left">Category</button> <div class="flex items-center justify-center h-6 w-6 shrink-0"> <img src="./assets/images/icons/arrow_bottom.svg" alt="" class="dropdown-arrow transition-transform duration-300" /> </div> </div> <ul class="dropdown-menu z-50 opacity-0 flex transition-all duration-300 absolute top-full left-0 mt-2 min-w-[150px] flex-col gap-1.5 bg-white rounded-xl py-2.5 shadow-lg"> <li class="group"> <a href="#" class="block py-1.5 px-5 text-[16px] leading-[24px] font-medium transition-all duration-300 hover:bg-secondary/5"> Foods </a> </li> <li class="group"> <a href="#" class="block py-1.5 px-5 text-[16px] leading-[24px] font-medium transition-all duration-300 hover:bg-secondary/5"> Drinks </a> </li> <li class="group"> <a href="#" class="block py-1.5 px-5 text-[16px] leading-[24px] font-medium transition-all duration-300 hover:bg-secondary/5"> Desserts </a> </li> </ul> </li> <!-- Services --> <li class="group flex flex-col justify-between h-[28px]"> <a href="#" class="text-[16px] leading-[24px] font-medium">Services</a> <span class="transition-all duration-300 h-0.5 w-full rounded-full bg-secondary opacity-0 group-hover:opacity-100"></span> </li> <!-- About Us --> <li class="group flex flex-col justify-between h-[28px]"> <a href="#" class="text-[16px] leading-[24px] font-medium">About us</a> <span class="transition-all duration-300 h-0.5 w-full rounded-full bg-secondary opacity-0 group-hover:opacity-100"></span> </li> </ul> </nav> <!-- Logo --> <a href="./"> <img src="./assets/images/icons/logo.svg" alt="" class="h-[38px] w-auto" /> </a> <!-- Search and Login --> <div class="flex gap-5"> <form class="group flex w-[322px] gap-2.5 py-4 px-7 bg-white rounded-[12px] transition-all duration-300 focus-within:ring-2 focus-within:ring-secondary hover:ring-2 hover:ring-secondary"> <div class="flex items-center justify-center h-6 w-6 shrink-0"> <img src="./assets/images/icons/search.svg" alt="" class="" /> </div> <input type="text" class="w-full text-[16px] font-medium leading-6 placeholder-placeholder group-hover:outline-none focus:outline-none" placeholder="Search your favorite food" /> </form> <a href="#" class="w-[104px] h-14 flex items-center justify-center bg-secondary/10 text-secondary text-[16px] font-semibold leading-6 rounded-[12px] transition-all duration-300 hover:shadow-secondary"> Log In </a> </div> </div> </header> Jadi header di sini ibarat pintu gerbang keren yang nyambut pengunjung waktu mereka buka web kamu. Dibungkus dengan padding kiri-kanan 60px dan jarak atas 60px biar nggak mepet, tampilannya jadi lega dan enak dipandang. Di dalamnya ada container utama yang pakai flex buat ngejalanin semua item secara horizontal dan rapi: navigasi, logo, sama area search + login. Navigasi (nav): Ini kayak peta jalan buat pengunjung. Ada beberapa menu utama yang kamu kasih gaya kece supaya interaktif: Home, Services, About Us: tiap menu ini ada underline halus yang muncul pas kamu hover, kayak lampu yang nyala, biar pengunjung tau lagi hover di mana.Category Dropdown: Ini bagian spesial. Kamu bikin dropdown yang pas di-hover atau diklik, muncul menu pilihan makanan, minuman, sama dessert. Tombolnya ada icon panah kecil yang animasi halus muter saat dropdown dibuka, biar keliatan hidup dan jelas. Logo: Tengah-tengah ada logo kamu yang keren, ukurannya pas biar nggak terlalu gede tapi tetap eye-catching. Jadi kayak tanda pengenal yang selalu ada di tengah panggung. Search dan Login: Di kanan, kamu punya form search yang tampilannya stylish, lengkap dengan ikon kaca pembesar. Saat kamu klik di kolom search, muncul efek ring warna secondary yang bikin terasa interaktif dan profesional. Di sebelahnya ada tombol “Log In” yang simple tapi punya hover efek dengan bayangan halus jadi ngajak banget pengunjung buat klik dan masuk. Main <main> <!-- Ads Section --> <section class="relative flex justify-center"> ... </section> <!-- Why us? --> <section class="flex justify-center"> ... </section> <!-- Popular restaurant --> <section class="flex justify-center"> ... </section> <!-- Near you restaurant --> <section class="flex justify-center"> ... </section> <!-- Expert chef --> <section class="mt-[60px] mb-[123px] flex justify-center"> ... </section> </main> Bayangin <main> ini kayak etalase utama di toko kamu, tempat semua hal menarik dan andalan ditampilkan buat pengunjung. Di sini, kamu punya beberapa section yang berjajar rapi, masing-masing punya perannya sendiri: Ads Section: Ini semacam billboard digital kamu, tempat kamu pasang iklan keren atau promo spesial biar pengunjung langsung tergoda dan ngelirik.Why Us?: Nah, ini kayak momen kamu ngejelasin kenapa pengunjung harus pilih tempat kamu. Bisa berisi alasan-alasan kece yang bikin kamu beda dan layak dipilih.Popular Restaurant: Di sini kamu pamerin restoran-restoran hits yang lagi naik daun. Jadi pengunjung bisa langsung lihat mana yang lagi favorit orang banyak.Near You Restaurant: Sekarang makin personal! Bagian ini ngasih rekomendasi restoran yang deket sama lokasi pengunjung, biar mereka gampang cari makan tanpa jauh-jauh.Expert Chef: Ini bagian yang kasih sentuhan spesial, ngenalin chef-chef jagoan yang bikin makanan di restoran kamu makin spesial. Dengan jarak atas dan bawah yang pas, tampilannya jadi bernafas dan elegan. Ads Section Resto - Ads Section <section class="relative flex justify-center"> <div class="swiper !pl-[140px] !pr-[60px]"> <div class="swiper-wrapper flex py-[60px]"> <!-- Item 1 --> <div class="group swiper-slide relative !w-[1128px] !h-[564px]"> <div class="w-full h-full rounded-3xl overflow-clip"> <img src="./assets/images/thumbnails/ads-1.png" alt="" class="object-cover w-full" /> </div> <div class="absolute transition-all duration-300 opacity-0 group-hover:opacity-100 flex flex-col gap-1 -left-20 top-[133px] bottom-[134px] h-[297px] w-[390px] rounded-3xl bg-white pl-6 py-6 pr-[140px]"> <div class="flex items-center h-[27px] w-[210px]"> <div class="flex gap-[6.5px] -mt-[3px] pr-[3px]"> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> </div> <div class="flex gap-1 items-center"> <p class="text-lg leading-[27px] font-semibold text-star">5.0</p> <p class="text-[16px] text-muted">(5.2K+)</p> </div> </div> <h2 class="text-[22px] font-semibold leading-[33px]">Padang Restaurant</h2> <p class="text-lg font-semibold leading-[27px] text-muted">IDR 49.999 - IDR 560.000</p> <div class="flex gap-1.5 items-center"> <div class="h-6 w-6 flex items-center justify-center"> <img src="./assets/images/icons/Location.svg" alt="" class="h-6 w-6" /> </div> <p class="text-[16px] leading-6 text-muted">Padang, Indonesia</p> </div> <div class="mt-[30px] flex flex-col gap-3"> <a href="#" class="flex items-center justify-center text-[16px] font-semibold leading-6 bg-primary rounded-[12px] w-[226px] h-14 hover:shadow-primary transition-all duration-300"> <span>Make Reservation</span> <img src="./assets/images/icons/arrow_right.svg" alt="" class="" /> </a> <div class="flex gap-1.5 items-center"> <img src="./assets/images/icons/info_square.svg" alt="" class="h-6 w-6" /> <p class="text-[16px] leading-6 text-muted">No extra cost</p> </div> </div> </div> </div> <!-- Item 2 --> <div class="group swiper-slide relative !w-[1128px] !h-[564px]"> <!-- ini image --> <div class="w-full h-full rounded-3xl overflow-clip"> <img src="./assets/images/thumbnails/ads-2.png" alt="" class="object-cover w-full" /> </div> <!-- ini details --> <div class="absolute transition-all duration-300 opacity-0 group-hover:opacity-100 flex flex-col gap-1 -left-20 top-[133px] bottom-[134px] h-[297px] w-[390px] rounded-3xl bg-white pl-6 py-6 pr-[140px]"> <div class="flex items-center h-[27px] w-[210px]"> <div class="flex gap-[6.5px] -mt-[3px] pr-[3px]"> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] shrink-0" /> </div> <div class="flex gap-1 items-center"> <p class="text-lg leading-[27px] font-semibold text-star">5.0</p> <p class="text-[16px] text-muted">(5.2K+)</p> </div> </div> <h2 class="text-[22px] font-semibold leading-[33px]">Jember Restaurant</h2> <p class="text-lg font-semibold leading-[27px] text-muted">IDR 39.999 - IDR 460.000</p> <div class="flex gap-1.5 items-center"> <div class="h-6 w-6 flex items-center justify-center"> <img src="./assets/images/icons/Location.svg" alt="" class="h-6 w-6" /> </div> <p class="text-[16px] leading-6 text-muted">Jember, Indonesia</p> </div> <div class="mt-[30px] flex flex-col gap-3"> <a href="#" class="flex items-center justify-center text-[16px] font-semibold leading-6 bg-primary rounded-[12px] w-[226px] h-14 hover:shadow-primary transition-all duration-300"> <span>Make Reservation</span> <img src="./assets/images/icons/arrow_right.svg" alt="" class="" /> </a> <div class="flex gap-1.5 items-center"> <img src="./assets/images/icons/info_square.svg" alt="" class="h-6 w-6" /> <p class="text-[16px] leading-6 text-muted">No extra cost</p> </div> </div> </div> </div> </div> </div> </section> Bagian HTML ini tuh kayak etalase digital yang keren banget buat nunjukin restoran-restoran kece pakai Swiper.js. Bayangin kamu lagi liat-liat brosur restoran, tapi versi modern, tinggal geser aja. Setiap slide itu semacam kartu gede berisi gambar restoran yang menggoda. Nah, pas kamu arahkan kursor ke gambarnya, langsung muncul detail kayak rating bintang lima, nama tempat, harga, sampai tombol buat langsung reservasi. Semuanya muncul mulus kayak sulap gara-gara efek opacity yang berubah waktu kamu hover. Slide-nya sendiri ukurannya udah diset fix biar tampilannya konsisten dan mantap, jadi kamu nggak perlu khawatir layout-nya acak-acakan. Gambar restorannya dibikin full tampil biar kesan "wah" langsung dapet. Terus bagian infonya muncul di sebelah kiri gambar, kayak pop-up brosur kecil yang nyodorin promo pas kamu lagi lewat. Kesan interaktif dan mewahnya dapet banget deh, cocok kalau kamu mau bikin orang langsung pengen booking tempat dari tampilan pertama. Why us? Resto - Why us? section <section class="flex justify-center"> <div class="w-[1320px] m-[60px]"> <div class="flex w-fit mx-auto flex-col gap-1.5 text-center mb-[41px]"> <span class="text-[16px] leading-6 font-semibold text-secondary uppercase">Special Benefit For You</span> <h2 class="text-[28px] leading-[42px] font-semibold">Why Should Choose Us?</h2> </div> <div class="flex w-full gap-5"> <!-- Item 1 --> <div class="flex flex-col gap-[54px] h-fit pt-6 min-h-[347px] w-[315px] bg-white rounded-3xl"> <div class="flex flex-col gap-6"> <div class="ml-[117px] mr-[118px] flex items-center justify-center h-20 w-20 rounded-full bg-primary/15"> <img src="./assets/images/icons/discount.svg" alt="" class="h-[58px] w-[58px]" /> </div> <h3 class="text-lg leading-[27px] font-semibold text-center">Extra Discounts</h3> <p class="w-[267px] -mt-3 mx-6 text-[16px] leading-6 text-muted text-center">Get your special discount by using our reservation</p> </div> <a href="#" class="w-full mt-auto h-[72px] flex items-center justify-center text-[16px] leading-6 font-semibold rounded-t-xl rounded-b-3xl transition-all duration-300 hover:bg-primary"> <span>View Details</span> <img src="./assets/images/icons/arrow_right.svg" alt="" class="h-6 w-6" /> </a> </div> <!-- Item 2 --> <div class="flex flex-col gap-[54px] h-fit pt-6 min-h-[347px] w-[315px] bg-white rounded-3xl"> <div class="flex flex-col gap-6"> <div class="ml-[117px] mr-[118px] flex items-center justify-center h-20 w-20 rounded-full bg-primary/15"> <img src="./assets/images/icons/eat.svg" alt="" class="h-[58px] w-[58px]" /> </div> <h3 class="text-lg leading-[27px] font-semibold text-center">Come and Eat</h3> <p class="w-[267px] -mt-3 mx-6 text-[16px] leading-6 text-muted text-center">Get your own table quickly & without waiting in line</p> </div> <a href="#" class="w-full mt-auto h-[72px] flex items-center justify-center text-[16px] leading-6 font-semibold rounded-t-xl rounded-b-3xl transition-all duration-300 hover:bg-primary"> <span>View Details</span> <img src="./assets/images/icons/arrow_right.svg" alt="" class="h-6 w-6" /> </a> </div> <!-- Item 3 --> <div class="flex flex-col gap-[54px] h-fit pt-6 min-h-[347px] w-[315px] bg-white rounded-3xl"> <div class="flex flex-col gap-6"> <div class="ml-[117px] mr-[118px] flex items-center justify-center h-20 w-20 rounded-full bg-primary/15"> <img src="./assets/images/icons/cost.svg" alt="" class="h-[58px] w-[58px]" /> </div> <h3 class="text-lg leading-[27px] font-semibold text-center">No Extra Fee</h3> <p class="w-[267px] -mt-3 mx-6 text-[16px] leading-6 text-muted text-center">Get tax free if you want to order food and make a reservation</p> </div> <a href="#" class="w-full mt-auto h-[72px] flex items-center justify-center text-[16px] leading-6 font-semibold rounded-t-xl rounded-b-3xl transition-all duration-300 hover:bg-primary"> <span>View Details</span> <img src="./assets/images/icons/arrow_right.svg" alt="" class="h-6 w-6" /> </a> </div> <!-- Item 4 --> <div class="flex flex-col gap-[54px] h-fit pt-6 min-h-[347px] w-[315px] bg-white rounded-3xl"> <div class="flex flex-col gap-6"> <div class="ml-[117px] mr-[118px] flex items-center justify-center h-20 w-20 rounded-full bg-primary/15"> <img src="./assets/images/icons/sparkle.svg" alt="" class="h-[58px] w-[58px]" /> </div> <h3 class="text-lg leading-[27px] font-semibold text-center">Guaranteed Cleanliness</h3> <p class="w-[267px] -mt-3 mx-6 text-[16px] leading-6 text-muted text-center">We ensure the cleanliness of the place as well as the food</p> </div> <a href="#" class="w-full mt-auto h-[72px] flex items-center justify-center text-[16px] leading-6 font-semibold rounded-t-xl rounded-b-3xl transition-all duration-300 hover:bg-primary"> <span>View Details</span> <img src="./assets/images/icons/arrow_right.svg" alt="" class="h-6 w-6" /> </a> </div> </div> </div> </section> Pernah nggak sih kamu bingung mau pilih tempat makan atau booking restoran, tapi semua kelihatan sama aja? Nah, di sinilah kita beda! Bayangin kamu lagi cari tempat nongkrong yang nggak cuma enak makanannya, tapi juga punya extra diskon, bisa langsung datang tanpa nunggu, nggak ada biaya tambahan, dan pastinya tempatnya bersih kinclong kayak baru dipel tiap 5 menit. Semua benefit ini kita siapin biar kamu bisa dapetin pengalaman terbaik, tanpa ribet dan tanpa biaya yang bikin dompet meringis. Dan yang bikin tampilannya enak dilihat? Semua kontennya dibungkus dalam card layout yang elegan dan responsif pakai Tailwind CSS. Class kayak w-[315px], rounded-3xl, dan gap-[54px] bikin tiap kartu punya ukuran pas, sudut membulat yang modern, dan jarak antar elemen yang lapang banget. Setiap kartu ini juga punya tombol View Details di bawahnya yang udah dikasih transisi halus (transition-all duration-300) jadi saat kamu hover, warnanya langsung berubah jadi lebih hidup (thanks to hover:bg-primary). Terus, biar ikon di atas judul kelihatan standout, kita masukin ke dalam lingkaran transparan (bg-primary/15) dengan tinggi-lebar 80px, yang bikin elemen visualnya jadi lebih "ngomong" tanpa bikin layout rame. Semuanya disusun pakai utility-first class dari Tailwind nggak pakai CSS tambahan yang ribet. Hasilnya? Tampilan bersih, struktur rapi, dan pastinya performa juga ringan. Desainnya udah disetting secara fleksibel dalam flex flex-col dan gap antar elemen yang bikin antar bagian nggak dempet-dempetan. Jadi kalau kamu lihat ini, bukan cuma enak dibaca, tapi juga feel-nya profesional dan friendly banget. Popular restaurant Resto - Popular restaurant Section <section class="flex justify-center"> <div class="flex items-center w-[1320px] m-[60px]"> <div class="w-[367px]"> <div class="flex flex-col gap-1.5"> <span class="text-[16px] leading-6 font-semibold text-secondary uppercase">Top 3 Featured Restaurant</span> <h2 class="w-full text-[28px] leading-[42px] font-semibold">Most Popular Restaurants</h2> </div> <p class="mt-5 w-[360px] pr-5 text-[16px] leading-6 text-muted">The best restaurant in our opinion is how much customers like it in terms of place, price, comfort and of course the taste of the food itself.</p> <a href="#" class="mt-14 flex items-center justify-center text-[16px] leading-6 font-semibold h-[56px] w-[238px] bg-primary rounded-xl transition-all duration-300 hover:shadow-primary"> <span>View All Restaurant</span> <img src="./assets/images/icons/arrow_right.svg" alt="" class="h-6 w-6" /> </a> </div> <div class="ml-[85px] flex gap-5"> <!-- Card 1 --> <div class="card group transition-all duration-300 relative h-[475px] w-[400px] rounded-3xl overflow-clip shrink-0 hover:w-[400px]" data-card="1"> <img src="./assets/images/thumbnails/resto-1.png" alt="" class="object-cover w-full h-full" /> <div class="card-info transition-all duration-300 delay-1000 ease-in-out flex gap-2 p-6 items-center absolute left-6 bottom-6 right-6 bg-white rounded-3xl"> <div class="flex flex-col gap-1 w-[260px]"> <div class="flex items-center"> <img src="./assets/images/icons/star.svg" alt="" class="h-auto w-[18px] -mt-[3px] mr-[3px]" /> <p class="text-[16px] leading-6 font-semibold text-star mr-1">5.0</p> <p class="text-[16px] leading-6 text-muted">(7.6K+)</p> </div> <h3 class="text-lg leading-[27px] font-semibold">Bind Balorant</h3> <div class="flex gap-1.5"> <img src="./assets/images/icons/Location.svg" alt="" class="h-6 w-6" /> <p class="text-[16px] leading-6 text-muted">Jakarta, Indonesia</p> </div> </div> <a href="#" class="flex items-center justify-center h-9 w-9 rounded-xl bg-primary shrink-0 transition-all duration-300 hover:shadow-primary"> <img src="./assets/images/icons/sign_right.svg" alt="" class="" /> </a> </div> </div> <!-- Card 2 --> <div class="card group transition-all duration-300 relative h-[475px] w-[214px] rounded-3xl overflow-clip shrink-0 hover:w-[400px]" data-card="2"> <img src="./assets/images/thumbnails/resto-2.png" alt="" class="object-cover h-full w-full" /> <div class="card-info transition-all duration-300 delay-1000 ease-in-out gap-2 p-6 items-center absolute left-6 bottom-6 right-6 bg-white rounded-3xl hidden"> <div class="flex flex-col gap-1 w-[260px]"> <div class="flex items-center"> <img src="./assets/images/icons/star.svg" alt="" class="h-auto w-[18px] -mt-[3px] mr-[3px]" /> <p class="text-[16px] leading-6 font-semibold text-star mr-1">4.8</p> <p class="text-[16px] leading-6 text-muted">(5.2K+)</p> </div> <h3 class="text-lg leading-[27px] font-semibold">Green Garden</h3> <div class="flex gap-1.5"> <img src="./assets/images/icons/Location.svg" alt="" class="h-6 w-6" /> <p class="text-[16px] leading-6 text-muted">Bandung, Indonesia</p> </div> </div> <a href="#" class="flex items-center justify-center h-9 w-9 rounded-xl bg-primary shrink-0 transition-all duration-300 hover:shadow-primary"> <img src="./assets/images/icons/sign_right.svg" alt="" class="" /> </a> </div> </div> <!-- Card 3 --> <div class="card group transition-all duration-300 relative h-[475px] w-[214px] rounded-3xl overflow-clip shrink-0 hover:w-[400px]" data-card="3"> <img src="./assets/images/thumbnails/resto-3.png" alt="" class="object-cover h-full w-full" /> <div class="card-info transition-all duration-300 delay-1000 ease-in-out gap-2 p-6 items-center absolute left-6 bottom-6 right-6 bg-white rounded-3xl hidden"> <div class="flex flex-col gap-1 w-[260px]"> <div class="flex items-center"> <img src="./assets/images/icons/star.svg" alt="" class="h-auto w-[18px] -mt-[3px] mr-[3px]" /> <p class="text-[16px] leading-6 font-semibold text-star mr-1">4.9</p> <p class="text-[16px] leading-6 text-muted">(6.8K+)</p> </div> <h3 class="text-lg leading-[27px] font-semibold">Sundanese Delight</h3> <div class="flex gap-1.5"> <img src="./assets/images/icons/Location.svg" alt="" class="h-6 w-6" /> <p class="text-[16px] leading-6 text-muted">Sunda, Indonesia</p> </div> </div> <a href="#" class="flex items-center justify-center h-9 w-9 rounded-xl bg-primary shrink-0 transition-all duration-300 hover:shadow-primary"> <img src="./assets/images/icons/sign_right.svg" alt="" class="" /> </a> </div> </div> </div> </div> </section> Kamu pernah lihat deretan restoran yang langsung bikin kamu pengen klik salah satunya? Nah, bagian ini tuh kayak etalase yang ditata rapi dan glowing biar kamu tinggal pilih tanpa mikir dua kali. Di sebelah kiri, ada teks pengantar yang fungsinya kayak MC: ngenalin kamu ke tiga restoran paling favorit versi kita. Dengan struktur flex justify-center dan container w-[1320px], semuanya udah diposisikan pas di tengah layar. Terus bagian infonya dikemas rapi dalam lebar w-[367px], lengkap dengan heading “Most Popular Restaurants” dan subjudul kecil buat narik perhatian mata. Oh, dan tombol “View All Restaurant” itu bukan tombol biasa udah dikasih animasi transisi hover:shadow-primary yang bikin efek glowing halus setiap kamu arahkan kursor, kayak ngajak kamu buat eksplor lebih jauh. Sekarang kita ke bagian yang seru tiga kartu restoran yang tampilannya keren banget. Bayangin ini kayak tiga showcase makanan, satu lagi besar di depan, dua lainnya ngintip di samping. Kartu pertama dikasih lebar penuh w-[400px], sedangkan dua lainnya lebih ramping w-[214px], tapi semuanya punya trik rahasia: hover interaktif. Begitu kamu arahkan mouse ke kartu mana pun, ukurannya langsung membesar jadi hover:w-[400px], seolah-olah bilang "eh, aku nih yang kamu cari!" Ini dimungkinkan karena kita pakai Tailwind transition-all duration-300, jadi semua perubahan ukuran terasa mulus. Tiap kartu juga punya lapisan info yang muncul dari bawah dengan absolute bottom-6 left-6 right-6 dan bg-white rounded-3xl, lengkap sama rating, lokasi, nama restoran, dan tombol masuk kecil berikon. Dan yang bikin makin ciamik, info dua kartu samping awalnya disembunyiin (hidden) dan baru ditampilin saat interaksi (nanti bisa dikontrol pakai JS atau toggle class di hover). Jadi kamu bisa bikin UX yang dinamis banget hanya dengan mainin kombinasi class Tailwind dan sedikit logika interaktif. Ini bukan cuma pamer visual, ini storytelling visual yang ngajak user buat penasaran, eksplor, dan akhirnya klik. Near you restaurant Resto - Near you restaurant Section <section class="flex justify-center"> <div class="flex flex-col gap-[34px] w-[1321px] m-[60px]"> <div class="flex w-full items-center justify-between"> <div class="flex flex-col gap-1.5"> <span class="text-[16px] leading-6 font-semibold text-secondary uppercase">Restaurant Based by City</span> <h2 class="w-full text-nowrap text-[28px] leading-[42px] font-semibold">Restaurant Near You</h2> </div> <div class="relative dropdown flex flex-col"> <button type="button" class="dropdown-button flex cursor-pointer gap-1.5 px-6 py-5 items-center h-[64px] w-[252px] rounded-xl bg-[#f2f2f2]"> <img src="./assets/images/icons/Location.svg" alt="" class="" /> <div class="flex"> <p class="text-[16px] leading-6 font-medium text-muted">Jakarta, Indonesia</p> <div class="flex items-center justify-center h-6 w-6"> <img src="./assets/images/icons/arrow_bottom.svg" alt="" class="dropdown-arrow transition-all duration-300" /> </div> </div> </button> <ul class="dropdown-menu z-50 opacity-0 transition-all duration-300 absolute top-full left-0 mt-2 min-w-[150px] flex-col gap-1.5 bg-white rounded-xl py-2.5 shadow-lg"> <li class="group"> <button type="button" class="flex cursor-pointer gap-1.5 px-6 py-5 items-center h-[64px] w-[252px] transition-all duration-300 hover:bg-[#f2f2f2]"> <img src="./assets/images/icons/Location.svg" alt="" class="" /> <div class="flex"> <p class="text-[16px] leading-6 font-medium text-muted">Bandung, Indonesia</p> </div> </button> </li> <li class="group"> <button type="button" class="flex cursor-pointer gap-1.5 px-6 py-5 items-center h-[64px] w-[252px] transition-all duration-300 hover:bg-[#f2f2f2]"> <img src="./assets/images/icons/Location.svg" alt="" class="" /> <div class="flex"> <p class="text-[16px] leading-6 font-medium text-muted">Bali, Indonesia</p> </div> </button> </li> <li class="group"> <button type="button" class="flex cursor-pointer gap-1.5 px-6 py-5 items-center h-[64px] w-[252px] transition-all duration-300 hover:bg-[#f2f2f2]"> <img src="./assets/images/icons/Location.svg" alt="" class="" /> <div class="flex"> <p class="text-[16px] leading-6 font-medium text-muted">Jember, Indonesia</p> </div> </button> </li> </ul> </div> </div> <div class="flex gap-5"> <!-- Item 1 --> <div class="relative h-[415px] w-[427px] rounded-3xl overflow-clip shrink-0"> <img src="./assets/images/thumbnails/near-1.png" alt="" class="object-cover w-full h-full" /> <div class="flex gap-[35px] p-6 items-center absolute left-6 bottom-[33px] right-6 bg-white rounded-3xl"> <div class="flex flex-col gap-1 w-[260px]"> <div class="flex items-center"> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] -mt-[3.5px] mr-[3px]" /> <p class="text-[16px] leading-6 font-semibold text-star mr-1">5.0</p> <p class="text-[16px] leading-6 text-muted">(6.6K+)</p> </div> <h3 class="text-lg leading-[27px] font-semibold">Batavia Restaurant</h3> <p class="text-lg font-semibold leading-6 text-muted">IDR 29.000 - IDR 259.999</p> </div> <a href="#" class="flex items-center justify-center h-9 w-9 rounded-xl bg-primary shrink-0 transition-all duration-300 hover:shadow-primary"> <img src="./assets/images/icons/sign_right.svg" alt="" class="" /> </a> </div> </div> <!-- Item 2 --> <div class="relative h-[415px] w-[427px] rounded-3xl overflow-clip shrink-0"> <img src="./assets/images/thumbnails/near-2.png" alt="" class="object-cover w-full h-full" /> <div class="flex gap-[35px] p-6 items-center absolute left-6 bottom-[33px] right-6 bg-white rounded-3xl"> <div class="flex flex-col gap-1 w-[260px]"> <div class="flex items-center"> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] -mt-[3.5px] mr-[3px]" /> <p class="text-[16px] leading-6 font-semibold text-star mr-1">5.0</p> <p class="text-[16px] leading-6 text-muted">(3.6K+)</p> </div> <h3 class="text-lg leading-[27px] font-semibold">Split Ascent Restaurant</h3> <p class="text-lg font-semibold leading-6 text-muted">IDR 49.999 - IDR 560.000</p> </div> <a href="#" class="flex items-center justify-center h-9 w-9 rounded-xl bg-primary shrink-0 transition-all duration-300 hover:shadow-primary"> <img src="./assets/images/icons/sign_right.svg" alt="" class="" /> </a> </div> </div> <!-- Item 3 --> <div class="relative h-[415px] w-[427px] rounded-3xl overflow-clip shrink-0"> <img src="./assets/images/thumbnails/near-3.png" alt="" class="object-cover w-full h-full" /> <div class="flex gap-[35px] p-6 items-center absolute left-6 bottom-[33px] right-6 bg-white rounded-3xl"> <div class="flex flex-col gap-1 w-[260px]"> <div class="flex items-center"> <img src="./assets/images/icons/star.svg" alt="" class="w-[18px] -mt-[3.5px] mr-[3px]" /> <p class="text-[16px] leading-6 font-semibold text-star mr-1">5.0</p> <p class="text-[16px] leading-6 text-muted">(11K+)</p> </div> <h3 class="text-lg leading-[27px] font-semibold">Daza Fracture Restaurant</h3> <p class="text-lg font-semibold leading-6 text-muted">IDR 29.999 - IDR 560.000</p> </div> <a href="#" class="flex items-center justify-center h-9 w-9 rounded-xl bg-primary shrink-0 transition-all duration-300 hover:shadow-primary"> <img src="./assets/images/icons/sign_right.svg" alt="" class="" /> </a> </div> </div> </div> <a href="#" class="mt-[22px] mx-auto flex items-center justify-center h-14 w-[238px] bg-primary rounded-xl text-[16px] leading-6 font-semibold transition-all duration-300 hover:shadow-primary"> <span>View All Restaurant</span> <img src="./assets/images/icons/arrow_right.svg" alt="" class="h-6 w-6" /> </a> </div> </section> <section> ini kerja kayak wrapper utama yang pake Flexbox buat nge-center semua konten secara horizontal. Di dalamnya ada sebuah <div> container yang diatur pakai flex-col biar isinya berdiri vertikal dengan jarak (gap) 34px antar elemen, kayak kamu ngatur layout pake CSS Flexbox supaya rapi dan responsif. Ukuran lebar container juga fixed di 1321px dan ada margin 60px buat kasih ruang di sekitar, jadi tampilannya nggak nempel ke tepi layar. Bagian header-nya diatur pake Flexbox juga, justify-between supaya judul di kiri dan dropdown lokasi di kanan bisa “menjauh” saling berjauhan. Dropdown ini pakai positioning relative dan absolute buat dropdown menunya, yang awalnya opacity-0 dan disembunyiin, lalu muncul dengan animasi transisi halus (transition-all duration-300) saat tombol diklik. Tombolnya sendiri dikasih padding, rounded corners, dan background abu-abu muda buat kasih kesan tombol interaktif yang ramah buat user. Nah, bawahnya ada tiga card restoran yang ukurannya fixed (lebar 427px, tinggi 415px), tiap card pakai overflow-clip dan rounded-3xl supaya gambar dan konten gak keluar batas dan tampilannya jadi elegan. Gambar restoran dipasang dengan object-cover supaya memenuhi kotak tanpa nge-distorsi. Di bagian bawah tiap kartu, info restoran dikemas dalam flex dengan jarak antar elemen yang pas, plus tombol action kecil yang diberi efek hover shadow buat interaksi lebih hidup. Terakhir ada tombol “View All Restaurant” yang desainnya eye-catching, dengan ukuran fixed dan efek hover untuk meningkatkan user engagement. Expert chef Resto - Expert chef Section <section class="mt-[60px] mb-[123px] flex justify-center"> <div class="flex items-center gap-[64px] w-[1321px]"> <!-- Tab content --> <div class="tab-content relative h-[848px] w-[660px]"> <div class="absolute left-[60px] right-10 h-full w-[560px] rounded-3xl overflow-clip"> <img src="./assets/images/thumbnails/chef-1.png" alt="" class="object-cover w-full h-full" loading="lazy" /> </div> <div class="absolute top-10 right-0 px-[46px] py-[30px] flex flex-col items-center h-[203px] w-[179px] bg-white rounded-3xl drop-shadow-custom"> <div class="mb-3 flex items-center justify-center h-20 w-20 bg-[#FFF7ED] rounded-full"> <img src="./assets/images/icons/shield.svg" alt="" class="h-[50px] w-[50px] shrink-0" /> </div> <div class="w-[87px] text-center"> <p class="experience-years text-lg leading-[27px] font-semibold">12 Years</p> <p class="text-[16px] leading-6 text-muted">Experience</p> </div> </div> <div class="p-6 absolute left-0 bottom-10 flex items-center gap-3 h-auto w-[330px] rounded-3xl bg-white drop-shadow-custom2"> <div class="h-[132px] w-[96px] rounded-xl overflow-clip shrink-0"> <img src="./assets/images/thumbnails/resto-4.png" alt="" class="object-cover w-full h-full" /> </div> <div class="w-[174px] h-auto"> <div class="flex flex-col gap-6"> <div class="flex flex-col gap-1"> <span class="text-[16px] leading-6 text-muted">Chef at restaurant:</span> <p class="resto-name text-lg leading-[27px] font-semibold">Pearl Dolphin</p> </div> <a href="#" class="flex text-[16px] leading-6 font-semibold text-primary"> <span>View Details</span> <div class="flex items-center justify-center h-6 w-6 mask-[url('./assets/images/icons/arrow_right.svg')] mask-no-repeat mask-contain bg-primary"> <img src="./assets/images/icons/arrow_right.svg" alt="" class="opacity-0" /> </div> </a> </div> </div> </div> </div> <div class="flex flex-col gap-8 w-[596px]"> <div class="flex flex-col gap-1"> <span class="text-[18px] leading-6 font-semibold text-secondary uppercase">Top 4 Expert Chefs</span> <h2 class="w-full text-nowrap text-[32px] leading-[48px] font-semibold">Expert Chefs In Fuddy</h2> </div> <!-- Tab menu --> <div class="tab-menu flex flex-col gap-5"> <!-- Tab item 1 --> <div class="tab-item cursor-pointer p-6 flex flex-col gap-1.5 h-[141px] w-[596px] rounded-3xl group transition-all duration-300 hover:bg-white"> <span class="text-[16px] leading-6 font-medium text-muted uppercase">Pizza</span> <div class="w-full flex items-center justify-between"> <h2 class="text-[22px] leading-[33px] font-semibold line-clamp-1 mr-0.5">Phoenix Satcheup</h2> <a href="#" class="flex text-[16px] opacity-100 leading-6 font-medium text-primary shrink-0"> <span>Profile Details</span> <div class="flex items-center justify-center h-6 w-6 mask-[url('./assets/images/icons/arrow_right.svg')] mask-no-repeat mask-contain bg-primary shrink-0"> <img src="./assets/images/icons/arrow_right.svg" alt="" class="opacity-0" /> </div> </a> </div> <div class="flex items-center gap-1.5"> <div class="location-icon transition-all duration-300 mask-[url('./assets/images/icons/Location.svg')] mask-no-repeat mask-contain"> <img src="./assets/images/icons/Location.svg" alt="" class="h-6 w-6 opacity-0" /> </div> <p class="text-[16px] leading-6 text-muted">Jakarta, Indonesia</p> </div> </div> <!-- Tab item 2 --> <div class="tab-item cursor-pointer p-6 flex flex-col gap-1.5 h-[141px] w-[596px] rounded-3xl group transition-all duration-300 hover:bg-white"> <span class="text-[16px] leading-6 font-medium text-muted uppercase">Vegan</span> <div class="w-full flex items-center justify-between"> <h2 class="text-[22px] leading-[33px] font-semibold line-clamp-1 mr-0.5">Chamber Botfrag</h2> <a href="#" class="opacity-0 flex text-[16px] leading-6 font-medium text-primary shrink-0"> <span>Profile Details</span> <div class="flex items-center justify-center h-6 w-6 mask-[url('./assets/images/icons/arrow_right.svg')] mask-no-repeat mask-contain bg-primary shrink-0"> <img src="./assets/images/icons/arrow_right.svg" alt="" class="opacity-0" /> </div> </a> </div> <div class="flex items-center gap-1.5"> <div class="location-icon transition-all duration-300 mask-[url('./assets/images/icons/Location.svg')] mask-no-repeat mask-contain bg-foreground"> <img src="./assets/images/icons/Location.svg" alt="" class="h-6 w-6 opacity-0" /> </div> <p class="text-[16px] leading-6 text-muted">Bandung, Indonesia</p> </div> </div> <!-- Tab item 3 --> <div class="tab-item cursor-pointer p-6 flex flex-col gap-1.5 h-[141px] w-[596px] rounded-3xl group transition-all duration-300 hover:bg-white"> <span class="text-[16px] leading-6 font-medium text-muted uppercase">Roast Chicken</span> <div class="w-full flex items-center justify-between"> <h2 class="text-[22px] leading-[33px] font-semibold line-clamp-1 mr-0.5">Asep Vandal</h2> <a href="#" class="opacity-0 flex text-[16px] leading-6 font-medium text-primary shrink-0"> <span>Profile Details</span> <div class="flex items-center justify-center h-6 w-6 mask-[url('./assets/images/icons/arrow_right.svg')] mask-no-repeat mask-contain bg-primary"> <img src="./assets/images/icons/arrow_right.svg" alt="" class="opacity-0" /> </div> </a> </div> <div class="flex items-center gap-1.5"> <div class="location-icon transition-all duration-300 mask-[url('./assets/images/icons/Location.svg')] mask-no-repeat mask-contain bg-foreground shrink-0"> <img src="./assets/images/icons/Location.svg" alt="" class="h-6 w-6 opacity-0" /> </div> <p class="text-[16px] leading-6 text-muted">Sunda, Indonesia</p> </div> </div> <!-- Tab item 4 --> <div class="tab-item cursor-pointer p-6 flex flex-col gap-1.5 h-[141px] w-[596px] rounded-3xl group transition-all duration-300 hover:bg-white"> <span class="text-[16px] leading-6 font-medium text-muted uppercase">Beef Steak</span> <div class="w-full flex items-center justify-between"> <h2 class="text-[22px] leading-[33px] font-semibold line-clamp-1 mr-0.5">I Made Invoker</h2> <a href="#" class="opacity-0 flex text-[16px] leading-6 font-medium text-primary shrink-0"> <span>Profile Details</span> <div class="flex items-center justify-center h-6 w-6 mask-[url('./assets/images/icons/arrow_right.svg')] mask-no-repeat mask-contain bg-primary"> <img src="./assets/images/icons/arrow_right.svg" alt="" class="opacity-0" /> </div> </a> </div> <div class="flex items-center gap-1.5"> <div class="location-icon transition-all duration-300 mask-[url('./assets/images/icons/Location.svg')] mask-no-repeat mask-contain bg-foreground shrink-0"> <img src="./assets/images/icons/Location.svg" alt="" class="h-6 w-6 opacity-0" /> </div> <p class="text-[16px] leading-6 text-muted">Bali, Indonesia</p> </div> </div> </div> <a href="#" class="mt-[30px] w-fit flex items-center justify-center text-[16px] leading-6 font-semibold px-7 py-4 bg-primary rounded-xl transition-all duration-300 hover:shadow-primary"> <span>View All Chef</span> <div class="flex items-center justify-center h-6 w-6 shrink-0"> <img src="./assets/images/icons/arrow_right.svg" alt="" class="" /> </div> </a> </div> </div> </section> Kamu lihat di <section> ini, layoutnya tuh pakai Flexbox buat nge-center konten utama, jadi semuanya rapi di tengah layar. Di dalamnya ada dua bagian utama yang ukurannya fixed banget: satu sisi buat tampilin gambar chef yang kece dengan style absolute dan overflow-clip supaya gambarnya ngga keluar batas rounded-3xl, dan di atas gambar itu ada kartu info pengalaman chef yang dikasih drop shadow dan rounded buat bikin kesan keren dan profesional banget. Nah, gambar dan info ini diatur pakai position: absolute supaya bisa layering yang cakep, kayak main layer di design UI. Di sebelah kanan, kamu punya bagian tab menu yang isinya list chef-chef top yang keren banget. Masing-masing tab item itu clickable dengan efek hover halus (transition-all duration-300 hover:bg-white), pakai flex buat ngatur isi seperti nama chef, jenis masakan, dan lokasi dengan ikon location yang di-mask supaya tampilannya elegan. Teknik line-clamp-1 juga dipakai buat ngebatesin teks supaya ngga kelewat panjang dan tetap rapi tanpa pecah layout. Ini kayak kamu ngatur UI supaya user gampang scroll dan fokus ke satu chef tanpa kebingungan. Terakhir, ada tombol “View All Chef” yang desainnya eye-catching, dengan background bg-primary, padding dan rounded corners, plus efek shadow saat hover biar tombolnya kayak manggil-manggil kamu buat klik. Tombol ini pake flexbox juga supaya teks dan icon panahnya sejajar rapi. Intinya, struktur dan stylingnya padu banget pakai teknik CSS modern kayak flex, positioning absolute, mask, dan transition biar user experience kamu makin smooth dan keren. Kode JavaScript card.js document.addEventListener("DOMContentLoaded", () => { const cards = document.querySelectorAll(".card"); // Fungsi untuk mengatur lebar dan tampilan card info function updateCards() { cards.forEach((card) => { const cardInfo = card.querySelector(".card-info"); if (card.classList.contains("active")) { card.style.width = "400px"; cardInfo.classList.remove("hidden"); cardInfo.classList.add("flex"); } else { card.style.width = "214px"; cardInfo.classList.remove("flex"); cardInfo.classList.add("hidden"); } }); } // Inisialisasi card pertama sebagai aktif cards[0].classList.add("active"); updateCards(); // Tambahkan event listener untuk hover cards.forEach((card) => { card.addEventListener("mouseenter", () => { cards.forEach((c) => c.classList.remove("active")); card.classList.add("active"); updateCards(); }); card.addEventListener("mouseleave", () => { cards.forEach((c) => c.classList.remove("active")); cards[0].classList.add("active"); // Kembalikan ke card pertama updateCards(); }); }); }); Kode ini kayak bikin sebuah “slider” atau “carousel” kartu yang interaktif. Begitu halaman kamu selesai dimuat (DOMContentLoaded), skrip ini bakal cari semua elemen dengan kelas .card. Nah, tiap card itu nanti bisa “aktif” atau “nggak aktif” yang aktif ukurannya lebih gede (400px) dan bakal nampilin info tambahan ( .card-info ) pakai class flex, sedangkan yang nggak aktif ukurannya kecil (214px) dan info-nya disembunyiin dengan class hidden. Jadi ini kayak kamu lagi main highlight di antara beberapa kartu, yang lagi dipilih bakal lebih stand out dan jelas tampilannya. Terus, biar makin keren, tiap kali kamu hover (alias mouse masuk ke card), event listener mouseenter bakal otomatis ngehapus class active di semua card, terus pasang lagi di card yang kamu hover itu. Jadi ukurannya langsung nge-resize dinamis, pakai updateCards() yang nge-handle perubahan width dan tampilan info-nya secara real-time. Nah, kalau mouse keluar dari card (mouseleave), script ini bakal balikin highlight ke card pertama kayak reset posisi supaya user nggak bingung, tetap ada yang aktif terus. Jadi, kalau kamu pikir ini kayak efek “spotlight” di panggung, di mana spotlight cuma fokus ke satu aktor (card) sekaligus, dan aktor yang lain jadi lebih kecil sambil informasi detailnya disembunyiin. Kode ini ngandelin DOM manipulation dan classList API buat ngatur class CSS dan style inline langsung. Simple tapi powerful buat bikin UI yang responsif dan asik dipakai. dropdown.js document.addEventListener("DOMContentLoaded", () => { // Ambil semua tombol dropdown, menu, dan panah const dropdownButtons = document.querySelectorAll(".dropdown-button"); const dropdownMenus = document.querySelectorAll(".dropdown-menu"); const dropdownArrows = document.querySelectorAll(".dropdown-arrow"); // Fungsi untuk menangani klik pada tombol dropdown dropdownButtons.forEach((button, index) => { const menu = dropdownMenus[index]; const arrow = dropdownArrows[index]; button.addEventListener("click", () => { if (menu.classList.contains("opacity-0")) { // Sembunyikan semua dropdown lainnya dropdownMenus.forEach((m) => { m.classList.add("opacity-0"); m.classList.remove("opacity-100"); }); dropdownArrows.forEach((a) => (a.style.transform = "rotate(0deg)")); // Tampilkan dropdown yang dipilih menu.classList.remove("opacity-0"); menu.classList.add("opacity-100"); arrow.style.transform = "rotate(180deg)"; } else { // Sembunyikan dropdown saat diklik lagi menu.classList.remove("opacity-100"); menu.classList.add("opacity-0"); arrow.style.transform = "rotate(0deg)"; } }); }); // Fungsi untuk menutup dropdown saat mengklik di luar document.addEventListener("click", (event) => { dropdownButtons.forEach((button, index) => { const menu = dropdownMenus[index]; const arrow = dropdownArrows[index]; if (!button.contains(event.target) && !menu.contains(event.target)) { menu.classList.remove("opacity-100"); menu.classList.add("opacity-0"); arrow.style.transform = "rotate(0deg)"; } }); }); }); bayangin kamu lagi main sulap dengan dropdown di web, nah kode ini adalah “sihir” yang bikin dropdown-mu hidup! Jadi, pas halaman udah kelar dimuat (DOMContentLoaded), script ini bakal ngambil semua tombol dropdown (.dropdown-button), menu dropdown (.dropdown-menu), sama ikon panahnya (.dropdown-arrow). Intinya, tiap kali kamu klik tombol dropdown, script ini ngecek apakah menu dropdown-nya lagi tersembunyi atau nggak, pakai class CSS opacity-0 buat sembunyiin dan opacity-100 buat nampilin dengan efek transparansi. Jadi dropdownnya kayak magic muncul dan hilang. Terus, supaya nggak ribet dan rapi, kode ini juga bikin aturan kalau kamu klik satu tombol, semua dropdown lain langsung ditutup dulu. Ini biar gak ada yang buka banyak-banyak sekaligus dan bikin halaman jadi berantakan. Selain itu, ikon panahnya juga ikutan muter 180 derajat pas dropdown kebuka, kayak tanda panah lagi “ngasih kode” ke kamu, ini pakai manipulasi CSS transform: rotate(). Jadi gak cuma dropdown-nya yang interaktif, tapi ikon panahnya juga ikut ngejalanin animasi biar user experience-nya makin keren. Nah, ada juga bagian yang jenius nih, kalau kamu klik di luar dropdown atau tombolnya, dropdown otomatis nutup sendiri. Ini pake event listener di document yang ngecek target klik kamu, kalau kliknya bukan di tombol atau menu dropdown, ya semua dropdown langsung disembunyikan dan panah diputer balik lagi. Jadi kode ini pinter banget jaga-jaga supaya dropdown gak nyangkut kebuka terus, bikin UI kamu rapi dan enak dipakai. Jadi kamu bisa bilang, ini script dropdown-mu yang kerja kayak asisten pribadi, selalu siap buka tutup menu pas kamu butuh. main.js document.addEventListener("DOMContentLoaded", function () { new Swiper(".swiper", { slidesPerView: "auto", spaceBetween: 40, grabCursor: true, centeredSlides: false, }); }); bayangin kamu lagi nyusun slide foto atau konten keren yang bisa digeser-geser di halaman web, nah kode ini tuh yang jadi “otak” di balik layar itu! Jadi pas halaman udah siap (DOMContentLoaded), kamu langsung bikin instance baru dari Swiper, library JavaScript yang super powerfull buat bikin slider yang gampang dikendalikan. Dengan konfigurasi kayak slidesPerView: "auto", setiap slide bakal otomatis sesuaikan lebarnya, jadi gak kaku! Terus jarak antar slide diatur 40 piksel (spaceBetween: 40) biar slide-slide itu gak numpuk, ada ruang napas yang enak buat mata. Selain itu, ada fitur grabCursor: true yang bikin kursor kamu berubah jadi tangan siap “nangkep” slide, jadi interaksinya berasa lebih natural dan seru. Terus, centeredSlides: false bikin slide mulai dari kiri, bukan di tengah, jadi tampilannya kayak barisan slide biasa yang bisa kamu geser dengan gampang. Intinya, kode ini bikin slider kamu jadi responsif, interaktif, dan stylish cuma dengan beberapa baris aja. Simpel, tapi powerful. tab.js document.addEventListener("DOMContentLoaded", () => { const tabContents = [ { chefName: "Phoenix Satcheup", category: "Pizza", location: "Jakarta, Indonesia", experience: "12 Years", restaurant: "Pearl Dolphin", restaurantImage: "./assets/images/thumbnails/resto-4.png", chefImage: "./assets/images/thumbnails/chef-1.png", }, { chefName: "Chamber Botfrag", category: "Vegan", location: "Bandung, Indonesia", experience: "8 Years", restaurant: "Green Garden", restaurantImage: "./assets/images/thumbnails/resto-3.png", chefImage: "./assets/images/thumbnails/chef-2.webp", }, { chefName: "Asep Vandal", category: "Roast Chicken", location: "Sunda, Indonesia", experience: "10 Years", restaurant: "Sundanese Delight", restaurantImage: "./assets/images/thumbnails/resto-2.png", chefImage: "./assets/images/thumbnails/chef-3.webp", }, { chefName: "I Made Invoker", category: "Beef Steak", location: "Bali, Indonesia", experience: "15 Years", restaurant: "Bali Bistro", restaurantImage: "./assets/images/thumbnails/resto-1.png", chefImage: "./assets/images/thumbnails/chef-4.webp", }, ]; const tabs = document.querySelectorAll(".tab-item"); function updateTabContent(index) { const selectedContent = tabContents[index]; const chefImageElement = document.querySelector(".tab-content img"); if (chefImageElement) chefImageElement.src = selectedContent.chefImage; const chefNameElement = document.querySelector(".tab-content h2"); if (chefNameElement) chefNameElement.textContent = selectedContent.chefName; const experienceElement = document.querySelector(".experience-years"); if (experienceElement) experienceElement.textContent = selectedContent.experience; const restaurantNameElement = document.querySelector(".resto-name"); if (restaurantNameElement) restaurantNameElement.textContent = selectedContent.restaurant; const restaurantImageElement = document.querySelector( ".tab-content .h-[132px] img" ); if (restaurantImageElement) restaurantImageElement.src = selectedContent.restaurantImage; } function setActiveTab(index) { tabs.forEach((tab) => { tab.classList.remove("bg-white"); const profileDetailsLink = tab.querySelector("a"); if (profileDetailsLink) { profileDetailsLink.classList.remove("opacity-100"); profileDetailsLink.classList.add("opacity-0"); } const locationIcon = tab.querySelector(".location-icon"); if (locationIcon) { locationIcon.classList.remove("bg-muted"); locationIcon.classList.add("bg-foreground"); } }); const activeTab = tabs[index]; activeTab.classList.add("bg-white"); const profileDetailsLink = activeTab.querySelector("a"); if (profileDetailsLink) { profileDetailsLink.classList.remove("opacity-0"); profileDetailsLink.classList.add("opacity-100"); } const locationIcon = activeTab.querySelector(".location-icon"); if (locationIcon) { locationIcon.classList.remove("bg-foreground"); locationIcon.classList.add("bg-muted"); } } tabs.forEach((tab, index) => { tab.addEventListener("click", () => { setActiveTab(index); updateTabContent(index); }); }); setActiveTab(0); updateTabContent(0); }); Bayangin kamu lagi lihat halaman profil chef yang keren-keren, terus kamu mau lihat detail tiap chef dengan klik tab-tab yang ada. Nah, di sini ada array tabContents yang berisi data lengkap tiap chef, mulai dari nama, kategori makanan, pengalaman kerja, sampai foto chef dan restorannya. Jadi, tiap kali kamu klik salah satu tab, fungsi updateTabContent langsung jalan untuk ngubah isi halaman sesuai data chef yang kamu pilih ganti gambar, nama, pengalaman, dan info resto tanpa reload halaman. Praktis banget, kayak kamu scroll Instagram tapi kontennya berubah cepat dan mulus. Terus, supaya kamu gak bingung tab mana yang aktif, ada fungsi setActiveTab yang nge-handle styling tab yang lagi kamu pilih. Jadi tab yang aktif bakal punya background putih, link profilnya muncul dengan opacity penuh, dan ikon lokasi juga berubah warna supaya kamu gampang lihat mana yang sedang dipilih. Semua ini diatur dengan nambahin dan ngurangin kelas CSS secara dinamis pakai JavaScript, jadi tampilannya selalu rapi dan keren sesuai interaksi kamu. Gak cuma itu, setiap tab punya event listener yang siap nangkep klik kamu dan langsung nge-trigger dua fungsi tadi update konten dan set styling aktif. Jadi, kode ini kerja sama kayak DJ yang nyalain playlist sesuai request kamu, bikin pengalaman browsing info chef jadi asik, interaktif, dan smooth banget tanpa harus ribet reload halaman. Pokoknya, kamu tinggal klik, langsung dapet info yang kamu mau dengan tampilan yang kece. input.css @import url("<https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap>"); @import "tailwindcss"; :root { --background: #fafafa; --foreground: #232631; --primary: #fdc886; --secondary: #5a4fcf; --muted: #656565; --star: #ffb800; --placeholder: #858585; } @theme inline { --font-poppins: "Poppins", sans-serif; --color-background: var(--background); --color-foreground: var(--foreground); --color-primary: var(--primary); --color-secondary: var(--secondary); --color-muted: var(--muted); --color-star: var(--star); --color-placeholder: var(--placeholder); --drop-shadow-custom: 8px 8px 25px rgba(102, 102, 102, 0.04); --drop-shadow-custom2: -8px 8px 25px rgba(102, 102, 102, 0.04); --shadow-primary: 0 4px 10px 0 rgba(253, 200, 134, 0.8); --shadow-secondary: 0 4px 10px 0 rgba(90, 79, 207, 0.1); } @layer base { body { @apply bg-background text-foreground font-poppins; } } Bayangin kamu lagi nyiapin wardrobe keren buat website kamu. Di sini, kamu lagi impor font Poppins dari Google Fonts, jadi tipografi di halaman bakal tampil stylish dan modern banget kayak kamu lagi pilih outfit kece dari brand terkenal supaya tampil maksimal. Trus kamu juga impor Tailwind CSS, yang kayak toolkit super lengkap buat styling cepat dan rapi tanpa harus pusing bikin CSS dari nol. Nah, di bagian :root, kamu bikin semacam ‘warna-warna andalan’ yang nanti bisa dipakai berulang-ulang di seluruh website. Jadi, misalnya kamu mau pakai warna utama buat tombol atau background, tinggal panggil --primary aja. Ini kayak kamu punya palette warna khusus yang selalu kamu pakai biar desainnya konsisten dan gak bikin mata lelah. Ada juga warna khusus buat placeholder, shadow keren, dan warna-warna muted yang bikin tampilan makin dinamis dan enak dilihat. Terus, di bagian @theme inline kamu bikin varian variabel CSS yang nyambung ke warna dan font tadi, plus beberapa efek shadow custom yang bikin elemen di halaman kayak “ngambang” dengan efek cahaya lembut. Nah, terakhir, di @layer base kamu pakai directive @apply dari Tailwind untuk langsung set style dasar body: background, warna teks, dan font default dari Poppins itu. Jadi, intinya kamu udah bikin fondasi styling yang solid dan mudah dikembangkan tanpa ribet, biar website kamu tampil clean, konsisten, dan super profesional. .gitignore node_modules Gitignore dengan isi node_modules itu ibarat kamu punya lemari yang super gede penuh barang, tapi kamu gak mau semua barang itu ikut kamu bawa ke rumah teman saat nongkrong. Jadi, file node_modules itu tempatnya semua paket dan dependensi yang kamu download dari npm, ukurannya bisa super jumbo dan isinya bisa direbuild kapan aja dari package.json. Dengan nge-ignore folder ini di .gitignore, kamu ngasih tahu Git buat gak ikut nyimpen folder node_modules ke repository, supaya repo kamu tetap ringan, gak penuh sampah, dan proses push-pull jadi lebih cepat. Jadi intinya, folder node_modules itu gampang dibuat ulang, gak perlu dibawa-bawa ke remote git. package.json { "name": "resto", "version": "1.0.0", "description": "", "license": "ISC", "author": "", "type": "commonjs", "main": "/src/index.html", "scripts": { "dev": "npx @tailwindcss/cli -i ./src/input.css -o ./src/output.css --watch" }, "dependencies": { "@tailwindcss/cli": "^4.1.3", "tailwindcss": "^4.1.3" } } jadi ini adalah isi file package.json yang jadi otak dari proyek Node.js atau frontend kamu, khususnya yang pakai Tailwind CSS. Di sini, ada beberapa info penting seperti name proyek kamu (dalam hal ini "resto"), versi, dan lisensi. Nah, bagian scripts itu keren banget karena kamu bisa bikin perintah singkat buat jalanin hal-hal yang sering kamu lakukan. Misalnya, script dev ini bakal ngejalanin Tailwind CSS CLI secara otomatis, nge-compile file CSS input (input.css) ke output (output.css), dan yang paling asik, dia terus “watch” alias mantau perubahan di file input, jadi tiap kamu simpan perubahan, Tailwind langsung update CSS-nya tanpa kamu harus ngapa-ngapain lagi. Terus di bagian dependencies, itu tempat kamu nyimpen paket-paket yang dipakai proyek kamu, dalam hal ini ada @tailwindcss/cli dan tailwindcss versi 4.1.3. Jadi, setiap kali kamu atau temen kamu clone project ini, tinggal ketik npm install atau yarn buat otomatis download semua paket ini sesuai versi yang tertulis, biar semua lingkungan kerja sama dan gak ada yang versi beda-beda. Singkatnya, package.json ini semacam peta dan remote control buat ngatur seluruh dependency dan perintah penting dalam proyek kamu. vercel.json { "builds": [ { "src": "src/**/*", "use": "@vercel/static" } ], "routes": [ { "src": "/(.*)", "dest": "/src/$1" } ] } Ini konfigurasi buat Vercel yang ngatur gimana cara nge-deploy project kamu: bagian builds bilang kalau semua file di folder src bakal diproses sebagai konten statis pakai builder @vercel/static, jadi Vercel tahu harus ngirim file-file itu apa adanya ke server. Terus di bagian routes, setiap request URL yang masuk bakal diarahkan ke file yang sesuai di folder src, jadi misalnya kamu buka /about, dia bakal nyari file src/about buat ditampilin, intinya ini bikin routing simple dan bikin file di src bisa langsung diakses kayak di root website kamu. Cara Mengedit Buat ngedit sesuatu itu gampang banget, misalnya kamu pengen ubah teks “Why Should Choose Us?” di kodenya. Caranya simpel, kamu tinggal pencet Ctrl + F di VSCode, terus ketik keyword atau kata kunci yang mau kamu cari, misal “Why Should Choose Us?”. Nah, otomatis VSCode bakal langsung bawa kamu ke bagian kodenya yang isinya teks itu. Tinggal kamu ganti deh teksnya sesuai yang kamu mau, terus simpan. Setelah itu, coba reload atau refresh halaman di browser, dan kamu bakal lihat perubahan yang kamu buat langsung muncul tanpa ribet. Contohnya kayak gini: Resto - Video Tutorial How to Edit Beragam Template HTML + Tailwind CSS ( FREE )🙌 Shaynakit - HTML Template Nah, yang terakhir nih, kalau kamu pengen langsung dapetin template yang udah jadi lengkap sama HTML dan Tailwind CSS-nya, tinggal dipakai aja tanpa harus ribet ngoding dari nol, kamu bisa mampir ke situs Shaynakit. Di sana banyak banget pilihan template gratis yang keren-keren, tapi juga ada yang versi premium kalau kamu pengen yang lebih eksklusif. Template-nya juga lengkap banget, mulai dari desain buat mobile sampai desktop, jadi cocok buat apapun kebutuhan proyek kamu. Pokoknya tinggal daftar atau registrasi, terus pilih deh template mana yang kamu suka, download, dan langsung pakai di proyek kamu. Ini cara yang asik banget buat ngehemat waktu dan tetep dapet hasil desain yang kece tanpa harus pusing mikirin styling dari awal. Jadi, jangan ragu buat eksplor dan manfaatin sumber daya keren ini buat bikin proyek kamu makin mantap. Penutup Sebagai penutup, kamu sekarang sudah punya sumber kode HTML dan Tailwind CSS lengkap dengan contoh dan penjelasannya supaya gak bingung. Kalau kamu butuh template kece lainnya, tinggal cek aja situs Shaynakit yang penuh dengan desain dan kode siap pakai. Jadi, semangat terus belajar dan eksplorasi supaya kamu bisa bikin proyek web yang keren banget.

Kelas Tutorial Next JS 15 Belajar Server dan Client Components Projek Web Booking Hotel di BuildWithAngga

Tutorial Next JS 15 Belajar Server dan Client Components Projek Web Booking Hotel

Kalau kamu baru mau mulai belajar bikin website modern, Next.js 15 adalah salah satu framework yang wajib kamu lirik. Framework ini dibangun di atas React, tapi punya banyak fitur tambahan yang bikin proses bikin web jadi lebih simpel, lebih cepat, dan hasilnya juga lebih SEO-friendly. Jadi kalau kamu pengen bantuin bisnis online biar lebih mudah ditemukan di Google, atau pengen klien kamu puas karena websitenya performanya mantap, Next.js bisa jadi solusi yang tepat. Yang bikin Next.js 15 makin menarik adalah kemampuannya dalam urusan SEO dan performa. Kita tahu, dua hal ini penting banget buat bisnis online. SEO itu ngaruh ke berapa banyak orang bisa nemuin website kamu lewat pencarian, sementara performa itu ngaruh ke apakah orang betah atau nggak buka websitenya. Next.js 15 hadir buat meanjawab dua masalah itu secara elegan, karena dia bisa bantu kamu ngerender halaman langsung dari server (yang lebih cepet diakses dan dibaca mesin pencari), tapi juga bisa fleksibel saat kamu butuh interaksi dinamis dari sisi pengguna. Kenapa Harus Paham Perbedaan Server dan Client Component? Nah, kalau kamu baru banget mulai, mungkin istilah server component dan client component masih terdengar asing. Tapi percaya deh, ini salah satu hal paling penting yang harus kamu kuasai dulu sebelum ngoding lebih jauh di Next.js 15. Singkatnya, komponen server itu dijalankan di server, artinya data bisa diolah duluan sebelum dikirim ke browser. Hasilnya? Website kamu bisa tampil lebih cepat dan langsung ramah SEO karena kontennya udah siap ketika user mengakses. Sedangkan client component dijalankan di browser, cocok buat fitur-fitur interaktif yang butuh respon langsung dari user, seperti klik tombol, buka modal, atau update state. Kalau kamu asal pakai semuanya di client padahal bisa di-handle server, efeknya bisa bikin web kamu jadi lambat dan susah terbaca mesin pencari. Sebaliknya, kalau kamu maksa semua di server tapi butuh interaksi, hasilnya juga bisa nge-lag dan nggak responsif. Makanya penting banget untuk tahu kapan pakai yang mana. Kita Akan Belajar Perlahan, Jangan Takut Duluan Tenang aja, artikel ini dibuat buat kamu yang baru mulai banget. Kita bakal bahas perlahan, dari konsep dasarnya dulu, biar kamu nggak bingung. Kita akan pelan-pelan bongkar gimana cara kerja server dan client components di Next.js 15, kenapa ini penting banget buat performa dan SEO, dan kapan waktu terbaik buat pakai masing-masing. Tujuannya adalah supaya kamu punya pondasi yang kuat dulu. Karena kalau fondasi kamu udah paham, ke depannya mau bikin website e-commerce, portfolio, company profile, sampai SaaS platform, semua bakal lebih mudah. Artikel ini bukan cuma ngajarin ngoding doang, tapi juga ngajak kamu mikir sebagai developer yang ngerti kenapa harus begini, bukan cuma ikut-ikutan tutorial aja. Lanjut yuk ke bagian berikutnya, di mana kita mulai bahas bagaimana cara membedakan dan menggunakan server component dan client component dengan lebih praktis. Apa Itu Server Component di Next.js 15? Kalau kamu baru kenal Next.js 15, kamu pasti sering dengar istilah server component. Tapi sebenarnya, apa sih server component itu? Server component adalah komponen React yang dijalankan di server, bukan di browser user. Jadi, ketika user membuka halaman website kamu, server-lah yang lebih dulu menjalankan logika dan menghasilkan tampilan HTML-nya. Setelah hasil HTML itu siap, baru dikirim ke browser. Dengan cara ini, user langsung melihat halaman yang sudah siap tampil, tanpa perlu nunggu proses JavaScript di browser. Berbeda dengan client component yang perlu waktu tambahan untuk diload dan dijalankan di browser (karena harus menunggu JavaScript siap), server component itu ibaratnya udah nyiapin semua makanan sebelum diantar ke meja kamu. Kamu tinggal duduk, dan makanan langsung tersedia. Nggak perlu nunggu dimasak lagi di depan kamu. Next.js 15 mempermudah proses ini dengan pembagian otomatis mana komponen yang berjalan di server dan mana yang butuh interaksi dan harus berjalan di sisi klien (browser). Jadi kita sebagai developer bisa fokus membangun pengalaman pengguna yang cepat, nyaman, dan tetap SEO-friendly. Manfaat Utama dari Server Component Ngomongin soal manfaatnya, server component itu bisa dibilang “raja” dalam urusan kecepatan dan SEO. Kenapa? Karena dia bekerja secara efisien dari sisi server dan menghindari kerja ekstra di browser user. Berikut beberapa manfaat paling terasa: SEO Lebih Optimal Konten halaman sudah siap saat dikirim ke browser, jadi mesin pencari seperti Google bisa langsung membaca dan mengindeks kontennya dengan mudah. Cocok banget buat halaman yang butuh tampil di hasil pencarian, seperti halaman detail hotel, promo kamar, atau artikel blog.Waktu Loading Lebih Cepat Karena data langsung diproses dari server, user nggak perlu nunggu JavaScript di browser selesai dijalankan dulu. Halaman bisa tampil hampir seketika.Bundle Size Lebih Kecil Komponen yang dijalankan di server nggak perlu dikirim ke browser dalam bentuk JavaScript. Artinya, ukuran file yang perlu didownload user jadi lebih kecil. Ini bikin website kamu lebih ringan dan hemat kuota.Keamanan Lebih Baik Proses data penting atau sensitif seperti akses database, autentikasi, atau validasi bisa tetap dilakukan aman di sisi server. User nggak akan bisa ngintip atau manipulasi proses ini dari browser.Arsitektur Lebih Rapi Kamu bisa pisahkan dengan jelas mana komponen yang hanya bertugas menampilkan data, dan mana yang bertugas menerima input dari user. Ini bikin struktur kode kamu lebih mudah dipelihara. Analogi Simpel Supaya Lebih Paham Bayangin kamu lagi pengen booking hotel buat liburan ke Bali. Kamu punya dua pilihan cara untuk cari hotel: Cara pertama (Server Component): Kamu buka aplikasi travel dan langsung dapet halaman yang udah lengkap isinya — daftar hotel, harga per malam, fasilitas, dan ulasan pelanggan. Semua sudah ditata rapi dan langsung muncul begitu kamu buka. Enak kan?Cara kedua (Client Component): Kamu buka aplikasinya, tapi halaman awal kosong. Lalu perlahan-lahan isinya mulai muncul satu-satu — loading harga, loading nama hotel, loading gambar. Kamu nunggu semuanya siap sambil bengong. Nggak enak, apalagi kalau internet lemot. Nah, Next.js 15 dengan server component ngasih kamu pengalaman seperti cara pertama. Data hotelnya udah disiapkan dari awal. Pengguna tinggal lihat dan pilih. Contoh Koding Lengkap Halaman Hotel Sekarang kita lihat contoh real-nya di project Next.js 15. Bayangin kamu bikin halaman daftar hotel di file app/hotels/page.tsx. Komponen ini akan di-render di server dan siap tampil dengan cepat. // app/hotels/page.tsx import { getAllHotels } from '@/lib/hotel.api'; import Image from 'next/image'; export default async function HotelListPage() { const hotels = await getAllHotels(); // Fetch data langsung di server return ( <div className="max-w-5xl mx-auto py-12"> <h1 className="text-3xl font-bold mb-6">Temukan Hotel Terbaik untuk Liburanmu</h1> <p className="text-gray-600 mb-10">Berbagai pilihan hotel dengan fasilitas terbaik, lokasi strategis, dan harga yang bersahabat.</p> <div className="grid grid-cols-2 gap-6"> {hotels.map((hotel) => ( <div key={hotel.id} className="border rounded-xl p-4 shadow bg-white"> <Image src={hotel.image} alt={hotel.name} width={400} height={250} className="rounded-lg" /> <h2 className="text-xl font-semibold mt-4">{hotel.name}</h2> <p className="text-sm text-gray-600">{hotel.location}</p> <p className="mt-2 text-green-600 font-bold"> Rp {hotel.pricePerNight.toLocaleString('id-ID')} / malam </p> </div> ))} </div> </div> ); } Apa yang Terjadi di Koding Ini? Fungsi getAllHotels() akan ambil data dari database atau API, dan ini dilakukan langsung di server.Karena kita pakai async function, kita bisa langsung pakai await di dalam komponen. Ini fitur eksklusif buat server component.Hasil HTML dari komponen ini akan langsung dikirim ke browser, jadi user nggak nungguin data dimuat lewat JavaScript.Komponen ini nggak punya interaksi dinamis (kayak klik tombol atau input), jadi cocok dijalankan dari server. Dengan pendekatan ini, halaman daftar hotel kamu jadi lebih cepat terbuka, lebih SEO-friendly, dan lebih efisien untuk user. Cocok banget buat weeb booking hotel yang butuh kecepatan dan kepercayaan. Setelah paham server component, di bagian selanjutnya kita bakal bahas client component, bagian yang berperan besar dalam membuat halaman hotel jadi lebih interaktif dan user bisa berkomunikasi dengan aplikasi secara langsung. Apa Itu Client Component di Next.js 15? Setelah kamu kenalan dengan server component, sekarang saatnya kita bahas client component — pasangan penting dalam pengembangan aplikasi Next.js 15. Kalau server component dijalankan di server dan menghasilkan HTML siap tampil, client component adalah komponen yang dijalankan di browser user. Artinya, semua logika, state (data sementara), event handler seperti onClick, onChange, sampai interaksi real-time — semuanya terjadi di sisi klien (client-side). Dalam proyek website booking hotel, client component cocok banget digunakan untuk bagian interaktif, misalnya: Formulir pencarian hotel berdasarkan lokasi dan tanggalTombol “Lihat Detail” atau “Booking Sekarang”Fitur filter berdasarkan harga, rating, atau fasilitasModal popup yang muncul saat user klik sesuatuDropdown pemilihan jumlah tamu atau kamar Pokoknya, kalau kamu butuh interaksi dari user dan ingin websitenya terasa “hidup”, kamu bakal pakai client component. Manfaat Utama Client Component Bisa Tangani Interaksi Langsung dari User Client component memungkinkan kamu menambahkan event seperti klik tombol, input teks, validasi form, dan sebagainya. Hal-hal seperti ini nggak bisa dilakukan di server component.Penggunaan State yang Fleksibel Kamu bisa pakai state (misalnya dengan useState) untuk menyimpan data sementara, seperti isian form atau status toggle.Pengalaman Pengguna Lebih Interaktif Misalnya ketika user klik tombol untuk membuka popup, mengganti tanggal booking, atau melihat harga terbaru, kamu bisa langsung merespon tanpa reload halaman.Cocok untuk Komponen UI Kompleks Kalau kamu bikin komponen seperti carousel gambar, kalender booking, atau sidebar filter dinamis, semuanya butuh client component agar bisa jalan. Analogi Simpel Supaya Makin Paham Bayangin kamu lagi di hotel dan pengen pesan makanan dari kamar. Kalau kamu cuma nerima brosur (kayak server component), kamu tahu daftar makanannya, tapi kamu tetap harus kontak resepsionis buat order. Nah, kalau client component, itu seperti kamu dikasih tablet di kamar yang bisa langsung kamu pencet-pencet buat order, bayar, dan atur pengiriman ke kamar. Semua bisa kamu lakukan langsung dari situ — interaktif dan instan. Client component itu penting banget untuk interaksi seperti itu. Jadi kombinasi antara brosur (server component) dan tablet interaktif (client component) itulah yang bikin pengalaman pengguna jadi komplit. Contoh Koding Client Component di Next.js 15 Sekarang kita bikin contoh client component di halaman booking hotel, misalnya komponen pencarian hotel berdasarkan nama kota yang bisa langsung merespon input user. 'use client'; import { useState } from 'react'; export default function HotelSearchForm() { const [city, setCity] = useState(''); const [results, setResults] = useState([]); const handleSearch = async () => { const res = await fetch(`/api/search-hotels?city=${city}`); const data = await res.json(); setResults(data.hotels); }; return ( <div className="p-6 bg-white rounded-xl shadow-md max-w-xl mx-auto"> <h2 className="text-xl font-semibold mb-4">Cari Hotel Berdasarkan Kota</h2> <input type="text" value={city} onChange={(e) => setCity(e.target.value)} placeholder="Contoh: Bandung" className="w-full border px-4 py-2 rounded-md mb-4" /> <button onClick={handleSearch} className="bg-blue-600 text-white px-6 py-2 rounded-md" > Cari Hotel </button> {results.length > 0 && ( <div className="mt-6"> <h3 className="text-lg font-medium mb-2">Hasil Pencarian:</h3> <ul className="space-y-2"> {results.map((hotel: any) => ( <li key={hotel.id} className="border rounded-md p-3 hover:bg-gray-50 transition" > <p className="font-bold">{hotel.name}</p> <p className="text-sm text-gray-600">{hotel.location}</p> </li> ))} </ul> </div> )} </div> ); } Apa yang Terjadi di Komponen Ini? Baris ‘use client’; di paling atas wajib ditulis. Ini memberi tahu Next.js bahwa komponen ini harus dijalankan di sisi browser.Kita pakai useState untuk menyimpan input kota dan hasil pencarian.Saat user mengetik nama kota, datanya langsung disimpan tanpa reload halaman.Ketika tombol “Cari Hotel” ditekan, kita fetch data dari API, dan tampilkan hasilnya langsung di bawahnya.Semua ini hanya bisa dilakukan di client component, karena bergantung pada interaksi user secara langsung dan state yang berubah-ubah. Kapan Harus Pakai Client Component? Pakai client component kalau kamu butuh: Interaksi langsung (klik, input, validasi)State lokal yang berubah-ubahKomponen dinamis seperti dropdown, toggle, modalEfek animasi atau event pengguna (hover, scroll) Tapi tetap harus bijak. Jangan semua komponen dijadikan client component, karena itu bisa bikin bundle JavaScript kamu jadi besar dan berat. Pakai client component hanya untuk bagian yang memang butuh. Dengan menggabungkan server component untuk tampilan awal dan SEO, serta client component untuk interaksi pengguna, kamu bisa bikin web booking hotel yang cepat, canggih, dan tetap enak digunakan. Di bagian selanjutnya, kita akan lihat bagaimana menggabungkan dua pendekatan ini dalam satu halaman — biar websitemu makin optimal! Menggabungkan Server dan Client Component dalam Satu Halaman Setelah paham perbedaan dan fungsi masing-masing, sekarang saatnya kita bahas hal yang paling sering dilakukan di project nyata: menggabungkan server dan client component dalam satu halaman. Ini adalah pendekatan yang sangat umum di Next.js 15 — dan justru inilah kekuatannya. Bayangin kamu sedang bikin halaman utama untuk web booking hotel. Di bagian atas halaman, kamu ingin menampilkan daftar hotel secara statis berdasarkan data dari server (server component). Tapi di bagian bawahnya, kamu pengin kasih filter interaktif supaya user bisa cari hotel berdasarkan kota, harga, atau tanggal (client component). Nah, kombinasi kayak gini sangat ideal dan bikin pengalaman pengguna jadi lengkap. Kenapa Harus Digabung? Karena nggak semua bagian halaman perlu interaksi. Kalau semua kamu jadikan client component, websitenya jadi berat dan lambat. Tapi kalau semua server, user jadi nggak bisa ngapa-ngapain secara langsung. Dengan Next.js 15, kamu bisa dapat yang terbaik dari dua dunia: Server component bikin halaman cepat tampil dan SEO-friendlyClient component bikin interaksi lebih hidup dan personal Contoh Koding Kombinasi Server + Client Berikut ini contoh struktur file app/hotels/page.tsx yang merupakan server component utama, lalu di dalamnya kita import client component HotelSearchForm. // app/hotels/page.tsx (SERVER COMPONENT) import { getAllHotels } from '@/lib/hotel.api'; import HotelSearchForm from '@/components/HotelSearchForm'; import Image from 'next/image'; export default async function HotelListPage() { const hotels = await getAllHotels(); // Data diambil dari server return ( <div className="max-w-5xl mx-auto py-12"> <h1 className="text-3xl font-bold mb-6">Temukan Hotel Terbaik</h1> <div className="grid grid-cols-2 gap-6 mb-12"> {hotels.map((hotel) => ( <div key={hotel.id} className="border rounded-xl p-4 shadow bg-white"> <Image src={hotel.image} alt={hotel.name} width={400} height={250} className="rounded-lg" /> <h2 className="text-xl font-semibold mt-4">{hotel.name}</h2> <p className="text-sm text-gray-600">{hotel.location}</p> <p className="mt-2 text-green-600 font-bold"> Rp {hotel.pricePerNight.toLocaleString('id-ID')} / malam </p> </div> ))} </div> {/* Bagian Interaktif */} <HotelSearchForm /> </div> ); } Dan ini file components/HotelSearchForm.tsx sebagai client component: // components/HotelSearchForm.tsx (CLIENT COMPONENT) 'use client'; import { useState } from 'react'; export default function HotelSearchForm() { const [city, setCity] = useState(''); const [results, setResults] = useState([]); const handleSearch = async () => { const res = await fetch(`/api/search-hotels?city=${city}`); const data = await res.json(); setResults(data.hotels); }; return ( <div className="p-6 bg-white rounded-xl shadow-md"> <h2 className="text-xl font-semibold mb-4">Cari Hotel Berdasarkan Kota</h2> <input type="text" value={city} onChange={(e) => setCity(e.target.value)} placeholder="Contoh: Yogyakarta" className="w-full border px-4 py-2 rounded-md mb-4" /> <button onClick={handleSearch} className="bg-blue-600 text-white px-6 py-2 rounded-md" > Cari Hotel </button> {results.length > 0 && ( <ul className="mt-4 space-y-2"> {results.map((hotel: any) => ( <li key={hotel.id} className="border p-3 rounded-md shadow-sm"> <p className="font-bold">{hotel.name}</p> <p className="text-sm text-gray-500">{hotel.location}</p> </li> ))} </ul> )} </div> ); } Penjelasan Alurnya HotelListPage adalah server component. Jadi halaman ini bisa langsung render daftar hotel dengan cepat saat user mengakses.Di dalamnya kita menyisipkan HotelSearchForm, yang merupakan client component. Jadi bagian ini akan berjalan di browser.User bisa langsung input kota dan lihat hasil pencarian tanpa reload — karena bagian ini dinamis.Pendekatan ini memberikan first load yang cepat dan tetap mendukung interaktivitas real-time. Kesimpulan Menggabungkan server dan client component dalam satu halaman adalah hal yang sangat umum dan powerful di Next.js 15. Ini adalah cara paling optimal untuk membangun website modern: cepat, SEO-friendly, dan tetap interaktif. Jadi mulai sekarang, saat kamu bikin halaman apapun — entah itu homepage, booking form, atau katalog hotel — pikirkan dulu mana bagian yang bisa disajikan dari server, dan mana bagian yang perlu interaksi dari client. Dengan cara ini, web kamu akan terasa lebih profesional, lebih ringan, dan jauh lebih menyenangkan digunakan oleh pengunjung. Di artikel berikutnya, kita bisa lanjut bahas gimana caranya optimasi SEO dan performa lebih dalam lagi, sambil tetap mempertahankan user experience terbaik di Next.js 15. Penutup: Saatnya Naik Level Bareng Mentor Expert Kalau kamu sudah sampai di bagian akhir artikel ini, artinya kamu serius banget ingin memahami Next.js 15 dengan benar. Dan itu langkah yang keren banget. Tapi, jujur aja, belajar sendiri kadang bisa bikin frustasi. Banyak fitur baru, banyak istilah asing, kadang kita udah ngoding bener tapi hasilnya nggak sesuai harapan. Di sinilah belajar bareng mentor expert jadi solusi paling efektif. Bayangin kamu punya seseorang yang udah pernah ngerjain real project dengan Next.js, yang ngerti seluk-beluk client dan server components, yang tahu kesalahan umum pemula, dan bisa bantu kamu debug saat kamu stuck. Belajar jadi lebih cepat, lebih terarah, dan jauh lebih menyenangkan. Dengan ikut belajar bareng mentor: Kamu bisa dapet feedback langsung dari orang yang lebih berpengalamanAda komunitas belajar yang bikin kamu tetap semangat dan nggak merasa sendirianKamu bisa dapet template dan resource premium yang siap pakaiBelajar bukan cuma teori, tapi langsung bikin project nyata yang bisa dipakai buat portofolioDan yang paling penting: kamu bisa tanya apa aja tanpa takut di-judge Buat kamu yang pengen kerja sebagai frontend developer profesional, atau ingin ngebantu bisnis online dengan performa web yang lebih cepat dan SEO-friendly, belajar bareng mentor itu investasi terbaik yang bisa kamu ambil hari ini. Yuk, jangan cuma jadi penonton. Saatnya kamu sendiri yang bikin karya hebat. Belajar bareng mentor di BuildWithAngga, dan rasain sendiri bedanya ketika kamu punya support system yang solid. 🚀💻 Sampai ketemu di artikel dan kelas selanjutnya!

Kelas Tutorial Next JS 15 Belajar Image Optimization di BuildWithAngga

Tutorial Next JS 15 Belajar Image Optimization

Pernah gak kamu buka sebuah website, dan dalam 3 detik langsung tutup tab-nya karena tampilannya meh banget? Nah, hal kayak gitu tuh bisa berdampak besar buat bisnis online. Di dunia digital sekarang, kesan pertama pengguna ditentukan bukan dari kata-kata, tapi dari tampilan visual yang mereka lihat di layar. Bayangin kamu punya produk bagus, layanan keren, bahkan diskon besar-besaran… tapi desain websitenya berantakan, loading-nya lama, gambar-gambar pecah, dan warna-warnanya bikin mata sakit. Udah pasti banyak pengunjung yang bakal langsung kabur, bukan karena produkmu jelek, tapi karena first impression-nya gagal total. Tampilan website yang cantik itu bukan soal gaya-gayaan. Ini soal membangun kepercayaan, meningkatkan waktu kunjungan, dan yang paling penting: mendorong konversi. Orang yang merasa nyaman di sebuah halaman, kemungkinan besar akan lebih lama mengeksplor, membaca lebih lanjut, bahkan akhirnya klik tombol beli sekarang atau hubungi kami. Dan jangan salah, tampilan yang menarik bukan hanya urusan desainer aja. Frontend developer juga punya peran penting buat mewujudkan desain jadi pengalaman nyata. Gambar yang dimuat, cara loading-nya, responsif-nya, semuanya berpengaruh ke persepsi pengguna. Makanya, sebelum mikirin fitur canggih atau sistem login yang kompleks, pastikan dulu tampilannya enak dipandang. Karena di dunia online, mata adalah gerbang ke dompet 💸 Kita Akan Belajar Soal Gambar di Next.js Nah, masuk ke topik utama. Di artikel ini, kita bakal bahas pentingnya penggunaan image yang baik dalam framework Next.js. Terutama buat kamu yang masih baru banget mulai belajar Next.js, ini adalah salah satu fondasi penting yang sering dianggap remeh. Gambar itu bukan cuma pemanis tampilan, tapi juga bisa memengaruhi kecepatan website, SEO, dan kenyamanan pengguna. Salah satu keunggulan Next.js adalah dia punya sistem optimasi gambar bawaan yang canggih, dan yes, ini sangat direkomendasikan buat pemula karena bisa langsung dapet benefit besar tanpa ribet. Kita gak langsung masuk ke coding dulu ya. Di bagian awal ini, tujuannya supaya kamu ngerti dulu kenapa hal ini penting banget. Setelah kamu paham konteks dan alasannya, barulah nanti kita pelajari gimana cara implementasinya di proyek nyata. Jadi, siapkan diri kamu. Karena kita akan eksplor fitur image di Next.js yang bisa bikin website kamu bukan cuma tampil cantik, tapi juga cepat dan efisien 🚀 Gambar di Next.js Gak Sama Kayak <img>, Tapi Bisa Gantikan dengan Cara Lebih Pintar Kalau kamu udah biasa pakai tag HTML <img>, kamu mungkin bakal mikir: “Lah, kenapa sih harus repot-repot ganti ke komponen <Image /> dari Next.js?” Jawabannya simpel: <Image /> itu versi modern dan smart dari <img>. Dia bawa fitur bawaan seperti lazy loading otomatis, optimasi ukuran gambar, dan format gambar modern (seperti WebP) — semua ini bisa ngebantu banget buat performa website kamu tanpa perlu setting manual. Tapi perlu diingat ya, <Image /> ini bukan 100% drop-in replacement dari <img>. Ada aturan mainnya. Kalau kamu asal copy-paste <img> terus ganti jadi <Image>, kemungkinan besar error. Yuk kita lihat perbedaannya. Contoh <img> biasa: <img src="/assets/images/hero.png" alt="Hero Banner" /> Kalau kamu pakai komponen <Image /> dari Next.js, kamu harus import dulu dan struktur penggunaannya beda: import Image from 'next/image' export default function HeroSection() { return ( <div> <Image src="/assets/images/hero.png" alt="Hero Banner" width={600} height={400} /> </div> ) } Perlu diperhatikan, kamu gak bisa pakai path dari luar (URL full dari domain lain) secara langsung tanpa setting tambahan. Dan kamu gak boleh asal nulis <Image src="..." /> tanpa kasih tahu ukuran gambar. Jadi intinya: <Image /> itu memang gantinya <img>, tapi kamu harus ngerti cara pakainya supaya gak error dan justru bikin frustrasi. Harus Pakai width dan height, Kecuali Kamu Pakai Layout Khusus Satu hal yang bikin developer baru sering bingung waktu pakai <Image /> adalah: kenapa harus banget ada width dan height? Kalau pakai <img> kan tinggal tempel, langsung jalan. Tapi di Next.js, kamu bakal kena error kalau gak spesifik kasih ukuran. Ini bukan Next.js iseng, tapi justru demi kebaikan performa website kamu. Dengan ukuran yang jelas, browser bisa langsung hitung layout halaman sebelum gambar benar-benar muncul — hasilnya: gak ada layout shift yang ganggu UX. Contoh penggunaannya: import Image from 'next/image' export default function ProfileCard() { return ( <div className="w-[300px] p-4 border rounded-lg"> <Image src="/assets/images/avatar.png" alt="User Avatar" width={100} height={100} className="rounded-full" /> <h3 className="mt-4 font-semibold text-lg">Andi Prasetyo</h3> <p className="text-gray-500">Fullstack Developer</p> </div> ) } Tapi gimana kalau kamu gak tahu ukurannya, atau kamu pengen gambar ini responsif? Tenang, Next.js kasih opsi lain: kamu bisa pakai prop fill atau layout="fill" (di versi lama). Tapi ini perlu container yang punya posisi relatif dan ukuran yang ditentukan. Contoh penggunaan fill: import Image from 'next/image' export default function FullCover() { return ( <div className="relative w-full h-[400px]"> <Image src="/assets/images/banner.jpg" alt="Cover Image" fill style={{ objectFit: 'cover' }} /> </div> ) } Yang penting kamu ingat: kalau gak pakai width dan height, maka kamu harus pakai pendekatan khusus seperti fill, dan pastikan container-nya punya ukuran yang jelas. Kalau dua-duanya gak ada? Ya… bakal error. Jadi jangan lupa aturan main ini biar pengalaman coding kamu lebih lancar 😉 Semua Gambar Di-Load Secara Lazy Otomatis — Tanpa Perlu Kamu Atur Kalau kamu pernah ngoding manual dan pakai <img loading="lazy" /> biar gambar gak langsung dimuat semua pas user buka halaman, kamu pasti tahu pentingnya lazy loading. Ini bikin halaman lebih ringan dan cepat tampil, terutama kalau ada banyak gambar. Nah, enaknya pakai <Image /> dari Next.js itu kamu gak perlu nulis loading="lazy" lagi. Soalnya Next.js udah otomatis menerapkan lazy loading untuk semua gambar yang pakai komponen ini. Artinya, gambar hanya akan dimuat ketika sudah hampir masuk ke viewport (layar user). Contohnya kayak gini: import Image from 'next/image' export default function BlogThumbnail() { return ( <div className="p-6 border rounded-lg w-full max-w-md"> <Image src="/assets/images/article-cover.jpg" alt="Cover Artikel" width={600} height={350} /> <h2 className="text-xl font-bold mt-4">Tips Belajar Next.js untuk Pemula</h2> <p className="text-gray-600 mt-2">Pelajari cara kerja komponen image yang powerful ini...</p> </div> ) } Gak ada keterangan lazy loading di kode? Betul. Tapi saat kamu cek DevTools atau scroll pelan-pelan, kamu akan lihat bahwa gambar baru dimuat saat mendekati layar. Ini karena sistemnya udah smart banget. Jadi kamu tinggal fokus ke desain dan strukturnya aja, sisanya Next.js bantuin optimasinya dari belakang layar 🛠️ Format Gambar Diubah Otomatis ke WebP atau yang Lebih Ringan Pernah dengar format gambar WebP? Itu loh, format gambar yang lebih ringan dari JPEG atau PNG tapi kualitasnya tetap bagus. Format ini bisa bikin loading website lebih cepat — terutama di koneksi yang lambat atau di device mobile. Nah, satu lagi fitur keren dari <Image /> di Next.js adalah: kamu gak perlu konversi gambar ke WebP secara manual. Next.js secara otomatis akan memilih format gambar paling optimal berdasarkan browser yang digunakan user. Misalnya kamu upload gambar PNG, lalu user buka website dari Chrome yang support WebP — maka Next.js akan otomatis kasih versi WebP ke browser tersebut. Kalau browsernya gak support WebP, ya gak masalah — fallback ke format asli. Jadi aman buat semua pengguna. Coba lihat contoh ini: import Image from 'next/image' export default function ProductCard() { return ( <div className="border p-4 rounded-md w-[300px]"> <Image src="/assets/images/shoes.png" alt="Sepatu Keren" width={280} height={200} className="rounded-md" /> <h4 className="font-semibold text-lg mt-3">Sepatu Lari Pro</h4> <p className="text-sm text-gray-500 mt-1">Ringan, stylish, dan nyaman dipakai seharian</p> </div> ) } Kamu upload-nya shoes.png, tapi user bisa aja nerima shoes.webp karena Next.js bantuin konversi di server saat build atau runtime. Ini yang bikin kecepatan website kamu bisa meningkat tanpa perlu kamu convert manual satu per satu. Kesimpulannya: pakai <Image /> itu kayak punya asisten pribadi yang ngurusin performa gambar buat kamu, tinggal pakai dan santai 😎 Gambar Lokal Lebih Disukai Kalau Disimpan di Folder public/ Next.js punya cara tersendiri dalam menangani gambar. Secara default, dia lebih suka gambar-gambar yang kamu simpan di folder public/. Kenapa? Karena gambar yang disimpan di folder public/ itu bisa langsung diakses sebagai URL statis, tanpa perlu di-import atau dibundle ke dalam JavaScript. Contohnya gini, kamu punya gambar hero.jpg yang kamu simpan di: /public/assets/images/hero.jpg Nah, kamu tinggal panggil gambar itu dengan path /assets/images/hero.jpg di komponen <Image />. Contoh penggunaannya: import Image from 'next/image' export default function LandingHero() { return ( <div className="w-full h-[500px] relative"> <Image src="/assets/images/hero.jpg" alt="Gambar Hero Section" fill style={{ objectFit: 'cover' }} /> <div className="absolute bottom-10 left-10 text-white"> <h1 className="text-4xl font-bold">Bangun Bisnis Online dengan Website</h1> </div> </div> ) } Kamu gak perlu import gambar tersebut seperti file JS atau asset lainnya, cukup tulis path-nya dari folder public/. Oh ya, yang perlu diingat: path-nya gak boleh diawali dengan ./ atau ../, cukup langsung mulai dari root URL, misalnya /images/foto.jpg. Mau Pakai Gambar dari Luar? Bisa Banget, Tapi Harus Diatur Dulu Kalau kamu ambil gambar dari domain luar, misalnya dari CDN atau website lain (kayak https://images.unsplash.com/...), Next.js bakal blokir secara default. Ini demi alasan keamanan dan performa — supaya server gak sembarangan fetch gambar dari mana aja. Tapi tenang, kamu masih bisa pakai gambar eksternal asal kamu daftarin dulu domain-nya di file next.config.js. Contoh konfigurasinya: // next.config.js const nextConfig = { images: { remotePatterns: [ { protocol: 'https', hostname: 'images.unsplash.com', }, ], }, } module.exports = nextConfig Setelah itu, kamu bisa pakai gambar dari URL eksternal seperti ini: import Image from 'next/image' export default function ExternalImageExample() { return ( <div className="w-full max-w-[500px] mx-auto p-4"> <Image src="<https://images.unsplash.com/photo-1603791440384-56cd371ee9a7>" alt="Ilustrasi Startup" width={500} height={300} className="rounded-lg" /> <h3 className="mt-4 font-semibold text-lg">Inspirasi Kantor Startup</h3> </div> ) } Tanpa setting remotePatterns tadi, kode di atas bakal error pas build atau runtime. Jadi kalau kamu tahu bakal ambil gambar dari luar, pastikan domainnya udah dikonfigurasi dulu. Intinya, Next.js kasih kamu fleksibilitas — mau pakai gambar dari dalam public/ atau dari luar, semua bisa… asal kamu tahu cara mainnya 😄 Bikin Gambar Responsif? Bisa Banget Pakai sizes dan Tailwind CSS Salah satu fitur canggih di Next.js <Image /> adalah responsive image — yaitu gambar yang menyesuaikan ukurannya tergantung ukuran layar pengguna. Tapi… ini bukan cuma soal width: 100%. Next.js juga bantuin kita nge-load gambar yang ukurannya paling efisien buat ukuran layar tersebut. Supaya fitur ini bekerja maksimal, kamu bisa kombinasikan properti sizes di Next.js dengan Tailwind CSS. sizes itu kayak “petunjuk” ke browser, bilang: “kalau layarnya segini, ambil gambar ukuran sekian ya.” Contoh penggunaannya: import Image from 'next/image' export default function ResponsiveCard() { return ( <div className="w-full md:w-1/2 lg:w-1/3 p-4"> <Image src="/assets/images/responsive.jpg" alt="Gambar Responsif" width={800} height={600} sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw" className="rounded-xl w-full h-auto" /> <h3 className="text-lg font-bold mt-3">Desain Fleksibel untuk Semua Layar</h3> </div> ) } Dengan kode ini, saat layarnya kecil (mobile), gambar akan gunakan 100% lebar viewport, tapi kalau makin lebar, dia akan turun jadi 50% atau 33% tergantung ukuran layar. Browser akan pilih gambar ukuran terbaik, jadi gak boros bandwidth dan tetap tajam tampilannya. Pakai layout="fill" atau fill Kalau Kamu Mau Gambar Penuh dan Bebas Atur Pakai CSS Kadang kamu pengen gambar jadi background penuh dari sebuah elemen — contohnya kayak header, banner, atau hero section yang besar. Dalam kasus seperti ini, kamu bisa pakai properti fill (versi modern dari layout="fill" di Next.js versi lama). Tapi inget ya, harus dibungkus dengan elemen yang punya posisi relatif dan ukuran yang jelas. Tujuannya? Supaya Next.js tahu seberapa besar ruang yang harus diisi gambarnya. Contoh penggunaan: import Image from 'next/image' export default function FullWidthBanner() { return ( <div className="relative w-full h-[500px]"> <Image src="/assets/images/full-banner.jpg" alt="Banner Penuh" fill style={{ objectFit: 'cover' }} priority /> <div className="absolute bottom-10 left-10 text-white"> <h1 className="text-4xl font-bold">Selamat Datang di Website Kami</h1> <p className="mt-2 text-lg">Solusi modern untuk bisnis digital kamu</p> </div> </div> ) } Di atas, div wrapper punya className="relative w-full h-[500px]", dan itu penting banget supaya <Image fill /> bisa menyesuaikan 100% lebar dan tinggi elemen tersebut. Ditambah dengan objectFit: 'cover', hasilnya gambar akan memenuhi seluruh ruang dengan crop otomatis kalau perlu, mirip banget kayak background-image: cover. Jadi, kalau kamu butuh kontrol penuh pakai Tailwind atau CSS untuk bikin hero section yang estetik dan powerful, opsi fill ini wajib banget kamu kuasai 💪 Bantu SEO an Percepat LCP (Largest Contentful Paint) Salah satu alasan kenapa komponen <Image /> dari Next.js itu powerful banget adalah karena dia gak cuma bantu tampilan website jadi kece, tapi juga berdampak langsung ke performa — terutama dalam skor SEO dan Core Web Vitals. Salah satu metrik penting di sana adalah LCP (Largest Contentful Paint), yaitu waktu yang dibutuhkan sampai konten terbesar (biasanya gambar hero atau judul utama) muncul di layar. Kalau kamu pakai gambar biasa yang belum dioptimasi, bisa bikin loading lama. Tapi kalau pakai <Image />, gambar bakal: Di-lazy load kalau bukan bagian utamaDi-preload kalau jadi prioritasDi-resize ke ukuran paling efisien Semua itu bantu browser nampilin konten utama lebih cepat, yang akhirnya ningkatin skor SEO dan pengalaman pengguna. Contoh implementasi yang bagus buat LCP: import Image from 'next/image' export default function HeroSEO() { return ( <section className="relative w-full h-[600px]"> <Image src="/assets/images/lcp-hero.jpg" alt="Gambar Utama LCP" fill priority style={{ objectFit: 'cover' }} /> <div className="absolute bottom-10 left-10 text-white"> <h1 className="text-5xl font-bold">Bangun Masa Depan Digital Kamu</h1> <p className="mt-3 text-xl">Website cepat = peluang lebih besar ✨</p> </div> </section> ) } Dengan properti priority, gambar ini akan dimuat lebih awal, karena kita kasih tahu ke Next.js bahwa ini konten penting di halaman. Hasilnya? Waktu LCP jadi jauh lebih cepat, dan Google pun akan lebih senang saat ngecek performa websitemu lewat Lighthouse. Masih Bisa Lewatin Optimasi Kalau Emang Perlu Walaupun optimasi gambar itu sangat berguna, kadang ada kasus di mana kamu gak pengen Next.js optimize gambar yang kamu pakai. Misalnya: Kamu udah punya gambar yang sangat teroptimasi sendiri (WebP atau SVG)Kamu butuh kontrol penuh atas cara gambar di-loadKamu pengen pakai <img> biasa tanpa sistem dynamic image loader dari Next.js Caranya? Kamu tinggal set prop unoptimized di komponen <Image />. Ini akan kasih tahu Next.js: “udah, gak usah diapa-apain ya gambar ini.” Contoh penggunaannya: import Image from 'next/image' export default function CustomImageExample() { return ( <div className="w-full p-6"> <Image src="/assets/images/custom.svg" alt="Custom Gambar" width={300} height={300} unoptimized className="mx-auto" /> <p className="text-center mt-4 text-gray-600">Gambar ini tidak dioptimasi otomatis</p> </div> ) } Perlu dicatat, saat kamu pakai unoptimized, artinya kamu bertanggung jawab sendiri terhadap performa gambar tersebut. Ini bukan opsi default, dan hanya digunakan kalau kamu tahu betul apa yang kamu lakukan. Tapi enaknya, Next.js tetap fleksibel: kalau kamu butuh performa — dia bantuin. Kalau kamu butuh kontrol penuh — dia izinkan. Kombinasi yang mantap buat developer modern 💼 Penutup: Kamu Sudah Kuasai 10 Hal Penting Tentang Gambar di Next.js Kita udah belajar bareng 10 poin penting tentang penggunaan gambar di Next.js — mulai dari kenapa <Image /> lebih baik dari <img>, gimana caranya bikin gambar lebih responsif, cara kerja lazy loading otomatis, optimasi format seperti WebP, hingga konfigurasi untuk gambar eksternal. Bahkan, kita juga bahas bagaimana optimasi ini bisa bantu skor SEO dan performa LCP-mu jadi lebih baik. Intinya, <Image /> bukan cuma soal estetika. Dia adalah alat penting buat bikin website kamu lebih cepat, lebih ramah SEO, dan lebih nyaman diakses dari semua device. Tapi ini baru permulaan. Kalau kamu pengen next level dalam belajar Next.js — bukan cuma tahu dasar-dasarnya, tapi juga bisa bikin project yang siap masuk portofolio kerja remote — kamu bisa belajar langsung dari mentor expert di BuildWithAngga. Dengan belajar di BuildWithAngga, kamu bisa dapat banyak benefit seperti: ✅ Akses kelas selamanya ✅ Materi langsung dari praktisi industri ✅ Forum diskusi dan feedback bareng mentor ✅ Project real-world yang bisa jadi portofolio ✅ Peluang persiapan kerja remote, freelance, atau startup Jadi tunggu apa lagi? Yuk lanjutkan belajar bareng mentor di BuildWithAngga, karena masa depan digital dimulai dari langkah kecil hari ini 🚀

Kelas 10 Hal Perlu Dipelajari Pemula Framework NextJS 15 di BuildWithAngga

10 Hal Perlu Dipelajari Pemula Framework NextJS 15

Zaman sekarang, punya bisnis online tuh gak cukup cuma punya produk bagus dan harga bersaing. Serius deh. Karena di era digital kayak sekarang, cara orang menilai bisnismu itu udah berubah. Orang bisa langsung ilfeel cuma karena websitemu lemot, tampilannya jadul, atau malah gak bisa dibuka di HP. Kita hidup di masa di mana semua serba instan dan cepat. Customer itu nggak mau nunggu, gak mau ribet. Mereka pengen cari produk, klik, terus checkout tanpa banyak drama. Dan buat bisa nyampe ke titik itu, artinya kamu — sebagai pemilik bisnis atau developer yang bantu bangun bisnis orang lain — perlu ngerti pentingnya pengalaman pengguna (user experience) dan teknologi yang mendukungnya. Website adalah pintu utama buat pelanggan baru. Kalau tampilannya gak meyakinkan atau loading-nya lambat, mereka bisa langsung keluar sebelum sempat lihat produkmu. Parahnya lagi, bisa jadi mereka langsung pindah ke kompetitor yang tampilannya lebih segar dan lebih responsif. Makanya, update teknologi itu wajib. Bukan karena ikut-ikutan tren, tapi karena itulah cara terbaik buat menjangkau lebih banyak orang dan ningkatin kepercayaan dari calon pembeli. Kenapa Next.js Jadi Pilihan Terbaik Buat Bikin Website Modern Di antara banyaknya framework yang bisa dipakai buat bikin website, Next.js sekarang bisa dibilang jadi salah satu primadona. Bukan cuma di kalangan developer expert, tapi juga buat pemula yang baru belajar bikin website profesional. Kenapa? Karena Next.js ini ngebuka banyak pintu kemudahan tapi tetap powerful. Pertama, performanya luar biasa. Dengan fitur-fitur seperti server-side rendering (SSR), static site generation (SSG), dan hybrid rendering, Next.js bisa bantu website kamu tampil lebih cepat. Buat customer, ini artinya loading halaman gak pake muter-muter lama. Dan buat SEO? Ini surga. Karena Google lebih suka website yang cepet dan bisa diakses dengan struktur yang jelas. Cocok banget buat kamu yang pengen websitenya nongol di halaman pertama hasil pencarian. Kedua, Next.js itu gak ribet. Serius. Struktur project-nya clean dan mudah diatur. Bahkan buat pemula, begitu mulai ngerti cara kerja routing-nya, semuanya jadi terasa natural. Ditambah lagi, dukungan komunitasnya gede banget. Kamu gak akan merasa sendirian saat belajar karena dokumentasinya lengkap dan banyak banget tutorial gratis di luar sana. Dan yang paling penting nih, Next.js itu cocok banget buat bikin full stack website. Artinya kamu bisa handle frontend dan backend sekaligus dalam satu project. Mau ngatur API sendiri? Bisa. Mau konek ke database? Bisa juga. Mau deploy ke Vercel? Tinggal klik. Gak ada lagi drama setup yang makan waktu berjam-jam cuma buat bisa mulai coding. Di Artikel Ini, Kita Bakal Kupas 10 Hal Penting Buat Kamu yang Baru Mulai Belajar Next.js Nah, setelah kita ngobrol soal pentingnya bisnis online punya website yang cepat dan responsif, serta kenapa Next.js itu layak banget dipelajari… sekarang kita masuk ke bagian yang gak kalah penting, yaitu apa aja sih yang perlu kamu pelajari sebagai pemula di dunia Next.js? Jujur aja, banyak banget orang yang baru mulai belajar Next.js langsung ngerasa overwhelmed. Mulai dari struktur folder yang beda dari React biasa, sampai fitur-fitur kayak server-side rendering dan API routes yang kedengarannya teknis banget. Tapi santai aja, karena sebenarnya kalau dipecah satu per satu, semuanya bisa dicerna dengan gampang kok. Yang penting adalah urutan belajarnya tepat dan gak buru-buru pengen jago instan. Di artikel ini, kita bakal bahas 10 hal penting yang wajib kamu pahami di awal-awal perjalanan kamu bareng Next.js. Semua poin ini disusun berdasarkan pengalaman pribadi dan juga kebiasaan belajar dari para pemula yang pernah gue mentoring—jadi bukan teori doang, tapi udah terbukti bermanfaat buat banyak orang. Tujuannya bukan supaya kamu langsung expert dalam semalam ya, tapi biar kamu punya fondasi yang kuat. Karena Next.js itu bisa dipakai untuk banyak jenis website—mulai dari company profile sederhana, toko online, sampai platform edukasi atau sosial media skala besar. Makanya, punya pemahaman dasar yang rapi itu penting banget supaya ke depannya kamu gak gampang bingung atau frustrasi di tengah jalan. Pahami Struktur Folder Next.js Lewat Analogi dan Contoh Biar Gak Nyasar Ketika kamu mulai bikin project pakai Next.js (terutama versi terbaru yang pakai App Router), kamu akan langsung nemuin struktur folder yang keliatannya cukup rapi. Tapi jujur aja, kalau kamu belum pernah ngulik Next.js sebelumnya, struktur ini bisa bikin mikir, “Lho, ini apaan aja sih?” Sekarang bayangin kamu lagi pindahan ke rumah baru. Rumah ini udah lengkap banget—ada ruang tamu, dapur, kamar tidur, sampai ruang kerja. Tapi semuanya ditata rapi. Nah, tiap ruangan itu fungsinya jelas, dan kamu gak perlu mikir dua kali buat nyari barang. Itulah perasaan ideal saat kamu udah paham struktur folder di Next.js. Biar gak cuma bayangan, coba kita lihat contoh struktur folder sederhana berikut: my-nextjs-project/ │ ├── app/ │ ├── page.tsx <- Ini halaman utama, tampil di route "/" │ ├── about/ │ │ ├── page.tsx <- Ini halaman tentang, tampil di route "/about" │ │ └── layout.tsx <- Layout khusus buat halaman "/about" │ ├── dashboard/ │ │ ├── page.tsx <- Halaman dashboard, route "/dashboard" │ │ └── layout.tsx <- Layout dashboard (biasanya sidebar) │ └── layout.tsx <- Layout global (header/footer yang muncul di semua halaman) │ ├── public/ │ ├── images/ │ │ └── logo.png <- Gambar yang bisa langsung diakses dari browser │ └── favicon.ico <- Icon website │ ├── styles/ │ └── globals.css <- CSS global kamu, misalnya reset style atau tema dasar │ ├── next.config.js <- Konfigurasi Next.js ├── tsconfig.json <- Setting TypeScript (kalau pakai TS) └── package.json <- Info dependencies & script project kamu Sekarang coba lihat pelan-pelan. Folder app/ ini bisa kamu anggap sebagai jantung utama project Next.js kamu. Semua halaman, layout, dan komponen routing berbasis file bakal ada di sini. Misalnya kamu bikin folder about, otomatis itu jadi halaman /about tanpa perlu konfigurasi routing manual. File page.tsx adalah isi utama halaman tersebut, sedangkan layout.tsx itu seperti “kerangka tetap” yang membungkus kontennya—misalnya kamu pengen ada sidebar khusus di dashboard aja, atau halaman tertentu punya layout yang beda dari global. Terus, folder public/ ini seperti garasi atau laci rumah tempat kamu nyimpen barang-barang yang bisa diakses langsung. Mau taruh gambar, icon, atau file lainnya? Simpen aja di sini, terus panggil di HTML atau komponen tanpa harus diimport secara eksplisit. Struktur ini kelihatannya banyak, tapi justru bikin project kamu lebih tertata dan gampang dikembangin jangka panjang. Gak ada lagi tuh file App.jsx isinya komponen campur aduk. Dengan Next.js, kamu belajar untuk lebih rapih dan disiplin dari awal—dan ini penting banget kalau suatu hari kamu kerja bareng tim. Intinya, struktur folder di Next.js itu bukan untuk bikin pusing, tapi justru ngebantu kamu kerja lebih enak. Begitu kamu udah terbiasa, semua bagian ini bakal terasa logis dan bikin proses ngoding jadi lebih nikmat. Gimana Sih Cara Kerja Routing di Next.js? Yuk Pahami Lewat Analogi Jalan dan Papan Petunjuk Routing itu sebenernya konsep yang udah lama banget ada di dunia web development. Tapi di Next.js, routing jadi terasa lebih alami karena semuanya diatur langsung lewat struktur folder. Nah, biar kamu gampang ngebayanginnya, kita coba pake analogi jalanan dan papan petunjuk, ya. Bayangin kamu lagi jalan-jalan di sebuah kota kecil. Di tiap sudut kota, ada papan penunjuk jalan yang ngarahin kamu ke lokasi tertentu. Misalnya, kalau kamu liat papan bertuliskan “/about”, kamu tahu itu jalan menuju halaman informasi. Atau kalau kamu belok ke “/contact”, itu jalan ke tempat buat ngirim pesan. Nah, di Next.js, kamu tinggal bikin folder atau file sesuai nama jalannya, dan secara otomatis sistemnya akan ngerti, “Oh, ini route ke halaman ini.” Jadi kamu gak perlu atur routing manual kayak di React biasa yang harus pakai react-router-dom dan bikin config panjang-panjang. Contohnya gini: Misal kamu punya struktur folder kayak gini di dalam app/: app/ ├── page.tsx ├── about/ │ └── page.tsx ├── contact/ │ └── page.tsx Artinya: app/page.tsx itu otomatis jadi route /app/about/page.tsx itu route /aboutapp/contact/page.tsx itu route /contact Setiap file page.tsx itu adalah papan petunjuk yang ngarahin pengunjung ke konten halaman tersebut. Contoh isi kodenya di masing-masing halaman bisa kayak gini: app/page.tsx export default function HomePage() { return ( <main> <h1>Selamat datang di website kita!</h1> <p>Ini adalah halaman utama.</p> </main> ); } app/about/page.tsx export default function AboutPage() { return ( <main> <h1>Tentang Kami</h1> <p>Website ini dibangun menggunakan Next.js.</p> </main> ); } app/contact/page.tsx export default function ContactPage() { return ( <main> <h1>Hubungi Kami</h1> <p>Kirim pesan lewat email ke [email protected].</p> </main> ); } Kamu gak perlu ngapalin sintaks aneh atau setup routing tambahan. Cukup bikin folder dan file, dan Next.js akan otomatis ngerti path-nya. Analoginya kayak kamu bikin bangunan-bangunan baru di kota kecil itu. Selama kamu kasih nama jalan dan papan petunjuk yang jelas, semua orang bisa dengan mudah navigasi ke tempat yang mereka tuju. Dan kalau nanti kamu pengen bikin dynamic route (misalnya halaman detail produk atau artikel), tinggal tambahin tanda kurung di nama folder atau file—tapi itu bakal kita bahas lebih dalam di bagian selanjutnya. Intinya, Next.js routing itu super simpel dan sangat powerful, tinggal kamu biasain aja mainan sama struktur foldernya. Jadi, gak ada alasan buat bingung-bingung lagi soal routing. Mulai dari sini aja, bikin beberapa halaman dan coba akses lewat browser. Rasain sendiri gimana Next.js ngatur jalannya buat kamu tanpa ribet. Client vs Server Components di Next.js — Bedanya Apa? Yuk Biar Gak Gagal Paham! Kalau kamu baru belajar Next.js, mungkin kamu bakal bingung waktu lihat ada komponen yang berjalan di "client" dan ada yang berjalan di "server". Di Next.js versi App Router, ini penting banget buat dipahami karena bakal nentuin di mana dan bagaimana komponen kamu dijalankan. Biar gak pusing, yuk kita pakai analogi yang gampang dulu. Bayangin kamu lagi nongkrong di restoran all-you-can-eat. Ada dua jenis makanan yang bisa kamu nikmati: Pertama, makanan yang langsung dimasakin dan disajikan dari dapur oleh chef. Kamu gak perlu ikut masak, tinggal duduk, dan makanan datang ke meja kamu. Proses masaknya gak kelihatan, tapi hasil akhirnya langsung bisa kamu nikmati. Nah, itu ibaratnya Server Component. Semua prosesnya terjadi di server, dan hasilnya langsung dikirim ke browser. Kedua, ada makanan yang kamu masak sendiri di meja, kayak Korean BBQ. Bahan-bahannya udah disiapin, tapi kamu yang ngatur masaknya. Ini ibarat Client Component—prosesnya terjadi di sisi browser, kamu bisa interaksi langsung sama elemennya: klik tombol, isi form, buka modal, dan sebagainya. Next.js kasih kamu fleksibilitas buat milih, komponen mana yang pengen dijalanin di server (biar ringan dan SEO-friendly), dan mana yang perlu dijalanin di client (karena butuh interaksi langsung). Oke, sekarang kita lihat contoh coding-nya biar lebih jelas. Contoh Server Component (default) Semua file .tsx di folder app/ itu default-nya adalah Server Component. Kamu gak perlu nulis apa-apa untuk deklarasinya. app/about/page.tsx export default function AboutPage() { const currentTime = new Date().toLocaleString(); return ( <main> <h1>Halaman Tentang Kami</h1> <p>Waktu saat halaman dirender dari server: {currentTime}</p> </main> ); } Komponen ini bakal dirender di server. Artinya, waktu currentTime bakal diset di server dan hasilnya langsung dikirim ke browser sebagai HTML statis. Bagus banget buat SEO dan kecepatan render awal. Contoh Client Component (butuh interaksi) Kalau kamu butuh fitur yang interaktif—misalnya tombol yang bisa diklik—kamu harus declare komponen itu sebagai client. app/counter/page.tsx 'use client' import { useState } from 'react'; export default function CounterPage() { const [count, setCount] = useState(0); return ( <main> <h1>Hitung Klik</h1> <p>Jumlah klik: {count}</p> <button onClick={() => setCount(count + 1)}>Tambah</button> </main> ); } Perhatikan bagian 'use client' di paling atas. Itu wajib ditulis supaya Next.js tahu bahwa komponen ini perlu dijalankan di browser karena pakai useState, useEffect, atau interaksi DOM lainnya. Kapan harus pakai yang mana? Kalau kamu cuma butuh nampilin data, format tanggal, atau ambil data dari API dan render-nya gak butuh interaksi dari user, pakai Server Component. Lebih cepat, lebih ringan, dan bagus buat SEO. Tapi kalau kamu butuh sesuatu yang interaktif—misalnya klik tombol, buka modal, isi form—pakai Client Component. Dengan paham perbedaan ini, kamu bisa bikin aplikasi yang performanya lebih mantap dan loading-nya ngebut, tanpa ngorbanin interaksi yang dibutuhin user. Jadi inget ya, Server Component = masakan siap saji dari dapur, Client Component = masak sendiri di meja. Dua-duanya enak, tinggal sesuaikan aja dengan kebutuhan aplikasi kamu. Layouts dan Templates di Next.js — Biar Halamanmu Gak Capek Ngulang-ngulang Ketika kamu bikin website, kamu pasti bakal punya banyak halaman yang punya bagian yang mirip-mirip. Misalnya, semua halaman punya header yang sama, footer yang sama, atau sidebar yang gak berubah. Nah, daripada kamu ngulang-ngulang bagian itu di tiap file, Next.js kasih fitur keren banget yang namanya layout dan template. Biar gampang bayanginnya, kita coba pakai analogi bangunan. Bayangin kamu lagi bangun sebuah apartemen. Semua unit apartemennya punya kerangka dasar yang sama—ada kamar mandi, dapur, ruang tamu, dan kamar tidur. Tapi masing-masing unit boleh punya isi yang berbeda, kayak furnitur atau warna tembok. Nah, layout itu kayak kerangka bangunan apartemen. Semua unit pakai kerangka yang sama biar efisien dan seragam. Sementara itu, template itu kayak dekorasi awal dari ruangan tertentu, biasanya lebih jarang berubah. Misalnya, ruang meeting yang selalu punya layout dan tema warna yang konsisten—jadi beda dengan layout umum. Dengan layout dan template di Next.js, kamu bisa atur biar tiap halaman punya kerangka tampilan yang konsisten, tapi tetap bisa beda isi sesuai kebutuhan. Sekarang kita lihat contoh koding biar makin jelas ya. Contoh Layout Utama (app/layout.tsx) Layout ini akan membungkus semua halaman yang ada di project kamu. // app/layout.tsx import './globals.css'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="id"> <body> <header> <h1>My Website</h1> <nav> <a href="/">Home</a> | <a href="/about">About</a> </nav> </header> <main>{children}</main> <footer> <p>© 2025 My Company</p> </footer> </body> </html> ); } Semua halaman di dalam folder app/ secara otomatis akan dibungkus oleh layout ini. Jadi kamu gak perlu lagi nulis ulang header, nav, atau footer di tiap halaman. Contoh Halaman (app/about/page.tsx) Halaman ini akan tetap tampil di dalam layout yang sudah kamu buat. export default function AboutPage() { return ( <section> <h2>Tentang Kami</h2> <p>Kami membangun website ini pakai Next.js yang kece banget!</p> </section> ); } Ketika kamu buka halaman /about, tampilannya akan tetap ada header, footer, dan konten dari halaman ini. Contoh Layout Khusus (app/dashboard/layout.tsx) Misalnya kamu pengen halaman di /dashboard punya sidebar dan tampilan yang beda dari layout utama. // app/dashboard/layout.tsx export default function DashboardLayout({ children }: { children: React.ReactNode }) { return ( <div style={{ display: 'flex' }}> <aside style={{ width: '200px', background: '#f0f0f0' }}> <p><strong>Menu Dashboard</strong></p> <ul> <li><a href="/dashboard">Home</a></li> <li><a href="/dashboard/settings">Settings</a></li> </ul> </aside> <main style={{ flex: 1, padding: '20px' }}>{children}</main> </div> ); } Dan kamu bisa bikin halaman kayak app/dashboard/page.tsx yang akan dibungkus dengan layout khusus ini. export default function DashboardHome() { return ( <div> <h2>Welcome to the Dashboard</h2> <p>Ini adalah halaman utama dashboard.</p> </div> ); } Dengan sistem layout dan template ini, kamu bisa bikin website yang modular, rapih, dan gampang dikembangin. Gak perlu capek-capek ngulangin header, nav, atau sidebar di tiap file. Tinggal taruh di layout, dan semuanya udah ke-handle otomatis. Jadi ingat: layout = kerangka bangunan apartemen, template = dekorasi standar dari ruangan tertentu. Semua jadi efisien dan konsisten, dan kamu bisa fokus ngembangin fitur-fitur lainnya tanpa mikir ulang struktur halaman dari awal. Metadata & SEO di Next.js — Biar Website Kamu Gak Cuma Cakep, Tapi Juga Gampang Ditemuin Pernah gak kamu bikin website yang tampilannya keren banget, cepet juga, tapi kok sepi banget pengunjungnya? Nah, bisa jadi kamu lupa satu hal penting: metadata dan SEO. Sekarang kita pakai analogi biar lebih gampang paham ya. Bayangin kamu lagi bikin sebuah toko keren di tengah kota. Desainnya cakep, produknya lengkap, pelayanannya ramah. Tapi… kamu gak pasang papan nama, gak masuk Google Maps, bahkan gak ada info sama sekali di depan toko. Gimana orang mau nemu? Nah, metadata itu ibarat identitas toko kamu yang muncul di Google. SEO (Search Engine Optimization) adalah upaya biar toko kamu muncul di hasil pencarian teratas waktu orang cari sesuatu yang kamu jual. Jadi meskipun kamu udah bangun website paling kece sedunia, tanpa metadata yang bener dan SEO yang oke, website kamu bisa aja gak pernah keliatan orang. Untungnya, Next.js udah nyediain cara super gampang buat atur metadata tiap halaman. Kamu tinggal nambahin konfigurasi metadata di setiap page.tsx atau bahkan secara global di layout.tsx. Langsung aja kita lihat contohnya. Metadata Global (app/layout.tsx) Ini akan jadi metadata default untuk semua halaman yang gak punya metadata spesifik. // app/layout.tsx export const metadata = { title: 'My Awesome Website', description: 'Belajar Next.js biar jadi web developer keren!', }; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="id"> <body>{children}</body> </html> ); } Dengan ini, setiap halaman akan punya judul "My Awesome Website" dan deskripsi sesuai yang kamu tulis. Ini penting banget buat hasil pencarian Google dan juga waktu orang share link kamu ke media sosial. Metadata Khusus Halaman (app/about/page.tsx) Kalau kamu pengen halaman tertentu punya metadata yang beda, kamu bisa override langsung di file halaman itu. // app/about/page.tsx export const metadata = { title: 'Tentang Kami - My Awesome Website', description: 'Pelajari lebih lanjut tentang tim dan misi kami di halaman ini.', }; export default function AboutPage() { return ( <main> <h1>Tentang Kami</h1> <p>Kami percaya teknologi bisa bantu banyak orang berkembang.</p> </main> ); } Dengan begitu, halaman /about akan punya title dan description yang spesifik. Ini bikin mesin pencari kayak Google bisa lebih paham konten halaman kamu dan ngasih ranking yang lebih baik. Bonus: Metadata Tambahan (Open Graph, Twitter, dll) Kalau kamu pengen halaman kamu tampil keren waktu di-share ke Twitter atau WhatsApp, kamu juga bisa tambahin metadata sosial seperti ini: // app/page.tsx export const metadata = { title: 'Beranda - My Awesome Website', description: 'Ini halaman utama dari website Next.js kamu.', openGraph: { title: 'Beranda - My Awesome Website', description: 'Gabung belajar bareng dan jadi developer masa depan.', images: [ { url: '/images/cover-home.jpg', width: 1200, height: 630, alt: 'Cover Home Page', }, ], }, twitter: { card: 'summary_large_image', title: 'Beranda - My Awesome Website', description: 'Gabung belajar bareng dan jadi developer masa depan.', images: ['/images/cover-home.jpg'], }, }; Jadi intinya, metadata itu bukan hiasan doang. Dia adalah wajah dan kartu nama digital halaman kamu di dunia luar. Mesin pencari, media sosial, dan browser semuanya ngandelin metadata buat nunjukin konten kamu ke dunia. Jangan sampai website kamu udah keren dan fungsional, tapi gak ada yang tahu karena gak dioptimasi dari sisi metadata dan SEO-nya. Di Next.js, semuanya udah disiapin tinggal kamu manfaatin. Pentingnya Optimasi Gambar di Next.js — Biar Website Gak Berat Kayak Bawa Koper Isi Batu Optimasi gambar itu hal yang sering diremehin sama pemula, padahal efeknya gede banget ke kecepatan website dan pengalaman pengguna. Nah, Next.js datang bawa solusi lewat fitur bawaan mereka: next/image. Tapi sebelum kita bahas teknisnya, kita pakai analogi dulu ya biar lebih kebayang. Bayangin kamu lagi liburan ke luar kota dan harus bawa koper. Kamu punya dua pilihan: bawa semua baju, sepatu, dan perlengkapan tanpa disortir—pokoknya semua masuk koper, berat banget. Atau, kamu pilah-pilah, bawa yang penting aja, gulung baju biar hemat tempat, dan pakai koper ringan. Jelas yang kedua lebih nyaman, kan? Nah, gambar di website juga gitu. Kalau kamu langsung taruh gambar ukuran besar (misalnya hasil export dari kamera atau Figma tanpa dikompres), browser bakal ‘nyeret koper berat’ setiap kali halaman dibuka. Ini bikin website jadi lambat, terutama di koneksi internet yang biasa-biasa aja. Next.js punya fitur khusus buat bantu kamu otomatis bawa ‘koper ringan’. Namanya next/image. Dia bantu resize, compress, dan pilih format gambar terbaik otomatis, tergantung device dan koneksi pengguna. Jadi kamu bisa tetap pakai gambar berkualitas tinggi, tanpa bikin loading page jadi lelet. Sekarang kita masuk ke contoh penggunaannya. Tanpa Optimasi (pakai tag img biasa): <img src="/images/banner.jpg" alt="Banner Website" width={1200} height={600} /> Kalau kamu pakai ini, browser akan langsung download gambar full-size tanpa optimasi apapun. Jadi walaupun user buka lewat HP kecil, tetap aja gambar 1200px itu bakal diload penuh. Boros banget. Dengan Optimasi (pakai next/image): import Image from 'next/image'; export default function HeroSection() { return ( <section> <h1>Selamat Datang di Website Kami</h1> <Image src="/images/banner.jpg" alt="Banner Website" width={1200} height={600} priority /> </section> ); } Saat kamu pakai komponen Image dari Next.js: Gambar akan otomatis dikompres dan disesuaikan dengan ukuran layar user.Gambar hanya diload saat muncul di viewport (lazy loading otomatis).Bisa pakai format gambar modern seperti WebP kalau browser mendukung.Kecepatan website meningkat tanpa kamu harus pakai tool optimasi gambar terpisah. Kamu juga bisa kasih style langsung ke gambarnya, dan bahkan atur layout atau fit-nya: <Image src="/images/profile.jpg" alt="Foto Profil" width={200} height={200} style={{ borderRadius: '100%' }} /> Jadi intinya, gambar itu penting banget buat branding dan desain, tapi kalau gak dioptimasi, dia bisa jadi beban paling besar buat website kamu. Dengan next/image, kamu kayak punya asisten pribadi yang bantu packing gambar-gambar kamu biar tetap kece, tapi ringan buat dibawa ke mana-mana. Mulai sekarang, coba deh ubah semua <img> biasa kamu jadi <Image> dari Next.js. Rasain bedanya waktu loading halaman. Website jadi lebih cepat, pengunjung pun lebih betah. Ngomongin Data di Next.js: API Routes vs Data Fetching — Simpelnya Kayak Masak Sendiri atau Delivery Waktu kamu bikin website pakai Next.js, kamu pasti butuh ngambil data dari suatu tempat. Bisa dari database, dari API lain, atau dari file lokal. Nah, gimana cara ngelola dan nampilin data ini tergantung kamu pakai sistem routing yang mana—Pages Router atau App Router. Tapi sebelum nyemplung ke teknis, yuk kita pakai analogi yang gampang dulu. Bayangin kamu lagi lapar. Kamu punya dua pilihan buat dapet makanan: Pertama, kamu masak sendiri di dapur rumah. Kamu yang kontrol semua bahan, waktu masak, dan rasa. Ini mirip kayak bikin API Routes di Pages Router—kamu bikin sendiri endpoint-nya, kamu atur prosesnya, dan kamu bisa kasih data sesuai kebutuhan.Kedua, kamu order makanan dari luar, tinggal buka aplikasi, pilih menu, dan tunggu makanan diantar. Ini mirip banget sama fitur Data Fetching di App Router. Kamu tinggal bilang “saya butuh data ini”, dan Next.js bantu ambilin dan siapin langsung sebelum halaman ditampilkan. Kedua metode ini sama-sama valid, tinggal tergantung kebutuhan kamu dan sistem routing yang kamu pakai. Kalau pakai Pages Router: kamu bikin API sendiri pakai API Routes Contoh bikin endpoint /api/products yang return data produk: // pages/api/products.ts import type { NextApiRequest, NextApiResponse } from 'next'; export default function handler(req: NextApiRequest, res: NextApiResponse) { const products = [ { id: 1, name: 'T-Shirt', price: 150000 }, { id: 2, name: 'Jacket', price: 300000 }, ]; res.status(200).json(products); } Endpoint ini bisa kamu akses lewat fetch: // pages/products.tsx import { useEffect, useState } from 'react'; export default function ProductPage() { const [products, setProducts] = useState([]); useEffect(() => { fetch('/api/products') .then((res) => res.json()) .then((data) => setProducts(data)); }, []); return ( <main> <h1>Daftar Produk</h1> {products.map((item) => ( <div key={item.id}> <p>{item.name} - Rp {item.price}</p> </div> ))} </main> ); } Kalau pakai App Router: kamu langsung fetch data di server pakai async function Misalnya kamu mau ambil data produk di halaman /products: // app/products/page.tsx async function getProducts() { const res = await fetch('<https://fakestoreapi.com/products>', { next: { revalidate: 60 }, // ini ISR biar bisa cache dan update tiap 60 detik }); return res.json(); } export default async function ProductPage() { const products = await getProducts(); return ( <main> <h1>Daftar Produk</h1> {products.map((item: any) => ( <div key={item.id}> <p>{item.title}</p> <p>Rp {item.price}</p> </div> ))} </main> ); } Di sini, semua data diambil sebelum halaman ditampilkan ke user, karena function page.tsx bersifat async dan bisa langsung fetch data saat render di server. Jadi intinya, kamu bisa pilih: Kalau kamu pakai Pages Router, kamu bisa bikin dapur sendiri (API Routes) dan fetch data manual dari client side.Kalau kamu pakai App Router, kamu tinggal ambil data langsung di server (Data Fetching di page.tsx) kayak order makanan, udah siap saji. Dua-duanya fleksibel dan bisa disesuaikan sesuai skenario. Yang penting kamu ngerti perbedaan mindset-nya: Pages Router lebih seperti kamu handle semuanya manual, sedangkan App Router kasih kamu tools biar proses ambil data terasa lebih “server-aware” dan efisien. Static vs Dynamic Rendering di Next.js — Ibarat Masak Nasi Bungkus vs Nasi Goreng Dadakan Ketika kamu bangun website dengan Next.js, kamu akan sering ketemu dua istilah penting ini: Static Rendering dan Dynamic Rendering. Kalau gak ngerti bedanya, bisa-bisa kamu bikin halaman yang lambat padahal harusnya bisa ngebut. Tapi jangan khawatir—kita bahas dengan cara santai biar gak bikin pusing. Bayangin kamu lagi jualan makanan. Static Rendering itu kayak kamu udah nyiapin nasi bungkus dari pagi. Semua lauk, nasi, sambel udah dikemas rapi di kotak, tinggal kamu kasih ke pelanggan yang datang. Cepat banget, gak ada proses masak ulang. Jadi cocok buat menu yang sama persis buat semua orang, dan gak perlu perubahan tergantung siapa yang beli. Nah, di Next.js, ini mirip banget sama Static Site Generation (SSG)—halaman udah diproses dan disimpan sebagai HTML siap pakai. Sebaliknya, Dynamic Rendering itu kayak kamu masak nasi goreng dadakan. Pas pelanggan datang dan bilang "saya mau nasi goreng level 3 pedesnya", barulah kamu masak di tempat. Gak bisa disiapin dari awal, karena harus disesuaikan sama permintaan masing-masing. Nah, ini mirip dengan Server Side Rendering (SSR) di Next.js—halaman baru dirender di server saat ada request masuk, dan bisa menyesuaikan isinya sesuai data user, query, atau kondisi tertentu. Contoh Static Rendering (dengan data tetap): Misalnya kamu mau bikin halaman list artikel yang jarang berubah. // app/blog/page.tsx async function getArticles() { const res = await fetch('<https://example.com/api/articles>', { next: { revalidate: 3600 }, // revalidate tiap 1 jam }); return res.json(); } export default async function BlogPage() { const articles = await getArticles(); return ( <main> <h1>Artikel Terbaru</h1> {articles.map((item: any) => ( <article key={item.id}> <h2>{item.title}</h2> <p>{item.summary}</p> </article> ))} </main> ); } Halaman ini akan dirender sekali di server, lalu disimpan sebagai HTML statis. Selama satu jam ke depan, semua pengunjung akan dapat versi yang sama, dan baru akan diperbarui setelah masa revalidasi habis. Contoh Dynamic Rendering (buat data real-time atau personalized): Misalnya kamu bikin halaman profil user yang harus menampilkan nama berdasarkan login mereka. // app/profile/page.tsx import { cookies } from 'next/headers'; export default async function ProfilePage() { const cookieStore = cookies(); const userId = cookieStore.get('user_id')?.value; const res = await fetch(`https://example.com/api/users/${userId}`, { cache: 'no-store', // jangan cache, selalu ambil fresh }); const user = await res.json(); return ( <main> <h1>Halo, {user.name}!</h1> <p>Selamat datang kembali ke dashboard kamu.</p> </main> ); } Karena kontennya tergantung siapa yang login, halaman ini dirender secara dinamis di server tiap kali ada request baru. Cocok buat data yang berubah terus atau yang sifatnya personal. Jadi, kesimpulannya: Static Rendering = nasi bungkus siap santap, cepat dan efisien, cocok untuk konten tetap.Dynamic Rendering = masak dadakan di tempat, fleksibel dan personal, cocok buat konten yang berubah-ubah atau tergantung user. Pilih yang paling sesuai sama kebutuhan halaman kamu. Jangan semua dipaksain dinamis, nanti performa jeblok. Tapi jangan juga semua diset statis, nanti data pentingnya malah gak update. Dengan Next.js, kamu punya kuasa buat atur strategi render sesuai kebutuhan — dan itu salah satu kekuatan terbesarnya. Ngerti Environment Variables di Next.js — Kayak Punya Catatan Rahasia di Saku Celana Kalau kamu udah mulai serius ngoding project Next.js, pasti bakal nemu istilah Environment Variables atau sering disebut env. Biar gak bingung, kita bahas ini dulu dengan analogi santai. Bayangin kamu lagi kerja di sebuah restoran. Nah, ada resep khusus yang cuma boleh diketahui oleh koki. Gak boleh ditulis di papan menu, gak boleh dikasih ke tamu. Tapi resep itu penting banget biar rasa makanannya konsisten, dan restoran tetap bisa jalan. Resep rahasia itu disimpan di saku celana koki, jadi cuma dia yang bisa lihat dan pakai pas masak. Nah, environment variables itu kayak catatan rahasia di saku developer. Informasi yang penting banget, tapi gak boleh ditaruh langsung di dalam kode. Misalnya: API key, database password, base URL API, secret token, dan lain-lain. Kenapa harus disembunyiin? Karena kalau kamu simpen langsung di file kode dan ternyata project-nya ke-push ke GitHub atau di-deploy ke server publik, orang lain bisa aja lihat informasi sensitif itu. Bahaya banget, bro. Makanya Next.js punya cara khusus buat nyimpen dan akses environment variable lewat file .env.local. Langkah pertama: bikin file .env.local di root project NEXT_PUBLIC_API_URL=https://api.example.com SECRET_TOKEN_SERVER=super-secret-token-123 Ada dua hal yang penting di sini: Variabel yang diawali dengan NEXT_PUBLIC_ akan bisa diakses dari browser/client.Variabel tanpa NEXT_PUBLIC_ hanya bisa diakses di server, jadi aman dari paparan publik. Contoh penggunaan di client component: 'use client' export default function ShowApiUrl() { return ( <div> <p>Base URL API kamu: {process.env.NEXT_PUBLIC_API_URL}</p> </div> ); } Hasilnya nanti akan tampil: Base URL API kamu: <https://api.example.com> Karena variabel ini punya awalan NEXT_PUBLIC_, maka bisa digunakan langsung di komponen React yang berjalan di browser. Contoh penggunaan di server (tanpa diekspose): // app/api/hello/route.ts export async function GET() { const token = process.env.SECRET_TOKEN_SERVER; return Response.json({ message: 'Token berhasil digunakan di server', tokenUsed: token, }); } Di sini, SECRET_TOKEN_SERVER tidak akan pernah muncul di client, tapi bisa kamu pakai untuk kirim request ke API yang butuh authentication, selama itu dilakukan di server. Hal penting yang perlu kamu tahu juga: File .env.local tidak akan pernah ikut ke-push ke GitHub kalau kamu pakai .gitignore dengan benar.Kamu bisa punya beberapa file env berbeda, seperti .env.production atau .env.development, tergantung environment project kamu dijalankan. Jadi kesimpulannya: Environment variables itu catatan rahasia penting yang disimpan di luar kode, tapi bisa kamu pakai kapan aja pas dibutuhin. Dengan ngatur ini dengan benar, project kamu jadi lebih aman, fleksibel, dan gampang dipindah-pindahin ke environment lain tanpa harus ubah banyak file. Deployment ke Vercel — Ibarat Buka Toko di Mall yang Udah Disediain Semua Fasilitasnya Setelah kamu selesai bikin website pakai Next.js, pertanyaan selanjutnya pasti: “Gimana caranya biar website-nya bisa diakses banyak orang dari mana aja?” Nah, inilah saatnya kamu masuk ke tahap deployment. Biar gampang dipahami, kita pakai analogi yang relate banget. Bayangin kamu baru selesai desain interior toko impian kamu. Udah rapi, produk siap, banner udah digantung. Tapi toko kamu masih di dalam garasi rumah—gak ada yang bisa lihat, gak ada yang lewat, gak ada pelanggan. Nah, deployment itu ibarat kamu mindahin toko dari garasi ke dalam mall besar. Di mall, ada pengunjung, sistem keamanan, listrik stabil, dan bahkan staff kebersihan. Vercel itu mall-nya. Kenapa Vercel jadi pilihan favorit buat deploy Next.js? Karena Vercel tuh dibuat langsung sama tim yang bikin Next.js, jadi udah sangat cocok dan seamless banget. Semua proses build dan hosting-nya udah diaturin. Kamu tinggal dorong project kamu dan... boom, website kamu langsung bisa diakses lewat internet dengan domain yang cantik. Langkah deployment ke Vercel: Push project kamu ke GitHub (atau GitLab, atau Bitbucket).Buka https://vercel.com dan login (bisa pakai akun GitHub).Klik tombol “New Project”, terus pilih repo project Next.js kamu.Tinggal klik deploy. Dalam beberapa detik, Vercel akan otomatis:install dependencybuild projecthost semua filedan kasih kamu URL online Contoh hasil build otomatis di Vercel (gak perlu ditulis sendiri): Vercel akan membaca next.config.js, package.json, dan struktur folder kamu, lalu jalankan: npm install npm run build npm start Semua itu dikerjakan otomatis di server mereka. Bonus: Tambahin file vercel.json kalau mau custom { "rewrites": [ { "source": "/old-route", "destination": "/new-route" } ] } Ini misalnya kamu mau redirect atau rewrite URL, tinggal atur aja lewat file vercel.json. Apa yang kamu dapet setelah deploy ke Vercel? Website kamu bisa langsung diakses dengan URL seperti https://nama-project.vercel.appSetiap kali kamu update kode di GitHub, Vercel otomatis build dan deploy versi terbaruBisa custom domain, misalnya jadi www.websitemu.comGratis buat project skala kecil sampai menengahBisa pantau performa, log error, dan analitik langsung dari dashboard Vercel Jadi kalau dibilang singkat: kamu cukup bikin project, dorong ke GitHub, terus klik deploy di Vercel. Tanpa setup ribet, tanpa mikirin server, tanpa harus ngerti networking. Dengan Vercel, kamu tinggal fokus bikin konten dan fitur keren. Urusan buka tokonya? Udah disiapin sama mall premium-nya si Vercel. Penutup: 10 Hal Penting Sudah Kamu Pelajari, Saatnya Naik Level Bareng Mentor Expert Nah, sampai di sini kamu udah berhasil ngelewatin 10 hal penting yang wajib banget dipahami pemula saat belajar Next.js. Mulai dari cara kerja routing, bedain client dan server components, paham layout, optimasi gambar, sampai cara deploy ke Vercel — semua udah kamu lalui dengan analogi yang mudah dicerna dan contoh kode yang bisa langsung dipraktikkan. Tapi jangan berhenti di sini ya. Belajar Next.js itu gak cukup cuma teori doang, apalagi kalau tujuan akhirnya pengen bikin website profesional, masuk ke dunia kerja, atau bahkan jadi freelance developer yang bisa dapetin klien dari luar negeri. Kalau kamu pengen belajar lebih terarah, punya mentor yang bisa bantu review hasil kerja kamu, dan akses ke komunitas yang supportif banget — kamu bisa lanjut belajar bareng mentor expert di BuildWithAngga. Di BuildWithAngga, kamu gak cuma dapat video pembelajaran, tapi juga: Project real-world yang bisa kamu masukin ke portfolioSertifikat resmi buat nunjukin skill kamu ke HRD dan klienAkses selamanya ke semua materi kelasForum diskusi langsung bareng mentor dan murid lainnyaTips karier buat persiapan kerja remote, freelance, atau startup Jadi daripada kamu belajar sendiri dan muter-muter gak jelas, mending langsung dapet arahan dari yang udah berpengalaman. Next.js udah jadi langkah awal yang bagus. Sekarang waktunya kamu leveling up. Belajar lebih dalam, bikin project lebih keren, dan raih karier impian bareng BuildWithAngga 🚀💼 Siap lanjut ke tahap selanjutnya? Yuk gabung sekarang!

Kelas Cara Ubah HTML yang Sudah Ada Jadi Data Berulang di React JS, TypeScript (Free Code) di BuildWithAngga

Cara Ubah HTML yang Sudah Ada Jadi Data Berulang di React JS, TypeScript (Free Code)

Daftar Isi PendahuluanDummy Code (Free)MulaiBuat Proyek ReactStep 1Step 2Step 3Step 4FocusAmbil KodenyaCovert Ke React Pake WebsiteData ReactTypes (TypeScript)Download LibrarySetelah Semua di Atas Bisa di Tulis GiniSwiperPengkondisianPerulanganLinkRupiah (Bonus)Hasil Akhir Semua Tutorial KitaPenutup Pendahuluan Kalau kamu lgi pegang file HTML dan mulai mikir, “Gimana ya caranya ngeubah ini jadi komponen React pakai TypeScript?” tenang, kamu ada di tempat yang tepat. Di sini, kita bakal bongkar bareng gimana cara nyulap HTML biasa jadi struktur React yang rapi dan reusable. Gak cuma itu, kamu juga bakal dapet kodenya secara gratis, tinggal ubah dan sesuaikan. Kita bakal bahas gimana data bisa ditampilkan, dan gimana cara ngelola data yang berulang biar gak bikin kepala cenat-cenut. Siap? Yuk mulai! Dummy Code (Free) Di tutorial kali ini, kita bakal sru-seruan bareng ngebedah proyek keren dari Shaynakit. Kabar baiknya: ini 100% gratis, bro! Dan yang makin mantep, kodenya udah siap tempur. Jadi lo nggak perlu mulai dari nol, tinggal colok, modif dikit, langsung jalan. Nggak ribet, nggak bikin kening berkerut, pokoknya ngoding jadi fun banget! Shaynakit ini tuh kayak buffet buat front-end developer tinggal pilih desain yang lo suka, semua udah sepaket sama kodenya. Ada versi gratis, ada juga yang premium. Tapi santai, yang gratis pun udah cukup loyal kok. Biasanya yang dibatesin cuma jumlah halaman aja. Nah, kalau yang premium? Itu sih udah kayak pesta coding semua elemen tinggal comot, tinggal pakai, beres! Sekarang masuk ke inti dari semuanya: gimana cara dapetin template gratisnya. Gampang banget, nggak perlu mantra khusus. Cukup ikutin langkah-langkah ini: Buka situs utamanya di sini: https://shaynakit.com/landing.Klik menu Register atau langsung aja meluncur ke https://shaynakit.com/register buat daftar akun dulu.Setelah berhasil daftar dan login, buka halaman template yang mau dipakai di sini: https://shaynakit.com/details/mahouse-real-estate-html-tailwind-css-template.Klik tombol Download, lalu pilih opsi Free Trial.Lanjut klik Start Today buat mulai akses gratisnya.Setelah itu, balik lagi ke halaman template tadi dan klik tombol Download sekali lagi.File-nya bakal langsung keunduh dalam format .zip.Simpan file .zip itu ke folder lokal kamu, misalnya ke: ./source-code/mahouse.zip. Udah, beres. Sekarang kamu punya satu paket desain + kode yang siap kamu eksplor. Tinggal buka, utak-atik, terus bawa ke proyek kamu. Mulai Buat Proyek React 1. Buat Folder Pertama-tama, bikin dulu folder baru sbagai tempat project-nya. Setelah itu, buka terminal di dalam folder itu, lalu ketik perintah ini: npm create vite@latest Sampai hasilnya nanti kira-kira bakal keliatan kayak gini: 2. Jalankan Proyeknya cd .\\mahouse-buildwithangga npm install npm run dev 3. Akses Browser 4. Buat Filenya Step 1 Sekarang kita geser dulu ke proyek gratisan dari shaynakit.com. Di sini kita bakal mulai utak-atik kode dari proyek mahouse yang udh kamu download. Pastikan file-nya udah kamu extract all, terus udah kamu buka juga di VSCode. Intinya, sebelum lanjut, pastiin dulu tampilan awalnya udah kayak gini: Nah, ini dia halaman utama VSCode ibaratnya kayak meja kerja kamu. Semua alat, catatan, dan bahan buat ngoding ada di sini. Di sinilah tempat kamu mulai ngerakit proyeknya pelan-pelan, satu baris kode demi satu ide. Step 2 Sekarang kita masuk ke file package.json ibaratnya ini kayak daftar belanjaan atau peta jalan buat project kamu. Nah, di dalamnya, kamu tinggal isi bagian ini: "dependencies": { ...... ...... "@tailwindcss/vite": "^4.1.4", "tailwindcss": "^4.1.4", ...... ...... }, ekarang buka file vite.config.ts anggap aja ini kayak remote control yang nge-set gimana proyek kamu jalan. Isi file ini dengan kode berikut: 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(),], }) Selanjutnya, di terminal kamu tinggal jalankan perintah ini buat mulai ngejalanin proyeknya: npm install npm install itu ibarat kamu lagi masuk ke toko alat tempur buat ngoding, terus bilang, "Bro, aku butuh senjata ini buat proyek aku!" Nah, begitu kamu ketik npm install, si npm (singkatan dari Node Package Manager) bakal lngsung ngedownload semua alat-alat (alias package/library) yang dibutuhin sama proyek kamu. Biasanya perintah ini dijalanin pertama kali setelah kamu ngedownload proyek orang dari GitHub atau nyalin template. Soalnya, di situ biasanya cuma ada daftar alat-alat yang dibutuhin (di file package.json), tapi barangnya belum ada. Jadi, npm install tuh yang bakal ngambilin semuanya dari gudang dan naro di folder node_modules. Hasil akhirnya? Kamu bakal dapet folder node_modules yang isinya semua tools yang proyek kamu butuhin biar bisa jalan dengan mulus. Bisa dibilang ini tuh kayak ngisi ulang amunisi sebelum perang di medan coding. Hasil: Step 3 Selanjutnya, tinggal kamu ketik dan jalanin perintah ini di terminal: npx @tailwindcss/cli -i ./src/input.css -o ./src/output.css --watch Perintah npx @tailwindcss/cli -i ./src/input.css -o ./src/output.css --watch itu intinya kamu nyuruh Tailwind buat ambil CSS mentah lalu diolah jadi CSS siap pakai, terus dipantau terus kalau ada perubahan. Lalu akses Proyeknya ke Browser kalian. Hasil: Step 4 Abis itu, klik tombol “Explore Houses”, nanti kamu bakal langsung diarahkan ke halaman ini: Ini tuh tampilan buat mobile, alias layar kcil dengan lebar maksimal 640px. Kalau ukurannya udah lewat dari 640px, itu udah masuk ke wilayah tablet atau desktop. Jadi, intinya: di bawah 640px = mobile, di atas itu = tablet dan desktop. Focus Sekarang, kita fokus ke bagian ini ya, kita bakal ngulik dan kerja bareng di bagian Category. Ambil Kodenya File-nya bisa kamu temukan di sini: <http://127.0.0.1:3000/src/home.html> Nah, ini dia kode yang buat nampilin gambar dari path tadi: <!-- Categories Section --> <section class="relative w-full overflow-hidden"> <div class="swiper !px-6"> <div class="swiper-wrapper py-5"> <!-- City --> <a href="#" class="swiper-slide group max-w-[130px]"> <div class="flex flex-col gap-4 items-center justify-center py-5 bg-accent rounded-[16px] w-[130px] transition-all duration-300 group-hover:ring group-hover:ring-foreground" > <div class="w-[60px] h-[60px] bg-primary rounded-full flex items-center justify-center shrink-0" > <img src="./assets/images/icons/building-4.svg" /> </div> <div class="text-center"> <h3 class="font-semibold text-[16px]">City</h3> <p class="text-secondary text-[14px]">829 house</p> </div> </div> </a> <!-- Nature --> <a href="#" class="swiper-slide group max-w-[130px]"> <div class="flex flex-col gap-4 items-center justify-center py-5 bg-accent rounded-[16px] w-[130px] transition-all duration-300 group-hover:ring group-hover:ring-foreground" > <div class="w-[60px] h-[60px] bg-primary rounded-full flex items-center justify-center shrink-0" > <img src="./assets/images/icons/tree.svg" /> </div> <div class="text-center"> <h3 class="font-semibold text-[16px]">Nature</h3> <p class="text-secondary text-[14px]">54,293 house</p> </div> </div> </a> <!-- Apartment --> <a href="#" class="swiper-slide group max-w-[130px]"> <div class="flex flex-col gap-4 items-center justify-center py-5 bg-accent rounded-[16px] w-[130px] transition-all duration-300 group-hover:ring group-hover:ring-foreground" > <div class="w-[60px] h-[60px] bg-primary rounded-full flex items-center justify-center shrink-0" > <img src="./assets/images/icons/3dcube.svg" /> </div> <div class="text-center"> <h3 class="font-semibold text-[16px]">Apartment</h3> <p class="text-secondary text-[14px]">221 house</p> </div> </div> </a> </div> </div> </section> Covert Ke React Pake Website Step-stepnya : Yuk, buka link ini: <https://transform.tools/html-to-jsx> Paste kode-nya persis seperti gambar di atas ya (gambar itu hasil dari kode yang tadi kamu paste).Klik tombol “Copy” yang berwrna biru di pojok kanan atas, ya!Lalu, paste kode-nya ke proyek React kamu, kira-kira bakal jadi seperti ini: Data React Bayangin kamu dapet data dari Back End Engineer, bentuknya kayak gini nih. Entah kamu liatnya di Postman, atau di tools lain yang biasa kamu pakai buat cek data. [ { id: 1, name: "City", slug: "city", photo: "<https://cakfan.github.io/mahouse-dark-mobile/assets/images/icons/building-4.svg>", staycations_count: 3, staycations: [ { id: 101, name: "Sunset Paradise Villa", location: "Bali, Indonesia", price: 1200000, image: "<https://example.com/images/staycations/villa1.jpg>", }, { id: 102, name: "Ocean Breeze Resort", location: "Lombok, Indonesia", price: 950000, image: "<https://example.com/images/staycations/resort1.jpg>", }, { id: 103, name: "Coral View Inn", location: "Raja Ampat, Indonesia", price: 1500000, image: "<https://example.com/images/staycations/inn1.jpg>", }, ], popular_staycations: [ { id: 103, name: "Coral View Inn", location: "Raja Ampat, Indonesia", price: 1500000, image: "<https://example.com/images/staycations/inn1.jpg>", }, { id: 101, name: "Sunset Paradise Villa", location: "Bali, Indonesia", price: 1200000, image: "<https://example.com/images/staycations/villa1.jpg>", }, ], }, { id: 2, name: "Nature", slug: "nature", photo: "<https://cakfan.github.io/mahouse-dark-mobile/assets/images/icons/tree.svg>", staycations_count: 3, staycations: [ { id: 101, name: "Sunset Paradise Villa", location: "Bali, Indonesia", price: 1200000, image: "<https://example.com/images/staycations/villa1.jpg>", }, { id: 102, name: "Ocean Breeze Resort", location: "Lombok, Indonesia", price: 950000, image: "<https://example.com/images/staycations/resort1.jpg>", }, { id: 103, name: "Coral View Inn", location: "Raja Ampat, Indonesia", price: 1500000, image: "<https://example.com/images/staycations/inn1.jpg>", }, ], popular_staycations: [ { id: 103, name: "Coral View Inn", location: "Raja Ampat, Indonesia", price: 1500000, image: "<https://example.com/images/staycations/inn1.jpg>", }, { id: 101, name: "Sunset Paradise Villa", location: "Bali, Indonesia", price: 1200000, image: "<https://example.com/images/staycations/villa1.jpg>", }, ], }, { id: 3, name: "Apartment", slug: "apartment", photo: "<https://cakfan.github.io/mahouse-dark-mobile/assets/images/icons/3dcube.svg>", staycations_count: 3, staycations: [ { id: 101, name: "Sunset Paradise Villa", location: "Bali, Indonesia", price: 1200000, image: "<https://example.com/images/staycations/villa1.jpg>", }, { id: 102, name: "Ocean Breeze Resort", location: "Lombok, Indonesia", price: 950000, image: "<https://example.com/images/staycations/resort1.jpg>", }, { id: 103, name: "Coral View Inn", location: "Raja Ampat, Indonesia", price: 1500000, image: "<https://example.com/images/staycations/inn1.jpg>", }, ], popular_staycations: [ { id: 103, name: "Coral View Inn", location: "Raja Ampat, Indonesia", price: 1500000, image: "<https://example.com/images/staycations/inn1.jpg>", }, { id: 101, name: "Sunset Paradise Villa", location: "Bali, Indonesia", price: 1200000, image: "<https://example.com/images/staycations/villa1.jpg>", }, ], }, ]; Pathnya: Ambil URL path dari hasil Get Data itu, terus simpan di file .env kamu, kira-kira seperti ini: # env VITE_REACT_API_URL = <http://127.0.0.1:8000/api> VITE_REACT_API_STORAGE_URL = <http://127.0.0.1:8000/storage> VITE_REACT_API_URL ini isinya alamat lokal buat akses endpoint API React kamu lewat Vite, jadi nanti buat ngambil data dari backend langsung ke sini. VITE_REACT_API_STORAGE_URL ini isinya alamat lokal buat akses folder storage API React kamu lewat Vite, biasanya dipake buat manggil file-file yang disimpen di backend. Types (TypeScript) Kalau kita liat dari data yang dikasih, kira-kira tipe TypeScript-nya bakal jadi kayak gini: // src/types/type.ts export interface Category { id: number; name: string; slug: string; photo: string; staycations_count: number; staycations: Staycations[]; popular_staycations: Staycations[]; } Download Library Lanjut ya, sekarang kita download dulu beberapa kebutuhan. Biasanya sih, walau cuma satu halaman, tetep aja ada beberapa library yang sering dipake biar semuanya enak dijalanin. axios Axios itu ibarat kurir pribadi di proyek React TypeScript kamu. Tugasnya? Bolak-balik nganter data dari frontend ke backend dan sebaliknya. Jadi kamu tinggal bilang, “Eh, ambilin data dari API ini dong,” dan si Axios langsung gerak ambilinnya buat kamu rapih, cepat, dan bisa diatur sesuai maumu. Cocok banget buat bikin komunikasi antar sistem jadi lancar tanpa ribet. Perintahin di terminal React kamu gini: npm install axios // src/services/apiServices.ts import axios from 'axios'; const BASE_URL = import.meta.env.VITE_REACT_API_URL; const apiClient = axios.create({ baseURL: BASE_URL, }); // Export axios.isAxiosError export const isAxiosError = axios.isAxiosError; export default apiClient; Bayangin kamu lagi bangun jalur kirim barang dari toko (frontend) ke gudang (backend). Nah, apiClient ini ibarat mobil pengantar yang udah disiapin jalurnya lewat peta (si VITE_REACT_API_URL). Jadi tiap kali kamu mau kirim atau ambil barang (data), tinggal panggil mobil ini nggak usah repot setel alamatnya tiap kali. Bonusnya, kamu juga dikasih alat buat ngecek kalau ada kecelakaan di jalan: isAxiosError buat tahu itu error dari jalur Axios atau bukan. Praktis banget buat urusan bolak-balik data. // HomePage.tsx import apiClient from "../services/apiServices"; Sekarang masukin aja apiClient itu biar nanti bisa langsung kamu pake di halaman HomePage.tsx, tinggal panggil dan gas ambil datanya. react-router-dom react-router-dom itu kayak GPS-nya aplikasi React kamu. Dia yang ngatur kamu mau pindah ke halaman mana tanpa harus rfresh satu halaman penuh. Jadi pas kamu klik tombol “Profile” atau “Explore”, dia langsung ngarahin ke rute yang bener halus, cepat, dan seamless! Tanpa dia, aplikasi kamu bakal kayak rumah tanpa pintu: semua ada, tapi bingung mau masuk ke mana 😄 Perintahin di terminal React kamu gini: npm i react-router-dom // HomePage.tsx import { Link } from "react-router-dom"; Sekarang masukin aja Link itu biar nanti bisa langsung kamu pake di halaman HomePage.tsx, tinggal panggil dan gas ambil datanya. swiper Swiper itu ibarat rel geser otomatis buat elemen-elemen di halaman kamu kayak galeri foto, daftar produk, atau testimoni. Tinggal kamu kasih "gerbong"-nya (alias item-item yang mau ditampilin), si Swiper yang bantuin geserin dengan mulus. Bisa geser manual, bisa otomatis, bisa juga dikustom sesuka hati. Pokoknya, bikin komponen kamu jadi lebih interaktif dan modern banget! Perintahin di terminal React kamu gini: npm i swiper // HomePage.tsx import { Swiper, SwiperSlide } from "swiper/react"; Sekarang masukin aja swiper itu biar nanti bisa langsung kamu pake di halaman HomePage.tsx, tinggal panggil dan gas ambil datanya. Setelah Semua di Atas Bisa di Tulis Gini // HomePage.tsx import { useEffect, useState } from "react"; import { Swiper, SwiperSlide } from "swiper/react"; import type { Category } from "./types/type"; import apiClient from "../services/apiServices"; import { Link } from "react-router-dom"; // Mengambil data kategori dari API const fetchCategories = async () => { const response = await apiClient.get("/categories"); return response.data.data; }; export default function Homepage() { const [categories, setCategories] = useState<Category[]>([]); const [loadingCategories, setLoadingCategories] = useState(true); const [error, setError] = useState<string | null>(null); // Mengambil data kategori saat komponen pertama kali dimuat useEffect(() => { const fetchCategoriesData = async () => { try { const categoriesData = await fetchCategories(); setCategories(categoriesData); } catch { setError("Failed to load categories"); } finally { setLoadingCategories(false); } }; fetchCategoriesData(); }, []); // Jika masih loading atau ada error, tampilkan pesan loading atau error if (loadingCategories) { return <p>Loading categories...</p>; } if (error) { return <p>Error loading data: {error}</p>; } // Base URL untuk gambar kategori const BASE_URL = import.meta.env.VITE_REACT_API_STORAGE_URL; return ( <section className="relative w-full overflow-hidden"> ... </section> ); } Swiper Pake // HomePage.tsx <section className="relative w-full overflow-hidden"> <div className="swiper !px-6"> <Swiper className="swiper-wrapper py-5" direction="horizontal" spaceBetween={20} slidesPerView="auto" slidesOffsetAfter={20} slidesOffsetBefore={20}> <SwiperSlide className="!w-fit"> {/* City */} <a href="#" className="swiper-slide group max-w-[130px]"> <div className="flex flex-col gap-4 items-center justify-center py-5 bg-accent rounded-[16px] w-[130px] transition-all duration-300 group-hover:ring group-hover:ring-foreground"> <div className="w-[60px] h-[60px] bg-primary rounded-full flex items-center justify-center shrink-0"> <img src="./assets/images/icons/building-4.svg" /> </div> <div className="text-center"> <h3 className="font-semibold text-[16px]">City</h3> <p className="text-secondary text-[14px]">829 house</p> </div> </div> </a> </SwiperSlide> <SwiperSlide className="!w-fit"> {/* Nature */} ... </SwiperSlide> <SwiperSlide className="!w-fit"> {/* Apartment */} ... </SwiperSlide> </Swiper> </div> </section> Penjelasan Pertama, kamu perlu pastiin udah install library Swiper di proyek React kamu. Bisa lewat npm install swiper atau yarn add swiper. Setelah itu, import Swiper dan SwiperSlide dari swiper/react, plus kalau mau styling-nya langsung jalan, tambahin juga import CSS-nya import 'swiper/css';. Nah, di dalam komponennya, kamu tinggal bungkus item kamu pake <Swiper> dan tiap konten di dalamnya taruh di <SwiperSlide>. Kamu juga bisa atur properti kayak slidesPerView="auto" biar jumlah slide-nya fleksibel, dan spaceBetween buat jarak antar slide. Jangan lupa slidesOffsetBefore dan slidesOffsetAfter kalau kamu pengn ada padding di kanan-kiri. Kedua, dari sisi HTML dan styling-nya, kamu bisa bungkus Swiper dalam <section> dan <div className="swiper"> buat kontrol layout dan padding. Tiap SwiperSlide kamu bisa atur lebar pakai !w-fit, dan di dalamnya isi komponen custom seperti card kategori—misalnya ikon, nama, dan jumlah rumah. Di contoh ini, pakai kmbinasi Tailwind seperti bg-accent, rounded-[16px], dan group-hover:ring biar animasi hover-nya hidup. Hasil akhirnya adalah tampilan slider kategori yang bisa digeser kanan-kiri dengan tampilan modern, responsif, dan interaktif! Hapus // HomePage.tsx <Swiper className="swiper-wrapper py-5" direction="horizontal" spaceBetween={20} slidesPerView="auto" slidesOffsetAfter={20} slidesOffsetBefore={20}> <SwiperSlide className="!w-fit"> {/* City */} <a href="#" className="swiper-slide group max-w-[130px]"> <div className="flex flex-col gap-4 items-center justify-center py-5 bg-accent rounded-[16px] w-[130px] transition-all duration-300 group-hover:ring group-hover:ring-foreground"> <div className="w-[60px] h-[60px] bg-primary rounded-full flex items-center justify-center shrink-0"> <img src="./assets/images/icons/building-4.svg" /> </div> <div className="text-center"> <h3 className="font-semibold text-[16px]">City</h3> <p className="text-secondary text-[14px]">829 house</p> </div> </div> </a> </SwiperSlide> </Swiper> Nah, bagian “Nature” dan “Apartment” ini wajib kamu hapus dulu karena nanti kita bakal buat mereka jadi perulangan pakai React JS biar lebih efisien dan gampang diatur. Jadi, jangan pusing bikin slide satu-satu manual, nanti React yang handle. Pengkondisian Pake // HomePage.tsx {categories.length > 0 ? "SwiperSlide" : "belum ada data category terbaru"} Jadi gini, kalau categories kamu isinya ada lebih dari nol, berarti data kategori udah siap dan langsung kita tampilin pake komponen SwiperSlide biar slider-nya jalan. Tapi, kalau ternyata belum ada data sama sekali, kita kasih pesan santai: “belum ada data category terbaru” supaya user nggak bingung dan tau kalau datanya memang lagi kosong. Gampang, kan? Jadi user dapet info yang jelas, bukan tampilan kosong doang. Lalu“SwiperSlide” nya ubah isinya dengan tag SwiperSlide, hasilnya gini: // HomePage.tsx <Swiper className="swiper-wrapper py-5" direction="horizontal" spaceBetween={20} slidesPerView="auto" slidesOffsetAfter={20} slidesOffsetBefore={20}> {categories.length > 0 ? ( <SwiperSlide className="!w-fit"> {/* City */} <a href="#" className="swiper-slide group max-w-[130px]"> <div className="flex flex-col gap-4 items-center justify-center py-5 bg-accent rounded-[16px] w-[130px] transition-all duration-300 group-hover:ring group-hover:ring-foreground"> <div className="w-[60px] h-[60px] bg-primary rounded-full flex items-center justify-center shrink-0"> <img src="./assets/images/icons/building-4.svg" /> </div> <div className="text-center"> <h3 className="font-semibold text-[16px]">City</h3> <p className="text-secondary text-[14px]">829 house</p> </div> </div> </a> </SwiperSlide> ) : ( "belum ada data category terbaru" )} </Swiper> Perulangan Caranya // HomePage.tsx categories.map((category) => ("SwiperSlide kita")) Nah, bayangin kamu punya tumpukan kategori yang pengen ditampilin. Dengan categories.map((category) => ("SwiperSlide kita")), kamu kayak lagi bilang ke React, “Eh, buat dong satu slide buat tiap kategori yang ada!” Jadi, buat setiap item di daftar kategori, React bakal bikin satu SwiperSlide baru yang isiya sesuai sama data kategori itu. Praktis banget, tinggal nambah data aja, langsung muncul slide baru. Nah, supaya bener, tag <SwiperSlide> itu kamu masukin langsung ke dalam fungsi map-nya. Jadi nanti tiap kategori bakal dibungkus oleh <SwiperSlide> secara otomatis. Hasilnya bakal kayak gini: // HomePage.tsx <Swiper className="swiper-wrapper py-5" direction="horizontal" spaceBetween={20} slidesPerView="auto" slidesOffsetAfter={20} slidesOffsetBefore={20}> {categories.length > 0 ? categories.map((category) => ( <SwiperSlide key={category.id} className="!w-fit"> {/* City */} <a href="#" className="swiper-slide group max-w-[130px]"> <div className="flex flex-col gap-4 items-center justify-center py-5 bg-accent rounded-[16px] w-[130px] transition-all duration-300 group-hover:ring group-hover:ring-foreground"> <div className="w-[60px] h-[60px] bg-primary rounded-full flex items-center justify-center shrink-0"> <img src={`${BASE_URL}/${category.photo}`} /> </div> <div className="text-center"> <h3 className="font-semibold text-[16px]">{category.name}</h3> <p className="text-secondary text-[14px]">{category.staycations_count} house</p> </div> </div> </a> </SwiperSlide> )) : "belum ada data category terbaru"} </Swiper> Link Pake Selanjutnya, kita perlu ubah linknya jadi kayak gini supaya pas diklik, dia langsung bawa kamu ke halaman yang sesuai dengan kategori itu. Jadi link-nya dinamis, nggak statis lagi bikin pengalaman user makin mulus dan keren. // HomePage.tsx <SwiperSlide key={category.id} className="!w-fit"> {/* City */} <Link to={`/category/${category.slug}`} className="swiper-slide group max-w-[130px]"> <div className="flex flex-col gap-4 items-center justify-center py-5 bg-accent rounded-[16px] w-[130px] transition-all duration-300 group-hover:ring group-hover:ring-foreground"> <div className="w-[60px] h-[60px] bg-primary rounded-full flex items-center justify-center shrink-0"> <img src={`${BASE_URL}/${category.photo}`} /> </div> <div className="text-center"> <h3 className="font-semibold text-[16px]">{category.name}</h3> <p className="text-secondary text-[14px]">{category.staycations_count} house</p> </div> </div> </Link> Jadi, di sini kamu pakai tag <Link> dari react-router-dom buat bikin area yang bisa diklik dan langsung bawa user ke halaman kategori tertentu, misalnya /category/city. Jadi bukan cuma tampilan doang, tapi ada navigasi dinamis yang bikin pengalaman browsing lebih lancar tanpa reload halaman. Nah, di dalam <Link> itu ada <img> yang sumber gambarnya (src) kita bikin dinamis juga. Jadi gambarnya diambil dari backend lewat BASE_URL ditambah path foto kategori (category.photo). Ini bikin tiap slide punya gambar unik sesuai kategorinya, jadi slider-nya nggak cuma keren tapi juga informatif. Rupiah (Bonus) Caranya // HomePage.tsx // Format currency to IDR const formatCurrency = (value: number) => { return new Intl.NumberFormat("id-ID", { style: "currency", currency: "IDR", maximumFractionDigits: 0, }).format(value); }; Fungsi formatCurrency ini tugasnya buat ngerapihin angka jadi format mata uang Indonesia, alias Rupiah. Jadi misalnya kamu punya angka 1500000, nanti bakal diubah jadi Rp1.500.000 yang enak dilihat dan gampang dimengerti. Gak ada desimal, biar tampilannya simpel dan rapi. Kamu tinggal panggil fungsi ini kapan pun mau nampilin harga atau uang di UI biar tampilannya profesional. // HomePage.tsx <strong>{formatCurrency(staycation.price)}</strong> Nah, di bagian ini kamu panggil fungsi formatCurrency buat ngerubah staycation.price jadi format Rupiah yang cakep. Jadi harga staycation-nya gak cuma angka doang, tapi lagsung tampil tebal dan rapi kayak Rp1.500.000 gitu. Hasil Akhir Semua Tutorial Kita Jadi, ini dia hasil akhir proyeknya! Sebenarnya kamu bisa langsung copy-paste kode ini kalau mau, atau kalau kamu lagi ngecek-ngecek, “Eh, udah sama belum ya sama yang aku buat?” tinggal cocok-cocokin aja. Santai, tinggal pakai dan eksplorasi lebih lanjut sesuai kebutuhan kamu. import { useEffect, useState } from "react"; import { Swiper, SwiperSlide } from "swiper/react"; import type { Category } from "./types/type"; import apiClient from "../services/apiServices"; import { Link } from "react-router-dom"; // Mengambil data kategori dari API const fetchCategories = async () => { const response = await apiClient.get("/categories"); return response.data.data; }; export default function Homepage() { const [categories, setCategories] = useState<Category[]>([]); const [loadingCategories, setLoadingCategories] = useState(true); const [error, setError] = useState<string | null>(null); // Mengambil data kategori saat komponen pertama kali dimuat useEffect(() => { const fetchCategoriesData = async () => { try { const categoriesData = await fetchCategories(); setCategories(categoriesData); } catch { setError("Failed to load categories"); } finally { setLoadingCategories(false); } }; fetchCategoriesData(); }, []); // Jika masih loading atau ada error, tampilkan pesan loading atau error if (loadingCategories) { return <p>Loading categories...</p>; } if (error) { return <p>Error loading data: {error}</p>; } // Base URL untuk gambar kategori const BASE_URL = import.meta.env.VITE_REACT_API_STORAGE_URL; return ( <section className="relative w-full overflow-hidden"> <div className="swiper !px-6"> <Swiper className="swiper-wrapper py-5" direction="horizontal" spaceBetween={20} slidesPerView="auto" slidesOffsetAfter={20} slidesOffsetBefore={20}> {categories.length > 0 ? categories.map((category) => ( <SwiperSlide key={category.id} className="!w-fit"> {/* City */} <Link to={`/category/${category.slug}`} className="swiper-slide group max-w-[130px]"> <div className="flex flex-col gap-4 items-center justify-center py-5 bg-accent rounded-[16px] w-[130px] transition-all duration-300 group-hover:ring group-hover:ring-foreground"> <div className="w-[60px] h-[60px] bg-primary rounded-full flex items-center justify-center shrink-0"> <img src={`${BASE_URL}/${category.photo}`} /> </div> <div className="text-center"> <h3 className="font-semibold text-[16px]">{category.name}</h3> <p className="text-secondary text-[14px]">{category.staycations_count} house</p> </div> </div> </Link> </SwiperSlide> )) : "belum ada data category terbaru"} </Swiper> </div> </section> ); } Penutup Sip, itu dia semuaya! Semoga langkah-langkahnya jelas dan kamu makin pede buat ngulik React + TypeScript. Kalau ada yng bingung atau pengen tanya-tanya, jangan ragu buat beli kelas premium BuildWithAngga, ya! Selamat ngoding, semoga proyek kamu lancar jaya dan hasilnya keren.

Kelas 7 Plugin Tailwind CSS di VSCode yang Ngebantu Banget di BuildWithAngga

7 Plugin Tailwind CSS di VSCode yang Ngebantu Banget

Pendahuluan Buat lo yang sering ngoding front-end, apalagi pake Tailwind CSS, pasti udah nggak asing lagi sama yang namanya “class utility yang numpuk kayak gundukan pasir”. Tailwind tuh emang enak sih, tinggal ketik flex, gap-4, text-center, langsung jadi tampilan kece. Gak perlu mikirin styling panjang-panjang di file CSS lagi. Tapi ya… kadang suka nyebelin juga 😅 Lo baru ngetik setengah bg-, eh lupa lagi kelanjutannya apa. Atau lebih parah, lo nulis bg-blu-500 (yes, salah ejaan!), terus heran kenapa warna gak muncul-muncul. Dan jangan lupakan class yang panjangnya kayak kereta api, flex items-center justify-between bg-white text-sm px-6 py-4 shadow-md rounded-lg, mata bisa jereng liatnya. Nah, daripada stres sendiri, mending manfaatin plugin-plugin keren di VSCode yang bisa bantuin lo ngoding Tailwind dengan lebih santai. Mulai dari auto-complete class, preview warna langsung, ngasih tahu kalau ada typo, sampai ngerapiin urutan class biar gak kayak mie kusut, semua bisa lo dapetin cuma modal install plugin. Intinya, Tailwind itu udah keren. Tapi dengan bantuan plugin, kerennya bisa naik level. Ngoding jadi cepet, rapi, gak banyak mikir, dan pastinya lebih asik. Apalagi kalo lo sering kerja di proyek yang full Tailwind, plugin-plugin ini bakal jadi temen setia banget! So, di artikel ini gue bakal kasih lo 7 plugin Tailwind CSS di VSCode yang ngebantu banget, udah gue pilihin yang paling kece, paling sering dipake, dan paling berfaedah buat workflow lo. Cus, langsung lanjut ke listnya! Tailwind CSS IntelliSense Oke, kita mulai dari yang paling wajib dan paling sering direkomenin orang, Tailwind CSS IntelliSense. Plugin ini tuh bener-bener kaya asisten pribadi lo pas lagi ngetik class Tailwind. Tailwind CSS IntelliSense 🔥 Fitur utamanya: Auto-complete class: Lo tinggal ketik bg- terus langsung keluar tuh semua opsi warna, lengkap dari bg-red-500 sampe bg-emerald-950. Gak perlu hafal semua.Hover preview: Kalo lo nge-hover di class text-xl, lo bakal dikasih tahu font-sizenya berapa, line height-nya berapa, semua ditampilin.Error warning: Salah nulis class? Misal pt-12px padahal harusnya pt-3, plugin ini bakal kasih garis merah biar lo sadar ada yang salah. Nyelametin banget. 🤓 Kenapa penting? Tailwind itu punya ratusan bahkan ribuan class. Mana mungkin lo hapalin semua? Nah, plugin ini ngebantu lo biar gak perlu browsing ke dokumentasi tiap detik cuma buat ngecek gap-4 itu berapa pixel. Kerja lo jadi lebih cepet, lebih efisien, dan ngurangin typo-typo konyol yang suka kejadian pas udah tengah malam, mata tinggal satu biji. ✋ Kekurangan? Hmm… kalo lo pake laptop kentang, kadang plugin ini kerasa agak berat sih, apalagi di project gede. Tapi selebihnya? Ini plugin wajib banget. No debat. Install Tailwind CSS IntelliSense Tailwind Shades Lo pernah gak sih, pengen bikin warna custom tapi tetep pengen vibes-nya kayak warna blue-500 bawaan Tailwind? Nah, Tailwind Shades ini solusinya. Tailwind Shades 🔧 Apa yang dia lakuin? Jadi lo tinggal masukin satu warna dasar, misal #3498db, dan plugin ini bakal generate variasi warnanya dari -50 sampe -900 otomatis. Gak perlu ngutak-atik manual di color generator. 😍 Kapan berguna? Kalo lo pengen bikin branding warna sendiri tapi tetep konsisten kayak skema Tailwind.Kalo lo kerja di tim desain-dev dan dikasih warna brand doang, lo bisa langsung turunin shadenya dengan plugin ini. ❌ Catatan kecil: Kadang hasil warnanya gak 100% mirip kaya warna default Tailwind, tapi masih masuk akal dan enak diliat kok. Worth it banget dicoba. Install Tailwind Shades Headwind Kalo lo termasuk orang yang ngetik class Tailwind asal ketik aja, kadang flex bg-white p-4, kadang p-4 bg-white flex, lo harus banget cobain Headwind. Headwind ✨ Apa sih Headwind itu? Singkatnya, ini plugin auto-formatter khusus buat Tailwind CSS. Dia bakal ngerapiin urutan class lo secara otomatis, sesuai urutan yang “standar” dan lebih readable. Misalnya lo nulis gini: <div class="text-white p-4 bg-blue-500 flex"> Setelah disave, dia langsung ubah jadi: <div class="flex p-4 bg-blue-500 text-white"> Rapi, konsisten, dan enak dibaca mata 🧼 💡 Kenapa penting? Class yang berantakan bikin susah dibaca, susah dicari, dan rawan error. Apalagi kalo kerja bareng tim, tiap orang punya gaya nulis class sendiri. Headwind bantu semuanya punya gaya yang sama. Gak cuma rapiin, dia juga bisa hapus class yang duplikat lho. 😅 Kekurangannya? Kadang urutan yang dia anggap “ideal” gak sama sama selera lo, tapi ya tinggal lo custom aja di setting-nya. Gak ribet kok. Install Headwind Tailwind Docs Nah ini buat lo yang sering banget buka tailwindcss.com cuma buat nyari satu class doang, Tailwind Docs plugin ini bakal jadi penyelamat hidup lo. Tailwind Docs 📎 Gimana cara kerjanya? Lo cukup sorot class Tailwind di file lo, terus klik kanan dan pilih “Search in Tailwind CSS Docs”, dan boom! Browser langsung buka dokumentasi resmi Tailwind ke class yang lo pilih tadi. Gak perlu ngetik manual, gak perlu buka tab baru, gak perlu googling site:tailwindcss.com segala. 🧠 Kapan berguna? Lagi belajar Tailwind dan pengen ngerti lebih dalam tiap class.Pengen liat contoh penggunaan dari dokumentasi resmi.Lagi males buka-buka tab baru karena laptop udah ngos-ngosan 🥲 😎 Tips kecil: Kalau lo sering pakai plugin ini, bisa juga bikin shortcut di keyboard biar lebih cepet aksesnya. Tinggal setting di VSCode keybindings. Install Tailwind Docs Tailwind Fold Lo tau gak sih, kadang class Tailwind bisa panjang banget sampe nyampe 3 baris sendiri di file JSX. Apalagi kalo lo tipenya yang suka styling di inline className="". Bikin pusing, beneran. Nah, Tailwind Fold ini bisa ngebantu banget buat nyembunyiin (fold) class-class Tailwind yang panjang jadi satu baris kecil aja. Jadi tampilan file lo tetep rapih dan gak penuh sama gulungan class. Tailwind Fold 🧪 Cara kerja? Contohnya gini, lo punya: <div className="flex items-center justify-between bg-white p-4 rounded shadow-md hover:bg-gray-100 transition duration-300 ease-in-out"> Nanti sama Tailwind Fold bisa dilipat jadi: <div className="…"> Tinggal klik, dan class-nya muncul lagi. Praktis bgt parah. 🧍🏻‍♂️ Kenapa penting? File lo jadi lebih bersihFokus ke struktur komponen, bukan numpuk classLebih gampang navigasi pas review kode ⚠️ Catetan dikit: Kadang plugin ini gak langsung aktif, jadi pastiin lo udah install & aktifin extensi-nya. Gue juga sempet bingung waktu itu, udah install tapi kok gak jalan. Ternyata VSCode harus direstart (iya, kadang VSCode-nya males jalan juga kek kita 😩) Install Tailwind Fold Tailwind Color Matcher Kalau lo pernah bingung nyari warna Tailwind yang paling mirip sama kode HEX tertentu, Tailwind Color Matcher ini bakal jadi penyelamat lo banget. Gak perlu nebak-nebak lagi, apalagi buka dokumen Tailwind cuma buat nyocokin warna 😵‍💫 Tailwind Color Matcher 🔥 Apa yang dia lakuin? Plugin ini nyocokin kode warna HEX yang lo masukin dengan kelas Tailwind CSS yang paling mendekati. Jadi lo tinggal masukin misalnya #38bdf8, terus plugin ini bakal kasih tau: → bg-sky-400 Warna mirip, gak perlu ribet, gak perlu pusing ngafalin semua kelas warna Tailwind yang seabrek itu 😩 🚀 Fitur-fitur utamanya: 🎯 Auto-cocokin kode HEX dengan kelas Tailwind terdekat🎨 Bisa buka color picker langsung di VSCode buat nyari warna💾 Bisa save warna favorit buat dipake berulang📋 Copy langsung ke clipboard class Tailwind-nya ⚠️ Typo Alert: Lo pasti pernah kan, ngetik warna bg-sky-400 tapi malah typo jadi bg-syky-400 atau bg-sky-44... yaudah, warnanya gak muncul. Panik, padahal salah ketik doang 😅 Nah, plugin ini bener-bener ngebantu ngurangin typo & trial-error warna, jadi lo bisa fokus ke layout, bukan malah ribet nyocokin warna. 🧪 Contoh pemakaian: Ketik perintah Match Color di Command Palette (Ctrl + Shift + P)Masukin warna HEX lo, misalnya: #facc15Dia bakal kasih tau lo: → bg-yellow-400 Mudah, cepet, dan gak pake ribet. Cocok banget buat lo yang sering kerja bareng tim desain dan dapet warna dari Figma atau Photoshop pake HEX. Install Tailwind Color Matcher Tailwind Sorter Lo pernah nulis class Tailwind yang panjang banget trus bingung sendiri bacanya? Atau pernah bandingin 2 elemen yang styling-nya sama tapi urutan class-nya ngacak? Nah, plugin Tailwind Sorter ini bener-bener penyelamat hidup lo yang suka styling pake Tailwind 🧹✨ Tailwind Sorter 🔍 Apa fungsinya? Sesuai namanya, plugin ini ngerapihin urutan utility class Tailwind lo secara otomatis. Gak cuma buat keliatan rapi, tapi juga biar gampang dibaca, dan konsisten antara satu file dengan yang lain. <!-- Sebelum --> <div class="text-white hover:bg-blue-600 bg-blue-500 p-4 rounded"> <!-- Setelah pake Tailwind Sorter --> <div class="p-4 rounded bg-blue-500 hover:bg-blue-600 text-white"> Nice kan? 😎 ✨ Fitur keren yang dibawa: 🔄 Sortir otomatis saat lo save file🧠 Urutan sesuai dokumentasi resmi Tailwind🔧 Bisa di-custom urutannya sesuai gaya lo💅 Support HTML, JSX, TSX, Vue, dan lainnya 🚨 Typo Zone: Kadang kita nulis hover:bg-blue-600 di awal, kadang di tengah, kadang di belakang. Apalagi kalo kerja tim, urutan class bisa beda-beda tiap orang. Makanya, plugin ini ngurangin typo & class conflict, dan bikin styling lo konsisten banget. 🧪 Cara make-nya gampang: Install plugin Tailwind Sorter dari VSCode MarketplaceAktifin fitur auto-sort on save biar tiap kali lo save file, class-nya langsung rapiAtur urutan custom (optional) kalo lo pengen gaya lo sendiri 🤝 Kenapa lo harus make? Lo bakal hemat waktu pas code reviewStyling jadi gampang dibaca & dipahamiNgurangin konflik merge di Git (karena beda urutan class bisa bikin konflik) Pokoknya plugin ini tuh ibarat tukang sapu otomatis buat class Tailwind lo, sekali save, langsung cling! Gak perlu lagi mantengin class panjang-panjang yang urutannya kayak abjad acak, tinggal fokus ngoding aja 🧼💻 Install Tailwind Sorter Tips Tambahan Sebelum lo install semua plugin tadi, coba perhatiin dulu beberapa hal ini biar pengalaman ngoding Tailwind lo makin josss: 🔗 Gabungkan plugin yang saling melengkapi Misalnya, lo pake Tailwind IntelliSense buat auto-complete, trus gabungin sama Tailwind Sorter biar class-nya langsung rapi. Kombinasi kayak gini bikin workflow lo makin lancar tanpa hambatan. 🧪 Cek kompatibilitas plugin sama versi Tailwind lo Beberapa plugin kadang belum support fitur terbaru dari Tailwind (apalagi kalo lo udah pake Tailwind v4). Jadi sebelum install, cek dulu di deskripsinya, jangan sampe malah error gak jelas karena versi gak cocok. 🛠️ Manfaatin fitur bawaan VSCode juga Aktifin fitur kayak format on save, emmet snippets, dan code folding. Plugin jadi makin powerful kalau didukung sama settingan VSCode yang optimal. Auto ngoding nyaman deh! Kesimpulan Plugin-plugin VSCode buat Tailwind CSS ini tuh bener-bener penolong hidup lo pas lagi ngoding. Mulai dari ngebantu nulis class yang panjang, ngecek dokumentasi tanpa buka browser, sampe ngerapiin urutan class biar gak kayak mie kusut. Gak cuma bikin kerjaan lo lebih cepet, tapi juga bikin kode lebih bersih, konsisten, dan gampang di-maintain, apalagi kalo lo kerja bareng tim. Yuk, cobain plugin-plugin yang udah gue sebutin tadi, dan rasain sendiri perbedaannya pas ngoding pakai Tailwind CSS! 🚀 “Lo sendiri udah coba plugin yang mana aja? Atau punya plugin andalan selain yang gue sebutin? Share dong di kolom komentar, biar kita saling bantu satu sama lain!” 🧠💬 🎓 Bonus: Rekomendasi Kelas Gratis dari BuildWithAngga Buat lo yang baru nyemplung ke dunia Tailwind CSS atau pengen upgrade skill desain web lo biar makin kece, ini ada beberapa kelas gratis yang super worth it dari BuildWithAngga. Gak cuma gratis, tapi materinya juga beneran daging semua 🥩🔥 1. CSS Tailwind Web Design Kelas ini cocok banget buat lo yang pengen ngedesain website modern dan clean pake Tailwind CSS. Cocok buat pemula maupun yang udah pernah nyoba Tailwind tapi pengen lebih rapi dan estetik. 2. Belajar Tailwind CSS untuk Pemula Website Designer Namanya juga buat pemula, jadi tenang aja, lo bakal dipandu dari nol. Cocok buat lo yang masih suka bingung bedain mt-4 sama mb-4 😆 3. HTML5 + Tailwind CSS: Creating Modern Eye-Catching Website Gabungan antara HTML5 dan Tailwind, lo bakal diajarin bikin website yang gak cuma fungsional tapi juga menarik secara visual. Pokoknya gak cuma ngoding asal tampil. 4. Vue 3 + Tailwind CSS: Membuat Komponen Autocomplete Khusus buat lo yang udah mainan Vue 3, kelas ini ngajarin cara bikin komponen autocomplete yang reusable dan stylish pake Tailwind. Keren buat portofolio lo juga nanti! Jadi, abis install plugin-plugin tadi, langsung aja gas ke salah satu kelas di atas biar makin pro mainin Tailwind CSS. Belajar gratis, dapet ilmu, skill naik, siapa yang nolak coba? 😎📚

Kelas Tutorial Next JS Pemula Mengenal Pentingnya Webpack di BuildWithAngga

Tutorial Next JS Pemula Mengenal Pentingnya Webpack

Kalau kamu sering nongkrong di forum web development atau sekadar scroll TikTok dan Instagraam yang isinya tech content, pasti kamu pernah dengar nama Next.js. Buat kamu yang baru mulai ngoding, mungkin awalnya kelihatan kayayk framework yang “too advanced”. Tapi sebenarnya justru sebaliknya, Next.js itu ramah banget buat pemula—apalagi kalau kamu udah punya sedikit dasar di React. Jadi gini… Next.js adalah framework open-source yang dibangun di atas React. Dia dikembangkan sama tim Vercel, dan fungsinya itu untuk bantu kita bikin aplikasi web modern dengan cara yang lebih cepat, rapi, dan performa yang optimal. Gak cuma untuk UI doang, tapi dia juga siap produksi alias production-ready. Ibaratnya kalau React itu komponen dasarnya, Next.js itu paket hematnya—udah termasuk nasi, lauk, sambal, sama es teh. Nah, fitur-fitur di dalam Next.js ini yang bikin dia jadi favorit banyak developer dan perusahaan: Routing otomatis. Gak perlu setup react-router manual. Cukup bikin file di folder pages/, langsung jadi route.SEO-friendly karena support server-side rendering (SSR) dan static site generation (SSG).Punya fitur API Routes buat bikin backend ringan langsung dari dalam project Next.js.Optimisasi performa seperti lazy loading, image optimization, dan code splitting udah built-in.Dukungan penuh buat TypeScript, ESLint, dan integrasi ke CSS framework modern kayak Tailwind. Keren, kan? Makanya gak heran kalau sekarang banyak perusahaan—dari startup sampe korporat—lebih suka pakai Next.js buat bangun produk mereka. Karena lebih maintainable, scalable, dan cepet. Jadi kalau kamu ngerasa belakangan ini udah mulai ketinggalan tren, masih stuck di HTML statis atau belum sempat ngulik React lebih dalam, belajar Next.js bisa jadi tiket kamu buat naik level. Karena banyak banget lowongan kerja yang cari orang dengan skill Next.js, apalagi kalau kamu pengen kerja remote atau masuk ke dunia startup tech. Nah, terus kenapa kita bahas Webpack di artikel ini? Meskipun kamu jarang banget harus utak-atik Webpack secara langsung pas bikin proyek Next.js, tapi Webpack itu punya peran penting banget di belakang layar. Bisa dibilang, Webpack adalah “mesin dapur” yang bantu nyusun dan ngemas semua kode kita jadi satu aplikasi web yang bisa jalan mulus di browser. Jadi pas kamu nulis komponen, import CSS, pakai gambar, atau bahkan bikin dynamic import untuk komponen tertentu, sebenarnya Webpack yang ngerjain semua di balik layar. Dia yang nge-bundle file-file kamu, optimize performa, dan bikin build kamu jadi ringan dan cepat. Next.js udah nyediain konfigurasi Webpack bawaaaan yang powerful banget, jadi kamu gak harus setting dari nol. Tapi kalau kamu tahu dasar-dasar cara kerja Webpack, kamu jadi lebih ngerti apa yang terjadi di balik layar. Ini juga bantu banget kalau suatu hari kamu butuh kustomisasi—misalnya mau tambahin loader untuk file SVG, atau ubah cara kerja plugin tertentu. Intinya, paham Webpack bukan cuma buat developer expert. Justru kalau kamu baru mulai, sekarang saat yang pas buat kenalan sama tool penting ini, biar kamu gak cuma bisa make, tapi juga ngerti gimana dia bekerja. Oke, itu dulu sebagai pembuka ya. Di artikel selanjutnya kita bakal bahas lebih dalam soal Webpack. Kita bakal lihat gimana dia kerja, apa itu konsep bundling, loader, plugin, dan kenapa semua itu penting buat developer modern—terutama yang pakai Next.js. Siap? Yuk lanjut! Yuk kita mulai bikin project Next.js terbaru buat company profile Sekarang kita udah ngerti kenapa Next.js penting dan apa hubungannya dengan Webpack. Jadi, saatnya kita praktik langsung bikin project Next.js dari nol. Kita bakal bikin fondasi awal untuk website company profile—yang biasanya berisi halaman seperti home, about, services, contact, dan mungkin beberapa halaman tambahan lainnya. Langkah pertama yang kita butuhin tentu aja install Next.js. Next.js sekarang nyediain CLI bernama create-next-app yang super praktis dan udah support setup modern out of the box. Gak usah ribet milih-milih lagi. Langsung buka terminal kamu dan ketik: npx create-next-app@latest company-profile Setelah itu, kamu bakal ditanya beberapa pertanyaan interaktif. Untuk project company profile sederhana, kamu bisa pilih jawaban seperti berikut: TypeScript: yes (supaya kode kamu lebih aman dan modern)ESLint: yes (biar kode lebih rapi)Tailwind CSS: yes (biar styling-nya gampang dan clean)src/ directory: yes (struktur folder lebih terorganisir)App Router: yes (fitur baru pengganti Pages Router, lebih fleksibel)Customize import alias: boleh di-skip atau pakai @/ untuk root folder Tunggu proses instalasi selesai, lalu pindah ke folder project: cd company-profile Jalankan development server dengan: npm run dev Kalau udah, kamu buka browseer dan masuk ke http://localhost:3000, tampilan awal Next.js udah muncul. Ini artinya semua setup kamu udah jalan dengan baik. Struktur folder awalnya kurang lebih seperti ini: company-profile/ ├─ public/ ├─ src/ │ ├─ app/ │ │ ├─ page.tsx │ ├─ styles/ ├─ tsconfig.json ├─ next.config.js Nah, sekarang kamu bisa mulai bikin halaman kayak about, services, atau contact. Tinggal tambahin file baru di dalam folder src/app/, contohnya about/page.tsx, dan isi kontennya bebas. Misalnya: // src/app/about/page.tsx export default function AboutPage() { return ( <main className="p-10"> <h1 className="text-4xl font-bold mb-4">Tentang Kami</h1> <p className="text-lg text-gray-700"> Kami adalah tim profesional yang berfokus membangun solusi digital untuk berbagai industri. </p> </main> ); } Styling bisa kamu atur dengan Tailwind CSS, jadi kamu gak perlu ribet setup class manual. Cukup kasih class seperti text-4xl, font-bold, p-10, dan lainnya. Kalau udah, halaman kamu bisa langsung diakses lewat http://localhost:3000/about. Nah sekarang, di mana sih peran Webpack dalam project Next.js ini? Oke, ini bagian yang jarang kelihatan tapi super penting. Walaupun kamu gak ngoding Webpack secara langsung, tapi semua yang terjadi saat kamu jalankan npm run dev atau npm run build, itu kerjaannya Webpack. Contohnya begini: Saat kamu bikin halaman about/page.tsx, dan kamu impoyrt file CSS atau gambar seperti ini: import Image from 'next/image' import teamPhoto from '@/assets/team.jpg' import './styles.css' Webpack yang ngurus supaya file team.jpg bisa dioptimalkan dan ditampilin di browser dengan ukuran yang tepat. Webpack juga yang handle supaya styles.css di-parse, dikompilasi, dan dimasukin ke dalam halaman yang sesuai. Kalau kamu buka file next.config.js, sebenarnya kamu bisa tambahin konfigurasi khusus buat Webpack. Misalnya, kamu mau custom loader: // next.config.js /** @type {import('next').NextConfig} */ const nextConfig = { webpack: (config) => { config.module.rules.push({ test: /\\.md$/, use: 'raw-loader', }) return config }, } module.exports = nextConfig Di sini kamu menambahkan aturan baru untuk nge-handle file markdown (.md). Jadi, setiap kali kamu import file .md, Webpack tahu harus pakai raw-loader. Contoh lainnya, Webpack juga bantu waktu kamu pakai dynamic import di halaman tertentu: import dynamic from 'next/dynamic' const ServicesComponent = dynamic(() => import('@/components/Services')) export default function HomePage() { return ( <main> <h1>Welcome to Our Company</h1> <ServicesComponent /> </main> ) } Webpack akan otomatis bikin chunk teerpisah untuk komponen Services, supaya gak langsung dimuat semuanya dari awal. Ini bikin aplikasi kamu lebih ringan dan lebih cepat—karena pengguna cuma nge-load yang mereka butuhin dulu. Jadi intinya, Webpack adalah semacam "pengatur lalu lintas" yang memastikan semua aset (JS, CSS, gambar, font, dan sebagainya) bisa dipaketin dan dikirim ke browser dengan cara yang efisien. Dan enaknya pakai Next.js adalah kamu gak perlu mikirin semua itu dari awal, karena konfigurasi Webpack-nya udah dirancang biar optimal buat kebanyakan use case. Tapi… kamu tetap punya akses buat nge-tweak kalau emang butuh. Kenapa sih kita butuh chunk terpisah dalam Next.js (dan proyek modern lainnya)? Oke, kita bahas pelan-pelan biar gak kerasa mumet. Waktu kamu bikin aplikasi web, semua komponen, gambar, file CSS, dan segala macamnya—itu akhirnya harus dikemas jadi file JavaScript (dan CSS) yang bisa dibaca sama browser. Nah, proses ngemasin semua itu disebut bundling, dan itu kerjaannya Webpack. Kalau semuanya digabung dalam satu file besar, bayangin kayak kamu belanja di supermarket terus semua barang ditaruh dalam satu plastik, satu tumpukan tinggi, berat, dan kamu harus bawa semua itu dari awal. Berat, lama, dan bikin kesel kan? Apalagi kalau ternyata kamu cuma butuh satu barang aja dari belanjaan itu. Nah, chunk terpisah adalah solusi dari masaelah itu. Webpack (dan Next.js) otomatis memecah kode kamu menjadi bagian-bagian kecil (chunk), lalu browser hanya akan mengambil bagian yang benar-benar dibutuhkan dulu, sisanya belakangan. Contohnya: Di halaman homepage kamu cuma nampilin komponen Hero dan Services. Tapi di halaman /contact ada form panjang, peta, dan FAQ. Nah, dengan chunk terpisah, pas user buka homepage, mereka hanya nge-load file yang dibutuhkan untuk homepage aja. File untuk /contact gak dimuat dulu sampai user benar-benar klik dan buka halaman itu. Ini penting banget buat performa. Berikut mabnfaat chunking yang paling terasa: Page load jadi lebih cepat. Karena browser gak harus download semua kode sekaligus.User experience lebih baik. Website terasa responsif karena cuma load bagian yang relevan.Cache lebih efisien. Kalau cuma ada satu bagian halaman yang berubah, user bisa reuse chunk lama dari cache mereka.Skalabilitas makin mudah. Semakin besar aplikasi kamu, semakin kamu butuh strategi chunk yang baik biar gak lemot. Dan kerennya, Next.js dengan App Router dan dynamic import bisa otomatis mengatur chunk ini tanpa kamu mikirin konfigurasi ribet. Contoh kodenya kayak gini: import dynamic from 'next/dynamic' const ContactForm = dynamic(() => import('@/components/ContactForm')) export default function ContactPage() { return ( <main> <h1>Hubungi Kami</h1> <ContactForm /> </main> ) } Dengan pakai dynamic, Webpack ngerti bahwa komponen ContactForm ini bisa di-load belakangan. Nanti di-dev tools kamu bisa lihat file chunk seperti contactform.123abc.js muncul secara terpisah. Dan itu yang bikin web kamu lebih ringan. Jadi, chunk terpisah bukan cuma trik teknikal aja, tapi kunci utama bikin website kamu cepat dan nyaman diakses, terutama buat user yang internetnya pas-pasan atau pakai perangkat low-end. Inilah kenapa modern web app udah jadiin ini sebagai standar ✨ Yuk kenalan lebih dalam sama bagiana-bagian penting di Webpack: loader, plugin, dan bundling Kamu mungkin udah pernah denger istilah-istilah ini waktu baca dokumentasi atau ngulik tutorial: loader, plugin, dan bundling. Tapi jujur aja, buat pemula, semua itu awalnya kelihatan kayak istilah alien. Padahal, ini bagian penting banget dari ekosistem modern web development, terutama kalau kamu pakai Next.js yang di balik layarnya dikuatkan oleh Webpack. Di bagian ini kita gak akan bikin konfigurasi Webpack dari nol (karena Next.js udah nyiapin default config yang powerful). Tapi kita akan coba pahami gimana cara kerja Webpack lewat simulasi kecil dan contoh yang bisa bikin kamu lebih paham “mesin” di balik project kamu. Apa itu bundling? Bundling itu proses di mana Webpack menggabungkan banyak file—JavaScript, CSS, gambar, bahkan font—menjadi satu atau beberapa file final yang siap dikirim ke browser. Misalnya kamu punya struktur seperti ini: components/ ├─ Header.tsx ├─ Footer.tsx pages/ ├─ index.tsx ├─ about.tsx Waktu kamu jalanin npm run build, Webpack bakaal telusurin semua import di dalam project kamu, lalu “nge-bundle” mereka jadi satu file (atau beberapa file terpisah, alias chunk). Jadi di browser, kamu gak perlu load 20 file satu-satu. Semuanya udah di-packing rapi dalam satu paket. Apa itu loader? Loader adalah alat bantu buat Webpack ngerti cara menangani jenis file tertentu. Karena default-nya Webpack cuma ngerti JavaScript. Tapi project modern butuh lebih dari itu—ada CSS, TypeScript, gambar, SVG, dan banyak lainnya. Misalnya kamu mau pakai file .css atau .jpg, maka Webpack butuh loader tertentu biar bisa masukin file itu ke dalam bundle akhir. Di project Next.js, ini semua udah diatur otomatis. Tapi kamu tetap bisa tambahin custom loader kalau mau. Contoh sederhana: kamu mau handle file markdown (.md), biar bisa di-import ke komponen React. // next.config.js const nextConfig = { webpack: (config) => { config.module.rules.push({ test: /\\.md$/, use: 'raw-loader', }) return config }, } module.exports = nextConfig Dengan config itu, kamu sekarang bisa import markdown seperti ini: import faqMarkdown from '@/content/faq.md' export default function FAQPage() { return <div>{faqMarkdown}</div> } Tanpa loader, file .md ini bakal error karena Next.js/Webpack gak tahu cara ngebacanya. Apa itu plugin? Kalau loader fokus ke satu file atau satu jenis resource, plugin itu levelnya lebih global. Plugin bisa ngatur proses build secara keseluruhan—kayak optimasi, environment variable, bahkan auto-generate HTML. Contohnya, kamu bisa pakai plugin byuat bersihin folder dist sebelum build baru, atau buat inject variabel saat build. Sekali lagi, di Next.js semua ini udah diurusin. Tapi kamu bisa tambahin plugin custom juga kalau butuh. Misalnya mau pakai plugin webpack.DefinePlugin buat masukin variabel: const webpack = require('webpack') const nextConfig = { webpack: (config) => { config.plugins.push( new webpack.DefinePlugin({ 'process.env.APP_NAME': JSON.stringify('My Company Profile'), }) ) return config }, } module.exports = nextConfig Lalu kamu bisa akses di mana pun di app kamu: console.log(process.env.APP_NAME) Intinya… Webpack itu kayak dapur utama. Loader itu alat-alat masaknya (kompor, oven, panci), plugin itu bumbu rahasia dan strategi masak, sedangkan bundling itu proses akhir semua bahan dimasak dan disajikan jadi satu hidangan lengkap buat user. Kamu mungkin gak ngoprek semua ini setiap hari, tapi dengan ngerti dasarnya, kamu bisa jadi developer yang lebih peka dan paham struktur aplikasi modern. Karena saat error muncul, atau kamu butuh kustomisasi, kamu gak cuma bengong—kamu tahu harus ngoprek bagian mana. Dan kabar baiknya: Next.js udah nyiapin semua fondasi ini buat kamu, jadi kamu tinggal fokus bikin aplikasi yang keren, cepat, dan maintainable. Yuk kita masuk ke simulasi nyata: load SVG jadi React component & import font custom lokal Sekarang kita udah ngerti teori dasar tentang loader, plugin, dan bundling di Webpack (dan Next.js). Tapi supaya makin kebayang gimana cara kerjanya di dunia nyata, kita langsung praktekin dua hal yang sering banget ditemui pas ngembangin website company profile: Load file SVG sebagai React ComponentImport font custom lokal ke dalam project Ini penting banget, karena dua hal ini sering jadi kebutuhan real di project—baik buat branding, design system, atau custom look & feel yang gak bisa dipenuhi cuma dengan library biasa. Load file SVG sebagai React component Biasanya kalau kita cuma import file SVG biasa, SVG itu akan diperlakukan sebagai image oleh Next.js, dan harus dirender pakai <Image /> atau <img>. Tapi gimana kalau kita pengen langsung masukin SVG itu sebagai bagian dari komponen React, biar bisa dikasih props, styling, atau animasi? Nah, di sinilah loader berperan. Pertama, install loader yang dibutuhkan: npm install --save-dev @svgr/webpack Lalu buka file next.config.js, dan tambahbkan konfigurasi custom loader-nya: const nextConfig = { webpack(config) { config.module.rules.push({ test: /\\.svg$/, issuer: /\\.[jt]sx?$/, use: ['@svgr/webpack'], }) return config }, } module.exports = nextConfig Konfigurasi di atas bilang ke Webpack: “Kalau nemu file .svg yang di-import dari file .js, .ts, .jsx, atau .tsx, gunakan loader @svgr/webpack.” Setelah itu kamu bisa langsung pakai SVG sebagai komponen: import Logo from '@/assets/logo.svg' export default function Header() { return ( <header className="flex items-center p-4"> <Logo className="h-8 w-auto text-blue-600" /> <h1 className="ml-4 text-2xl font-semibold">My Company</h1> </header> ) } SVG sekarang bisa diubah warna, dikasih animasi, bahkan diberi props layaknya React component biasa. Ini yang bikin developer modern cinta banget sama SVGR. Import font custom lokal Biasanya kamu bakal butuh font khusus buat branding, dan lebih baik kalau file font-nya disimpan lokal, bukan ambil dari Google Fonts. Alasannya? Lebih cepaat, gak tergantung third-party, dan lebih private. Kamu bisa letakkan file font di public/fonts/, misalnya: public/fonts/ ├─ Inter-Regular.woff2 ├─ Inter-Bold.woff2 Lalu bikin file CSS global khusus untuk font: /* src/styles/fonts.css */ @font-face { font-family: 'Inter'; src: url('/fonts/Inter-Regular.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: 'Inter'; src: url('/fonts/Inter-Bold.woff2') format('woff2'); font-weight: 700; font-style: normal; font-display: swap; } Import CSS-nya di layout.tsx agar font tersedia di seluruh halaman: import '@/styles/fonts.css' export default function RootLayout({ children }: { childrena: React.ReactNode }) { return ( <html lang="id"> <body className="font-sans">{children}</body> </html> ) } Dan terakhir, tinggal tambahkan konfigurasi di tailwind.config.js buat pakai font tersebut: module.exports = { theme: { extend: { fontFamily: { sans: ['Inter', 'sans-serif'], }, }, }, } Boom. Sekarang seluruh web kamu pakai font custom lokal yang jauh lebih ringan dan cepat load-nya. Jadi, apa yang terjadi di balik layar? Pas kamu import SVG sebagai komponen, loader @svgr/webpack akan membaca file SVG, mengubahnya jadi JSX, dan dimasukin ke bundle kamu. Artinya, kamu gak perlu lagi pakai <img src="...">, tapi bisa treat SVG kayak komponen React yang bisa kamu styling langsung. Sedangkan pas kamu import font dari public/, Webpack bakal nge-handle URL-nya dan tetap masukin link itu saat build production. Jadi kamu punya kontrol penuh atas performance dan branding, tanpa harus tergantung CDN luar. Dari dua simulasi real case ini, kamu bisa lihat bahwa loader dan plugin bukan cuma sekadar istilah di dokumentasi. Tapi benar-benar punya dampak besar dalam workflow sehari-hari. Dan makin kamu paham mereka, makin fleksibel dan powerful cara kamu ngembangin web. Gak cuma make Next.js, tapi kamu sekarang ngerti banget kenapa Next.js powerful—karena di belakangnya ada Webpack yang dikonfigurasi secara cerdas. Next.js sekarang punya mesin baru bernama Turbopack: pengganti Webpack yang lebih ngebut dan modern 🚀 Oke, kita udah kenalan sama Webpack, udah paham bundling, loader, dan plugin, dan kita udah nyoba beberapa simulasi real-case yang relevan. Tapi sekarang saatnya update ilmu nih—karena Next.js versi terbaru (khususnya dari versi 13 ke atas) memperkenalkan Turbopack, sebuah game changer dalam dunia bundling dan build tool modern. Yes, Turbopack ini dikembangkan langsung oleh tim Vercel (orang-orang yang bikin Next.js juga), dan mereka secara resmi menyebut Turbopack sebagai "pengganti Webpack di masa depan" untuk Next.js. Jadi… apa itu Turbopack? Turbopack adalah bundler baru yang dibuat dari nol dengan bahasa pemrograman Rust—bahasa yang terkenal super cepat dan aman. Tujuan utama Turbopack adalah untuk mengatasi kelemahan Webpack, terutama dari segi kecepatan dan skalabilitas. Kalau Webpack itu kayak mobil keluarga yang nyaman dan fleksibel, Turbopack itu kayak motor listrik super cepat yang gak berisik dan langsung nyamber gasnya. Apa aja sih perbedaan dan manfaat Turbopack dibanding Webpack? Berikut beberapa hal yang bikin Turbopack jadi primadona baru (dan alasan kenapa kamu bakal cinta banget kalau udah nyoba): 1. Build & Hot Reload Lebih Cepat Turbopack itu berkali-kali lipat lebih cepat dibanding Webpack. Cold Start (pertama kali npm run dev): bisa 10x sampai 700x lebih cepat dibanding Webpack.Hot Reload (pas kamu ubah file): responsnya bisa nyaris instan. Buat kamu yang kerja di project besar, atau punya banyak file dan komponen, ini kerasa banget. Gak perlu nunggu lama-lama saat develop—kerjaan jadi lebih efisien dan produktif. 2. Incremental Compilation Turbopack punya pendekatan yang disebut incremental bundling, di mana dia cuma proses ulang file yang benar-benar berubah. Jadi gak kayak Webpack yang harus “nge-bundle ulang” project tiap kali ada perubahan. Artinya: makin besar project kamu, makin terasa keunggulan Turbopack. 3. Future-proof dan native Next.js Karena dikembangkan langsung oleh Vercel, Turbopack ini udah dioptimasi habis-habisan buat Next.js. Native support TypeScriptNative support React Server ComponentsIntegrasi lancar dengan App Router dan semua fitur baru di Next.js 13+aaa Pokoknya benar-benar dibikin supaya kamu bisa langsung pakai dan nikmatin kecepatannya. Oke, terus gimana cara pakai Turbopack di project kita? Kalau kamu pakai Next.js 13 ke atas, Turbopack udah tersedia secara default untuk development mode. Jadi pas kamu jalanin: npm run dev Secara otomatis, Next.js bakal jalanin project kamu pakai Turbopack. Di terminal biasanya muncul log seperti: Creating an optimized development build... Using Turbopack as bundler Tapi untuk saat ini, Turbopack baru dipakai di development mode aja, bukan production. Untuk production build (npm run build), Next.js masih pakai Webpack. Tapi Vercel udah nyiapin roadmap untuk migrasi full ke Turbopack di production juga—tinggal nunggu stabil. Jadi, apakah Webpack akan ditinggalkan? Iya, pelan-pelan. Tapi tenang, Webpack gak langsung dibuang kok. Banyak project lama masih pakai Webpack, dan ekosistem plugin Webpack juga masih luas banget. Tapi buat project baru, terutama yang dibangun dengan Next.js versi terbaru, kamu udah bisa nikmatin kecepatan Turbopack dan mulai transisi ke masa depan. Intinya… Turbopack itu bundler modern super cepat yang dirancang untuk era React masa kini. Dengan teknologi dari Rust, sistem yang lebih efisien, dan integrasi native ke Next.js, dia udah mulai menggantikan peran Webpack secara bertahap. Sebagai developer pemula, kamu gak perlu ngerti detail teknis Rust atau compiler—cukup ngerti bahwa Turbopack bantu kamu ngoding lebih cepat, reload lebih ringan, dan scaling project jadi lebih nyaman. Penutup: Saatnya naik level dengan Next.js dan siap kerja remote bareng BuildWithAngga Kita udah jalan bareng dari awal: mulai dari kenalan sama Next.js, ngulik Webpack dan semua bagian pentingnya kayak loader dan plugin, sampai akhirnya bahas Turbopack sebagai generasi terbaru bundler modern. Harapannya, sekarang kamu udah gak cuma tahu cara pake Next.js, tapi juga paham apa yang terjadi di balik layar. Belajar kayak gini itu penting banget, apalagi kalau kamu pengen serius kerja sebagai web developer, khususnya di lingkungan kerja remote yang sekarang makin banyak dibuka oleh perusahaan luar negeri. Mereka gak cuma carei orang yang bisa ngehasilin halaman doang, tapi yang ngerti struktur, performa, dan scalable architecture—dan Next.js jadi salah satu skill utama yang sering banget disebut di lowongan kerja internasional. Nah, buat kamu yang pengen belajar lebih terarah, efisien, dan ditemani mentor yang udah punya pengalaman langsung di dunia kerja nyata, **BuildWithAngga adalah tempat terbaik buat mulai**. Di sini kamu gak belajar sendirian, kamu akan: Dibimbing langsung oleh mentor expert yang udah kerja di industri tech dan pernah ngerjain project nyataBikin project nyata seperti company profile, e-commerce, portfolio, hingga admin dashboardAkses kelas seumur hidup, jadi bisa belajar ulang kapan aja tanpa takut expiredDapat sertifikat dan portfolio profesional yang bisa kamu masukin ke LinkedIn atau kirim ke HRGabung ke forum diskusi dan komunitas aktif, tempat kamu bisa tanya, dapet feedback, atau bahkan dapet referensi kerjaFokus ke skill siap kerja remote, bukan cuma teori, tapi praktik langsung seperti di dunia kerja sesungguhnya Dan yang paling penting, kamu akan dapat mindset yang bener: bahwa jadi developer itu bukan soal jago ngoding doang, tapi juga ngerti cara berpikir sistematis, komunikasi tim, dan problem-solving. Jadi… jangan cuma baca artikel ini terus diem aja. Ambil langkah konkrit. Mulai belajar bareng BuildWithAngga, dan siapkan diri kamu buat masuk ke dunia kerja remote yang lebih luas dan lebih menjanjikan 🌍✨ See you di kelas, dan semoga kita bisa kolaborasi bareng sebagai sesama developer profesional. Semangat! 💪🔥

Kelas VSCode Setup Pemula: Setting Praktis Biar Ngoding Nggak Ribet di BuildWithAngga

VSCode Setup Pemula: Setting Praktis Biar Ngoding Nggak Ribet

Pendahuluan Lo pernah nggak sih, pas baru install VSCode, malah bingung sendiri? Tampilannya rame, banyak tombol yang nggak jelas fungsinya, terus pas lo ngoding juga rasanya berantakan banget. Gua kasih tau, banyak banget programmer pemula yang ngalamin hal sama. Padahal VSCode itu sebenernya powerful banget asal lo tau cara nyetting-nya biar nyaman dan nggak ribet waktu dipake ngoding. Di artikel ini, gua bakal bantu lo setup VSCode dari nol, mulai dari tema yang enak dilihat, ekstensi yang berguna, sampai setting yang bikin workflow lo makin lancar. Semua dibahas simpel, nggak ribet, dan cocok banget buat lo yang baru mulai belajar ngoding. Yuk, gaskeun! Install VSCode dan Bahasa Pemrograman Sebelum ngoding, pastiin dulu lo udah install VSCode dari situs resminya ya. Jangan asal download dari tempat nggak jelas, bahaya! Setelah itu, tinggal install extension yang sesuai bahasa pemrograman yang lo pake. Misalnya, lo mau belajar JavaScript, install extension JavaScript atau ES7 React biar codingan lo makin gampang dan rapi. Gampang banget, kan? Nggak usah ribet dulu, yang penting lo udah siap mulai ngoding. Pilih Tema & Font yang Nyaman Buat ngoding enak dan betah, tampilan VSCode harus nyaman di mata. Nah, tema dan font itu salah satu kunci pentingnya. Nih, gua jelasin beberapa tema dan font yang recommended banget buat lo: Tema VSCode yang Oke Banget One Dark Pro Tema gelap yang terinspirasi dari Atom's One Dark. Warna-warnanya kalem dan nyaman di mata, cocok buat ngoding lama tanpa bikin capek. Paling banyak diunduh di VSCode Marketplace. One Dark Pro Download One Dark Pro Dracula Theme Official Tema gelap dengan warna-warna cerah yang kontras, bikin kode lo gampang dibaca. Dracula juga tersedia di banyak editor lain, jadi kalau lo pindah-pindah editor, tampilannya tetap konsisten. Dracula Theme Official Download Dracula Theme Official GitHub Theme Mau tampilan yang mirip GitHub? Pakai tema ini. Cocok buat lo yang sering ngecek kode di GitHub dan pengen tampilan editor yang familiar. GitHub Theme Download GitHub Theme Catppuccin for VSCode Tema yang lagi hits banget karena warnanya soft dan eye-friendly, cocok buat yang pengen tampilan modern tapi nggak bikin mata cepat lelah. Selain VSCode, Catppuccin juga tersedia untuk banyak aplikasi lain, jadi lo bisa pakai tema yang konsisten di berbagai tools. Catppuccin for VSCode Catppuccin Icons for VSCode Biar makin matching, lo juga bisa install Catppuccin Icons. Ikonnya dibikin sesuai gaya temanya, jadi folder & file lo tampil lebih konsisten dan estetik. Catppuccin Icons for VSCode Font Coding yang Bikin Ngoding Lebih Nyaman Fira Code Font monospaced yang support ligatures, jadi karakter-karakter tertentu digabung jadi simbol keren kayak => jadi panah. Bikin kode lo lebih rapi dan enak dibaca. Fira Code Download Fira Code JetBrains Mono Font dari JetBrains yang dirancang khusus buat programmer. Tampilan hurufnya jelas dan nyaman, plus support ligatures juga. JetBrains Mono Download JetBrains Mono Cascadia Code Font dari Microsoft yang dirancang buat Windows Terminal dan VSCode. Support ligatures dan tampilannya modern. Cascadia Code Download Cascadia Code Cara Ganti Tema & Font di VSCode Ganti Tema: Tekan Ctrl + Shift + P (Windows/Linux) atau Cmd + Shift + P (Mac).Ketik Preferences: Color Theme.Pilih tema yang udah lo install. Ganti Font: Tekan Ctrl + Shift + P (Windows/Linux) atau Cmd + Shift + P (Mac).Ketik Preferences: Open User Settings (JSON).Tambahkan atau ubah baris berikut: "editor.fontFamily": "JetBrains Mono, Consolas, 'Courier New', monospace", "editor.fontLigatures": true Ganti "JetBrains Mono" dengan nama font yang lo pilih. Dengan tema dan font yang pas, ngoding bakal lebih nyaman dan fokus. Coba deh beberapa pilihan di atas dan pilih yang paling cocok buat lo. Ekstensi Wajib VSCode Biar Ngoding Makin Lancar Prettier – Code Formatter Buat lo yang suka kode rapi tanpa harus ngatur indentasi manual, Prettier adalah penyelamat. Ekstensi ini bakal otomatis ngeformat kode lo sesuai aturan yang lo tentuin. 💡 Cocok buat: HTML, CSS, JavaScript, TypeScript, dll.🔗 Install Prettier Prettier - Code formatter ESLint Kalau lo ngoding pakai JavaScript atau TypeScript, ESLint penting banget buat ngecek kesalahan dan ngasih warning langsung di editor. Bisa dibilang kayak “teman cerewet” yang jagain kode lo tetap bersih. 💡 Cocok buat: JS/TS projects, terutama yang pakai React atau Next.js.🔗 Install ESLint ESLint Auto Rename Tag Nulis HTML atau JSX? Gak usah lagi repot ganti tag buka dan tutup satu per satu. Ekstensi ini otomatis ngeganti tag penutup kalau tag pembukanya lo ubah. 🔗 Install Auto Rename Tag Auto Rename Tag Path Intellisense Males nulis path atau sering typo waktu import file? Ini solusinya. Path Intellisense ngasih auto-complete buat path file di proyek lo. 🔗 Install Path Intellisense Path Intellisense Live Server Buat lo yang ngoding pakai HTML dan pengen lihat perubahan langsung di browser tanpa reload manual, ini ekstensi andalan. Sekali klik, langsung jalan! 🔗 Install Live Server Liive Server GitLens - Git supercharged Kalau lo kerja pakai Git, ekstensi ini bakal bantu banget. Bisa liat siapa yang ngedit baris tertentu, kapan, dan bisa ngebandingin versi sebelumnya dengan gampang. 🔗 Install GitLens GitLens - Git supercharged Tips Tambahan Biar Produktif di VSCode Aktifin auto save: biar gak lupa save tiap kali ngoding.Gunakan zen mode (Ctrl + K Z) biar tampilan fokus tanpa gangguan.Coba split editor buat buka 2 file sekaligus. Gampang bandingin atau salin kode.Tambahin shortcut sesuai workflow lo di keyboard shortcuts. Gimana, udah mulai kebayang kan gimana enaknya ngoding kalo VSCode lo udah di-setup dengan rapi? Tinggal install yang perlu, custom dikit, dan siap gas proyek-proyek keren lo. Bonus: Buat Tampilan VSCode Jadi Lebih Clean Udah install tema & ekstensi, tapi pengen tampilannya makin minimalis dan gak ganggu fokus? Nih beberapa tips tambahan biar VSCode lo makin clean: 📁 File & Format "files.trimTrailingWhitespace": true, Otomatis hapus spasi kosong di akhir baris pas file disimpan. Bikin file lo bersih dari "sampah tak terlihat". "files.associations": { "*.css": "tailwindcss" } Semua file .css bakal diperlakukan kayak file TailwindCSS, jadi lo dapet auto-complete dan highlight Tailwind. ✍️ Font & Formatting "editor.fontFamily": "JetBrains Mono, 'Hack Nerd Font', monospace", Nentuin font utama di editor. Kombinasi ini clean dan dukung nerd-font icon. "editor.fontLigatures": true, Aktifin ligature, jadi simbol kayak !==, =>, dll tampil lebih rapi dan keren. "editor.formatOnSave": true, Format otomatis setiap kali save. Gak perlu pencet Shift+Alt+F lagi. "editor.defaultFormatter": "esbenp.prettier-vscode", Gunain Prettier buat auto-format kode. Standar banget buat project modern. 🔍 Tampilan Editor "window.zoomLevel": 2, Perbesar tampilan VSCode biar lebih enak dibaca (zoom 200%). "editor.fontSize": 14, "editor.lineHeight": 24, Ukuran teks & tinggi baris. Kombinasi ini bikin teks padat tapi tetap nyaman. "editor.autoClosingBrackets": "languageDefined", VSCode otomatis nutup tanda kurung/kurawal sesuai bahasa pemrograman. "editor.quickSuggestions": { "other": "off", "comments": "off", "strings": "off" } Matikan auto-suggest di komentar/string supaya gak ganggu. "editor.wordWrap": "on", Otomatis wrap teks panjang biar gak horizontal scroll. "editor.cursorStyle": "line-thin", "editor.cursorWidth": 5, "editor.cursorBlinking": "smooth", "editor.cursorSmoothCaretAnimation": "on", Atur gaya kursor: tipis, halus, dan animasi smooth. Lebih clean & modern. "editor.tabCompletion": "on", "editor.snippetSuggestions": "top", "emmet.triggerExpansionOnTab": true, Aktifin auto-complete pake Tab, snippet muncul di atas, dan Emmet bisa di-trigger dengan Tab (buat HTML/CSS). Bagian: Clean Look "workbench.statusBar.visible": false, "editor.minimap.enabled": false, "breadcrumbs.enabled": true, "breadcrumbs.filePath": "off", "workbench.activityBar.location": "hidden", "editor.guides.indentation": false, Sembunyiin status bar, minimap, dan activity bar. Breadcrumbs tetap nyala tapi file path disembunyiin. Tampilan jadi bersih. "editor.scrollbar.verticalScrollbarSize": 0, "editor.scrollbar.horizontalScrollbarSize": 2, "editor.scrollbar.vertical": "hidden", "editor.scrollbar.horizontal": "hidden", Scrollbar disembunyiin (atau super tipis). Super clean! "editor.renderLineHighlight": "none", "editor.glyphMargin": false, "editor.lineNumbers": "off", "editor.showFoldingControls": "mouseover", "editor.padding.bottom": 2, "editor.padding.top": 2, Nonaktifin highlight line aktif, sembunyiin line number, dan atur padding editor. Hasilnya: minimalis banget. 💻 Clean Look "workbench.statusBar.visible": false, "editor.minimap.enabled": false, "breadcrumbs.enabled": true, "breadcrumbs.filePath": "off", "workbench.activityBar.location": "hidden", "editor.guides.indentation": false, Sembunyiin status bar, minimap, dan activity bar. Breadcrumbs tetap nyala tapi file path disembunyiin. Tampilan jadi bersih. "editor.scrollbar.verticalScrollbarSize": 0, "editor.scrollbar.horizontalScrollbarSize": 2, "editor.scrollbar.vertical": "hidden", "editor.scrollbar.horizontal": "hidden", Scrollbar disembunyiin (atau super tipis). Super clean! "editor.renderLineHighlight": "none", "editor.glyphMargin": false, "editor.lineNumbers": "off", "editor.showFoldingControls": "mouseover", "editor.padding.bottom": 2, "editor.padding.top": 2, Nonaktifin highlight line aktif, sembunyiin line number, dan atur padding editor. Hasilnya: minimalis banget. 📂 Explorer & Sidebar "workbench.sideBar.location": "right", "explorer.confirmDragAndDrop": false, "explorer.confirmDelete": false, "workbench.tree.enableStickyScroll": false, "catppuccin-icons.hidesExplorerArrows": true, Sidebar pindah ke kanan, matiin semua konfirmasi explorer, dan sembunyiin panah folder. Simpel & cepat akses. 🧱 UI Tambahan & Tab "window.density.editorTabHeight": "compact", "workbench.layoutControl.type": "menu", "window.commandCenter": false, "workbench.editor.editorActionsLocation": "hidden", "workbench.editor.showTabs": "single", "editor.scrollBeyondLastLine": false, "editor.hideCursorInOverviewRuler": true, "editor.stickyScroll.enabled": false, "window.customTitleBarVisibility": "never", "window.titleBarStyle": "custom", "window.menuBarVisibility": "hidden", "window.newWindowDimensions": "inherit", "window.nativeFullScreen": true, Semua UI disederhanain: tab height kecil, menu & command center disembunyiin, full-screen native, dll. Fokus full ke coding. 🎨 Tema & Icon "workbench.colorTheme": "Catppuccin Frappé", "workbench.iconTheme": "catppuccin-frappe", "workbench.tree.indent": 10, "workbench.tree.renderIndentGuides": "none", "explorer.decorations.colors": false, Aktifin tema Catppuccin Frappé (warna lembut), ikon juga dari Catppuccin, dan tampilan explorer dibuat bersih tanpa garis indentasi atau warna folder. 🔁 Settings Cycler "settings.cycle": [ { "id": "lineNumbers", "values": [ { "editor.lineNumbers": "off" }, { "editor.lineNumbers": "on" } ] } ], "workbench.layoutControl.enabled": false, Bisa toggle line number pake shortcut (kalau install Settings Cycler). Asik buat switching visual style. 🧬 Git "git.confirmSync": false, "git.enableSmartCommit": true, Auto sync Git tanpa konfirmasi & commit langsung tanpa ketik pesan kalau cuma satu file. 🔍 Search & Exclude "search.useIgnoreFiles": true, "search.exclude": { "**/vendor/{[^l],?[^ai]}*": true, "**/public/{[^i],?[^n]}*": true, "**/node_modules": true, "**/dist": true, "**/_ide_helper.php": true, "**/composer.lock": true, "**/package-lock.json": true, "storage": true, ".phpunit.result.cache": true } Search exclude semua folder sampah biar pencarian bersih. Tapi tetep nyisain folder penting kayak laravel, livewire, index.php, dll. 🖥️ Terminal "terminal.integrated.fontLigatures.enabled": true, "terminal.integrated.fontFamily": "JetBrains Mono, 'Hack Nerd Font', Monospace", Terminal juga dikasih font keren + ligature. Jadi matching sama editor. 🌀 TypeScript Auto Imports "typescript.updateImportsOnFileMove.enabled": "always" Kalau lo mindahin file TypeScript, import-nya langsung auto-update. Gak perlu cari-cari dan benerin manual. Full Kode settings.json { "files.trimTrailingWhitespace": true, "files.associations": { "*.css": "tailwindcss" }, "editor.fontFamily": "JetBrains Mono, 'Hack Nerd Font', monospace", "editor.fontLigatures": true, "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "window.zoomLevel": 2, "editor.fontSize": 14, "editor.lineHeight": 24, "editor.autoClosingBrackets": "languageDefined", "editor.quickSuggestions": { "other": "off", "comments": "off", "strings": "off" }, "editor.wordWrap": "on", "editor.cursorStyle": "line-thin", "editor.cursorWidth": 5, "editor.cursorBlinking": "smooth", "editor.cursorSmoothCaretAnimation": "on", "editor.tabCompletion": "on", "editor.snippetSuggestions": "top", "emmet.triggerExpansionOnTab": true, "workbench.statusBar.visible": false, "editor.minimap.enabled": false, "breadcrumbs.enabled": true, "breadcrumbs.filePath": "off", "workbench.activityBar.location": "hidden", "editor.guides.indentation": false, "editor.scrollbar.verticalScrollbarSize": 0, "editor.scrollbar.horizontalScrollbarSize": 2, "editor.scrollbar.vertical": "hidden", "editor.scrollbar.horizontal": "hidden", "editor.renderLineHighlight": "none", "editor.glyphMargin": false, "editor.lineNumbers": "off", "editor.showFoldingControls": "mouseover", "editor.padding.bottom": 2, "editor.padding.top": 2, "workbench.sideBar.location": "right", "explorer.confirmDragAndDrop": false, "explorer.confirmDelete": false, "workbench.tree.enableStickyScroll": false, "catppuccin-icons.hidesExplorerArrows": true, "window.density.editorTabHeight": "compact", "workbench.layoutControl.type": "menu", "window.commandCenter": false, "workbench.editor.editorActionsLocation": "hidden", "workbench.editor.showTabs": "single", "editor.scrollBeyondLastLine": false, "editor.hideCursorInOverviewRuler": true, "editor.stickyScroll.enabled": false, "window.customTitleBarVisibility": "never", "window.titleBarStyle": "custom", "window.menuBarVisibility": "hidden", "window.newWindowDimensions": "inherit", "window.nativeFullScreen": true, "workbench.colorTheme": "Catppuccin Frappé", "workbench.iconTheme": "catppuccin-frappe", "workbench.tree.indent": 10, "workbench.tree.renderIndentGuides": "none", "explorer.decorations.colors": false, "settings.cycle": [ { "id": "lineNumbers", "values": [ { "editor.lineNumbers": "off" }, { "editor.lineNumbers": "on" } ] } ], "workbench.layoutControl.enabled": false, "git.confirmSync": false, "git.enableSmartCommit": true, "search.useIgnoreFiles": true, "search.exclude": { "**/vendor/{[^l],?[^ai]}*": true, "**/public/{[^i],?[^n]}*": true, "**/node_modules": true, "**/dist": true, "**/_ide_helper.php": true, "**/composer.lock": true, "**/package-lock.json": true, "storage": true, ".phpunit.result.cache": true }, "terminal.integrated.fontLigatures.enabled": true, "terminal.integrated.fontFamily": "JetBrains Mono, 'Hack Nerd Font', Monospace", "typescript.updateImportsOnFileMove.enabled": "always" } Maka tampilan VSCode lo akan seperti ini: VSCode Clean UI Penutup Jadi gimana? VSCode lo sekarang udah makin kece, bersih, dan pastinya lebih enak dipake buat ngoding, kan? Dengan setup yang simpel tapi efektif ini, lo nggak cuma bikin editor jadi enak dipandang, tapi juga ngebantu banget ningkatin fokus dan produktivitas pas ngoding. Gue ngerti banget, ngoding kadang bisa bikin mumet, apalagi kalau tampilannya berantakan atau fitur-fitur nggak dimaksimalkan. Makanya, jangan anggap remeh soal setup VSCode karena ini bisa jadi senjata utama lo biar makin enjoy dan efisien pas ngoding. 🎓 Rekomendasi Kelas Gratis dari BuildWithAngga Biar makin mantap dan nggak cuma jago setting VSCode doang, nih gue kasih beberapa kelas keren dari BuildWithAngga yang bisa bantu lo upgrade skill: 🔥 Adonis JavaScript Framework: Basic Web Development Cocok banget buat lo yang pengen nyobain fullstack development dengan JavaScript. Setelah VSCode lo kece, tinggal gas ngoding backend pakai Adonis!✅ Vanilla JavaScript OOP + LocalStorage: Web Task Management Pas banget buat yang pengen belajar bikin aplikasi to-do list dari nol. Kelas ini ngajarin OOP pake JavaScript murni, jadi lo bisa ngerti konsep dasarnya sebelum loncat ke framework.💸 Mastering Laravel: Bikin Web Seperti Saweria Buat lo yang suka Laravel, kelas ini bisa ngebuka wawasan lo lebih dalam lagi. Materinya real project banget, dan VSCode setup kita tadi juga cocok banget buat Laravel dev. Kalau setup lo udah rapi, tinggal tambahin ilmunya lewat kelas-kelas di atas. Belajar makin semangat, produktivitas naik, dan ngoding nggak ribet lagi. Jangan lupa share artikel ini ke temen lo yang VSCode-nya masih “default banget” biar sama-sama upgrade workspace mereka juga! Selamat ngoding, dan semoga makin jago tiap harinya. 🚀👨‍💻