🍭 NodeJS #24: Proyek Mini – Membuat Aplikasi Catatan Sederhana
Halo, calon full-stack developer! 👋
Selamat! Kamu sudah melewati 23 tutorial dan mempelajari banyak hal: JavaScript dasar, Express, routing, middleware, EJS, API, penyimpanan file JSON, dan bahkan deployment. Sekarang saatnya kita menggabungkan semua materi itu dalam satu proyek mini: Aplikasi Catatan Sederhana (Simple Notes App).
Dengan aplikasi ini, pengguna bisa:
- 📋 Melihat daftar catatan yang sudah dibuat.
- ➕ Menambah catatan baru melalui form.
- 🗑️ Menghapus catatan (opsional, kita akan buat juga).
Kita akan menyimpan data catatan di file JSON, menampilkannya dengan EJS, dan membuat form untuk menambah data. Semua akan kita buat dari nol, langkah demi langkah. Yuk, mulai! 🚀
📁 Persiapan Proyek
Buat folder baru bernama notes-app. Buka terminal di folder tersebut dan jalankan:
npm init -y
npm install express ejs
Sekarang buat struktur folder seperti ini:
notes-app/
├── data/
│ └── notes.json
├── views/
│ ├── index.ejs
│ └── add.ejs
├── public/
│ └── css/
│ └── style.css (opsional)
├── app.js
└── package.json
Buat file data/notes.json dan isi dengan array kosong []. File ini akan menyimpan catatan-catatan kita.
📝 Membuat Server dan Konfigurasi
Buka app.js dan tulis kode dasar berikut:
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const port = process.env.PORT || 3000;
// Set view engine
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// Middleware
app.use(express.urlencoded({ extended: true })); // untuk membaca data form
app.use(express.json()); // untuk JSON (kalau ada API)
app.use(express.static(path.join(__dirname, 'public')));
// Path file data
const dataFile = path.join(__dirname, 'data', 'notes.json');
// Fungsi baca data
function readNotes() {
try {
const data = fs.readFileSync(dataFile, 'utf8');
return JSON.parse(data);
} catch (err) {
// Jika file belum ada, buat file dengan array kosong
if (err.code === 'ENOENT') {
fs.writeFileSync(dataFile, '[]');
return [];
}
console.error(err);
return [];
}
}
// Fungsi tulis data
function writeNotes(notes) {
fs.writeFileSync(dataFile, JSON.stringify(notes, null, 2));
}
app.listen(port, () => {
console.log(`Aplikasi catatan berjalan di http://localhost:${port}`);
});
Penjelasan:
express.urlencoded({ extended: true })diperlukan untuk membaca data dari form biasa (method POST).- Fungsi
readNotesmembaca file JSON dan mengembalikan array. Jika file belum ada, dibuat otomatis. writeNotesmenulis array ke file JSON dengan format rapi.
🏠 Route Utama: Menampilkan Semua Catatan
Tambahkan route berikut sebelum app.listen:
// Halaman utama: daftar catatan
app.get('/', (req, res) => {
const notes = readNotes();
res.render('index', { notes });
});
Sekarang buat file views/index.ejs:
<!DOCTYPE html>
<html>
<head>
<title>Catatan Saya</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<h1>📒 Aplikasi Catatan Sederhana</h1>
<a href="/add" class="btn">➕ Tambah Catatan</a>
<% if (notes.length === 0) { %>
<p>Belum ada catatan. Yuk, buat catatan pertama! 😊</p>
<% } else { %>
<div class="notes-container">
<% notes.forEach(note => { %>
<div class="note-card">
<h3><%= note.title %></h3>
<p><%= note.content %></p>
<small>Dibuat: <%= note.createdAt %></small>
<form action="/delete/<%= note.id %>" method="POST" style="margin-top: 10px;">
<button type="submit" class="btn-delete" onclick="return confirm('Yakin ingin menghapus?')">Hapus</button>
</form>
</div>
<% }); %>
</div>
<% } %>
</body>
</html>
Buat file CSS sederhana di public/css/style.css untuk mempercantik tampilan:
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background: #f4f4f4;
}
h1 {
color: #333;
text-align: center;
}
a.btn {
display: inline-block;
background: #9b59b6;
color: white;
padding: 10px 15px;
text-decoration: none;
border-radius: 5px;
margin-bottom: 20px;
}
a.btn:hover {
background: #8e44ad;
}
.notes-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.note-card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
padding: 15px;
width: calc(33% - 20px);
min-width: 200px;
}
.note-card h3 {
margin-top: 0;
color: #9b59b6;
}
.note-card small {
color: #777;
font-size: 0.8em;
}
.btn-delete {
background: #e74c3c;
color: white;
border: none;
padding: 5px 10px;
border-radius: 3px;
cursor: pointer;
}
.btn-delete:hover {
background: #c0392b;
}
➕ Route Tambah Catatan (Tampilkan Form)
Buat route GET untuk menampilkan form tambah catatan:
// Halaman tambah catatan
app.get('/add', (req, res) => {
res.render('add');
});
Buat file views/add.ejs:
<!DOCTYPE html>
<html>
<head>
<title>Tambah Catatan</title>
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<h1>➕ Tambah Catatan Baru</h1>
<form action="/add" method="POST">
<div>
<label>Judul:</label><br>
<input type="text" name="title" required>
</div>
<div>
<label>Isi Catatan:</label><br>
<textarea name="content" rows="5" required></textarea>
</div>
<button type="submit" class="btn">Simpan</button>
</form>
<p><a href="/">← Kembali ke Daftar</a></p>
</body>
</html>
Tambahkan sedikit CSS tambahan untuk form di style.css:
input[type="text"], textarea {
width: 100%;
padding: 8px;
margin: 10px 0;
border: 1px solid #ddd;
border-radius: 4px;
}
button.btn {
background: #9b59b6;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
button.btn:hover {
background: #8e44ad;
}
📥 Route POST untuk Menyimpan Catatan
Sekarang kita buat route POST untuk menerima data dari form dan menyimpannya ke file JSON.
// Proses tambah catatan
app.post('/add', (req, res) => {
const { title, content } = req.body;
// Validasi sederhana
if (!title || !content) {
return res.status(400).send('Judul dan isi catatan harus diisi.');
}
const notes = readNotes();
// Buat ID baru (menggunakan timestamp agar unik)
const newNote = {
id: Date.now(),
title: title,
content: content,
createdAt: new Date().toLocaleString('id-ID', { dateStyle: 'medium', timeStyle: 'short' })
};
notes.push(newNote);
writeNotes(notes);
res.redirect('/'); // kembali ke halaman utama
});
Penjelasan:
req.bodyberisi data dari form berkat middlewareexpress.urlencoded().- ID dibuat dari timestamp saat ini (angka milidetik) sehingga unik.
createdAtdiformat agar lebih manusiawi.- Setelah menyimpan, kita redirect ke halaman utama.
🗑️ Route Hapus Catatan (Opsional)
Tambahkan juga fitur hapus agar aplikasi lebih lengkap.
// Hapus catatan berdasarkan ID
app.post('/delete/:id', (req, res) => {
const id = parseInt(req.params.id);
let notes = readNotes();
notes = notes.filter(note => note.id !== id);
writeNotes(notes);
res.redirect('/');
});
Perhatikan kita menggunakan method POST untuk menghapus (bukan DELETE) karena form biasa hanya mendukung GET dan POST. Ini adalah praktik umum untuk menghindari penghapusan melalui tautan langsung.
🧪 Uji Coba
Jalankan aplikasi dengan perintah:
node app.js
Buka browser ke http://localhost:3000. Kamu akan melihat halaman kosong (karena belum ada catatan). Klik "Tambah Catatan", isi judul dan isi, lalu simpan. Catatan akan muncul di halaman utama. Coba tambah beberapa catatan, lalu hapus salah satu. Semua data tersimpan di file data/notes.json.
📂 Menambahkan Validasi dan Keamanan
Untuk pembelajaran, kita bisa menambahkan beberapa validasi:
- Pastikan judul dan isi tidak kosong (sudah dilakukan).
- Batasi panjang judul dan isi.
- Bersihkan input dari HTML berbahaya (gunakan package seperti
sanitize-htmljika perlu).
🧩 Menggunakan API (Opsional)
Kita juga bisa menambahkan endpoint API untuk mengambil data catatan dalam format JSON. Misalnya:
// API: ambil semua catatan
app.get('/api/notes', (req, res) => {
const notes = readNotes();
res.json(notes);
});
Ini bisa digunakan jika nanti kita buat frontend terpisah (misal dengan React).
🚀 Mendeploy Aplikasi
Aplikasi ini siap dideploy ke platform seperti Render, Cyclic, atau Azure. Jangan lupa untuk:
- Menggunakan
process.env.PORT(sudah kita lakukan). - Menambahkan script
startdipackage.json:"start": "node app.js". - Membuat file
.gitignore(masukkannode_modulesdan.env). - Push ke GitHub, lalu deploy.
🧪 Latihan Mandiri
- Tambahkan fitur edit catatan (buat route GET
/edit/:iduntuk menampilkan form dengan data lama, dan route POST/edit/:iduntuk menyimpan perubahan). - Tambahkan filter atau pencarian catatan berdasarkan judul.
- Gunakan Bootstrap untuk tampilan yang lebih profesional.
- Ubah penyimpanan dari file JSON ke database (MySQL atau MongoDB).
📚 Rangkuman
Dalam proyek mini ini, kita telah menggabungkan:
- Express.js untuk routing dan server.
- EJS untuk templating halaman.
- Form handling (GET dan POST).
- Membaca dan menulis file JSON sebagai database sederhana.
- Membuat API endpoint (opsional).
- Styling dengan CSS.
Ini adalah fondasi yang kuat untuk membangun aplikasi web yang lebih kompleks. Selamat! Kamu sekarang sudah siap untuk membuat proyek-proyekmu sendiri. 🎉
🏁 Penutup
Terima kasih telah mengikuti seri tutorial Node.js + Express.js ini dari awal hingga akhir. Kamu telah belajar banyak hal, dari dasar JavaScript hingga membuat aplikasi lengkap dan mendeploynya. Jangan berhenti di sini, teruslah bereksperimen dan buatlah proyek-proyek keren lainnya.
Jika ada pertanyaan atau ingin berbagi hasil karyamu, tulis di komentar. Selamat coding! 💻😊
Ditulis dengan ❤️ untuk para pemula yang ingin menjadi programmer handal.