Panduan langkah demi langkah yang jelas untuk membangun aplikasi to-do kecil: rencanakan fitur, buat tampilan, tambahkan logika, simpan data, uji, dan publikasikan.

Saat saya menyebut “app” di panduan ini, yang saya maksud adalah sebuah web app kecil: satu halaman yang Anda buka di browser yang merespons apa yang Anda klik dan ketik. Tidak perlu instalasi, akun, atau setup rumit—hanya proyek kecil yang bisa dijalankan secara lokal.
Pada akhirnya, Anda akan memiliki aplikasi to‑do yang bisa:
localStorage (jadi menutup tab tidak menghapus semuanya)Aplikasinya tidak akan sempurna atau “enterprise-grade”, dan memang itu maksudnya. Ini proyek pemula yang dirancang untuk mengajarkan dasar tanpa memakai banyak alat.
Anda akan membangun aplikasi langkah demi langkah dan mempelajari bagian inti cara kerja front-end web app:
Sederhana saja. Anda cuma butuh:
Jika Anda bisa membuat folder dan mengedit beberapa file, Anda siap.
Sebelum menulis kode apa pun, tentukan seperti apa hasil yang Anda inginkan. Tutorial ini membuat satu aplikasi kecil dengan satu tugas jelas: membantu Anda melacak tugas yang ingin dilakukan.
Tulis satu kalimat tujuan yang bisa Anda pegang selama membangun:
“Aplikasi ini memungkinkan saya menambahkan tugas ke daftar supaya saya tidak lupa.”
Itu saja. Jika Anda tergoda menambahkan kalender, pengingat, tag, atau akun, simpan ide-ide itu untuk nanti.
Buat dua daftar singkat:
Wajib (untuk proyek ini):
Opsional (tidak diperlukan hari ini): tanggal jatuh tempo, prioritas, kategori, pencarian, drag-and-drop, sinkronisasi cloud.
Menjaga bagian “wajib” tetap kecil membantu Anda benar-benar menyelesaikannya.
Aplikasi ini bisa berupa satu halaman dengan:
Jelas supaya Anda tidak bingung:
Dengan itu diputuskan, Anda siap menyiapkan file proyek.
Sebelum menulis kode, buat “rumah” kecil yang rapi untuk aplikasi. Mengatur file dari awal membuat langkah berikutnya lebih mulus.
Buat folder baru di komputer dan beri nama seperti todo-app. Folder ini akan menampung semua untuk proyek ini.
Di dalam folder itu, buat tiga file:
index.html (struktur halaman)styles.css (tampilan dan tata letak)app.js (perilaku dan interaktivitas)Jika komputer Anda menyembunyikan ekstensi file (mis. “.html”), pastikan Anda benar-benar membuat file dengan ekstensi yang benar. Kesalahan umum pemula: berakhir dengan index.html.txt.
Buka folder todo-app di editor kode (VS Code, Sublime Text, dll.). Lalu buka index.html di browser.
Saat ini halaman Anda mungkin kosong—dan itu wajar. Kita akan menambah konten di langkah berikut.
Saat Anda mengedit file, browser tidak akan otomatis memperbarui (kecuali Anda menggunakan alat yang melakukan itu).
Jadi loop dasarnya:
Jika sesuatu “tidak bekerja”, refresh adalah hal pertama yang harus dicoba.
Anda bisa membangun aplikasi ini dengan mengklik ganda index.html, tetapi server lokal bisa mencegah masalah aneh nanti (terutama saat mulai menyimpan data atau memuat file).
Pilihan ramah pemula:
python -m http.server
Kemudian buka alamat yang dicetak (sering http://localhost:8000) di browser.
Sekarang kita akan membuat kerangka bersih untuk aplikasi. HTML ini belum membuat sesuatu menjadi interaktif (itu langkah berikutnya), tapi memberi JavaScript tempat yang jelas untuk membaca dan menulis.
Kita akan menyertakan:
Gunakan nama yang sederhana dan mudah dibaca. ID/class yang baik membuat langkah berikutnya lebih mudah karena JavaScript bisa mengambil elemen berdasarkan nama tanpa kebingungan.
index.html Anda<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>To‑Do App</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<main class="app" id="app">
<h1 class="app__title" id="appTitle">My To‑Do List</h1>
<form class="task-form" id="taskForm">
<label class="task-form__label" for="taskInput">New task</label>
<div =>
Add
Itu saja untuk struktur. Perhatikan kita menggunakan id="taskInput" dan id="taskList"—itu dua elemen yang akan sering Anda gunakan di JavaScript.
Saat ini halaman Anda ada, tetapi mungkin terlihat polos. Sedikit CSS membuatnya lebih mudah dipakai: jarak, teks yang terbaca, dan tombol yang terasa bisa diklik.
Kotak yang dipusatkan menjaga fokus aplikasi dan mencegah konten melebar di layar lebar.
/* Basic page setup */
body {
font-family: Arial, sans-serif;
background: #f6f7fb;
margin: 0;
padding: 24px;
}
/* Centered app container */
.container {
max-width: 520px;
margin: 0 auto;
background: #ffffff;
padding: 16px;
border-radius: 10px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
}
Setiap tugas harus terlihat seperti “baris” terpisah, dengan jarak yang nyaman.
ul { list-style: none; padding: 0; margin: 16px 0 0; }
li {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 12px;
border: 1px solid #e7e7ee;
border-radius: 8px;
margin-bottom: 10px;
}
.task-text { flex: 1; }
Saat tugas selesai, tampilannya harus berubah supaya Anda tahu sekilas.
.done .task-text {
text-decoration: line-through;
color: #777;
opacity: 0.85;
}
Jaga semua tombol agar sama ukuran dan gaya sehingga terasa seperti bagian dari satu aplikasi.
button {
border: none;
border-radius: 8px;
padding: 8px 10px;
cursor: pointer;
}
button:hover { filter: brightness(0.95); }
Itu cukup styling untuk UI yang bersih dan ramah—tidak perlu trik lanjutan. Selanjutnya, kita akan menghubungkan perilaku dengan JavaScript.
Sekarang Anda mempunyai input, tombol, dan daftar di halaman, saatnya membuatnya berguna. Tujuannya sederhana: ketika seseorang mengetik tugas dan menekan Add (atau menekan Enter), item baru muncul di daftar.
Di file JavaScript Anda, ambil dulu elemen yang dibutuhkan, lalu dengarkan dua aksi: klik tombol dan tombol Enter di dalam input.
const taskInput = document.querySelector('#taskInput');
const addBtn = document.querySelector('#addBtn');
const taskList = document.querySelector('#taskList');
function addTask() {
const text = taskInput.value.trim();
// Block empty tasks (including ones that are just spaces)
if (text === '') return;
const li = document.createElement('li');
li.textContent = text;
taskList.appendChild(li);
// Clear the input and put the cursor back
taskInput.value = '';
taskInput.focus();
}
addBtn.addEventListener('click', addTask);
taskInput.addEventListener('keydown', (event) => {
if (event.key === 'Enter') {
addTask();
}
});
trim() untuk menghapus spasi ekstra di awal/akhir.\u003cli\u003e baru, mengisi teksnya, dan menambahkannya ke daftar.Jika tidak terjadi apa-apa, periksa kembali bahwa ID elemen di HTML cocok persis dengan selector di JavaScript (ini salah satu masalah umum pemula).
Setelah Anda bisa menambahkan tugas, buat mereka bisa diambil tindakan: Anda harus bisa menandai tugas selesai dan menghapusnya.
Alih-alih menyimpan tugas sebagai string, simpan sebagai objek. Itu memberi setiap tugas identitas yang stabil dan tempat untuk menyimpan status “done”:
text: isi tugasdone: true atau falseid: angka unik supaya kita bisa menemukan/menghapus tugas yang benarContoh sederhana:
let tasks = [
{ id: 1, text: "Buy milk", done: false },
{ id: 2, text: "Email Sam", done: true }
];
Saat Anda merender setiap tugas di halaman, sertakan checkbox atau tombol “Done”, plus tombol “Delete”.
Listener peristiwa adalah cara untuk merespons klik. Anda menempelkannya ke tombol (atau seluruh daftar), dan saat pengguna klik, kode Anda berjalan.
Polanya yang ramah pemula adalah event delegation: pasang satu listener klik pada kontainer daftar, lalu periksa elemen mana yang diklik.
function toggleDone(id) {
tasks = tasks.map(t => t.id === id ? { ...t, done: !t.done } : t);
renderTasks();
}
function deleteTask(id) {
tasks = tasks.filter(t => t.id !== id);
renderTasks();
}
document.querySelector("#taskList").addEventListener("click", (e) => {
const id = Number(e.target.dataset.id);
if (e.target.matches(".toggle")) toggleDone(id);
if (e.target.matches(".delete")) deleteTask(id);
});
Di fungsi renderTasks() Anda:
data-id="${task.id}" ke setiap tombol..done).Sekarang daftar to‑do Anda punya masalah: jika Anda refresh halaman (atau menutup tab), semuanya hilang.
Itu terjadi karena tugas hanya ada di memori JavaScript. Ketika halaman dimuat ulang, memori itu di-reset.
localStorage sudah ada di browser. Anggap ini seperti kotak kecil tempat Anda bisa menyimpan teks dengan nama (sebuah “key”). Cocok untuk proyek pemula karena tidak perlu server atau akun.
Kita akan menyimpan seluruh daftar tugas sebagai teks JSON, lalu memuatnya lagi saat halaman dibuka.
Setiap kali Anda menambah tugas, menandai selesai, atau menghapus, panggil saveTasks().
const STORAGE_KEY = "todo.tasks";
function saveTasks(tasks) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(tasks));
}
Di mana pun aplikasi Anda memperbarui array tasks, lakukan ini segera setelahnya:
saveTasks(tasks);
renderTasks(tasks);
Saat halaman dimuat, baca nilai yang tersimpan. Jika belum ada apa-apa, gunakan daftar kosong sebagai cadangan.
function loadTasks() {
const saved = localStorage.getItem(STORAGE_KEY);
return saved ? JSON.parse(saved) : [];
}
let tasks = loadTasks();
renderTasks(tasks);
Selesai: aplikasi Anda sekarang mengingat tugas setelah refresh.
Tip: localStorage hanya menyimpan string, jadi JSON.stringify() mengubah array jadi teks, dan JSON.parse() mengubahnya kembali menjadi array saat dimuat.
Pengujian terdengar membosankan, tapi ini cara tercepat mengubah aplikasi to‑do Anda dari “bekerja di mesin saya” menjadi “bekerja setiap saat.” Lakukan satu pemeriksaan cepat setiap kali Anda membuat perubahan kecil.
Jalankan alur utama dengan urutan ini:
Jika ada langkah yang gagal, perbaiki sebelum menambah fitur baru. Aplikasi kecil jadi berantakan saat Anda menumpuk masalah.
Kasus tepi adalah input yang tidak Anda rancang, tetapi orang nyata akan lakukan:
Perbaikan umum adalah memblokir tugas kosong:
const text = input.value.trim();
addButton.disabled = text === "";
(Jalankan itu pada setiap event input, dan sekali lagi tepat sebelum menambah.)
Saat klik tidak bereaksi, biasanya salah satu ini:
id atau class berbeda antara HTML dan JS).app.js tidak ditemukan).Saat sesuatu terasa acak, log saja:
console.log("Adding:", text);
console.log("Current tasks:", tasks);
Periksa Console di browser untuk error (teks merah). Setelah Anda memperbaiki masalah, hapus log agar tidak mengacaukan proyek.
Aplikasi to‑do baru dianggap “selesai” ketika nyaman dipakai orang nyata—di ponsel, dengan keyboard, dan dengan alat bantu seperti screen reader.
Di layar kecil, tombol kecil membuat frustasi. Beri elemen yang bisa diklik ruang yang cukup:
Jika pakai CSS, menambah padding, font-size, dan gap sering memberikan perbedaan besar.
Screen reader butuh nama yang jelas untuk kontrol.
\u003clabel\u003e nyata (opsi terbaik). Jika tidak ingin ditampilkan, Anda bisa menyembunyikannya secara visual dengan CSS, tapi tetap pertahankan di HTML.aria-label="Delete task" sehingga screen reader tidak mengatakan “button” tanpa konteks.Ini membantu orang memahami fungsi setiap kontrol tanpa menebak.
Pastikan Anda bisa menggunakan seluruh aplikasi tanpa mouse:
\u003cform\u003e supaya Enter bekerja alami).Gunakan ukuran font yang mudah dibaca (16px adalah baseline yang baik) dan kontras warna kuat (teks gelap di latar terang, atau sebaliknya). Hindari menggunakan warna saja untuk menandai “selesai”—tambahkan gaya jelas seperti coret plus status “Done”.
Setelah semuanya bekerja, luangkan 10–15 menit untuk merapikan. Ini memudahkan perbaikan di masa depan dan membantu Anda memahami proyek saat kembali nanti.
Jaga tetap kecil dan dapat diprediksi:
/index.html — struktur halaman (input, tombol, daftar)/styles.css — tampilan (jarak, font, gaya “done”)/app.js — perilaku (tambah, toggle done, hapus, simpan/muat)/README.md — catatan singkat untuk “anda di masa depan"Jika Anda suka subfolder, bisa juga:
/css/styles.css/js/app.jsPastikan \u003clink\u003e dan \u003cscript\u003e path sesuai.
Beberapa perbaikan cepat:
taskInput, taskList, saveTasks()Contoh mudah dibaca:
renderTasks(tasks)addTask(text)toggleTask(id)deleteTask(id)README.md Anda bisa sederhana:
index.html di browser)Minimal, zip folder setelah menyelesaikan milestone (mis. “localStorage bekerja”). Jika mau riwayat versi, Git sangat berguna—tetapi opsional. Bahkan satu salinan cadangan bisa menyelamatkan dari penghapusan tidak sengaja.
Mempublikasikan artinya menaruh file aplikasi (HTML, CSS, JavaScript) di internet agar orang lain bisa membuka link dan menggunakannya. Karena aplikasi to‑do ini adalah “static site” (jalan di browser dan tidak butuh server), Anda bisa meng-host gratis di beberapa layanan.
Langkah umum:
Jika aplikasi menggunakan file terpisah, periksa nama file agar cocok dengan tautan (mis. styles.css vs style.css).
Jika Anda mau cara paling sederhana “unggah dan jalan”:
localStorage bekerja).Jika semua lolos, kirim link ke teman dan minta mereka mencoba—mata baru cepat menemukan masalah.
Anda telah membuat aplikasi to‑do yang bekerja. Kalau ingin terus belajar tanpa lompat ke proyek besar, peningkatan ini menambah nilai nyata dan mengajarkan pola berguna.
Tambahkan tombol “Edit” di samping setiap tugas. Saat diklik, tukar label tugas menjadi input kecil (terisi awalnya), plus tombol “Save” dan “Cancel.”
Tips: pertahankan data tugas sebagai array objek (dengan id dan text). Edit jadi: temukan tugas dengan id, perbarui text, re-render, dan simpan.
Tambahkan tiga tombol di atas: All, Active, Done.
Simpan filter saat ini di variabel seperti currentFilter = 'all'. Saat merender, tampilkan:
Jaga tetap ringan:
YYYY-MM-DD) dan tampilkan di samping tugasSatu field ekstra mengajarkan bagaimana memperbarui model data dan UI bersama.
Saat siap, ide besarnya: alih-alih menyimpan ke localStorage, Anda kirim tugas ke API (server) menggunakan fetch(). Server menyimpannya di database, sehingga tugas tersinkronisasi antar perangkat.
Jika ingin mencoba lompatan itu tanpa membangun ulang semuanya, platform prototyping bisa membantu Anda membuat versi “berikutnya” cepat: jelaskan fitur di chat (endpoint API, tabel database, perubahan UI), iterasi di mode perencanaan, dan ekspor kode sumber saat siap mempelajari (atau menyesuaikan) proyek React/Go/PostgreSQL yang dihasilkan.
Coba buat notes app (dengan pencarian) atau habit tracker (cek harian). Keduanya memakai kembali keterampilan: rendering daftar, edit, simpan, dan desain UI sederhana.