NodeJS #24: Proyek Mini – Membuat Aplikasi Catatan Sederhana


🍭 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 readNotes membaca file JSON dan mengembalikan array. Jika file belum ada, dibuat otomatis.
  • writeNotes menulis 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.body berisi data dari form berkat middleware express.urlencoded().
  • ID dibuat dari timestamp saat ini (angka milidetik) sehingga unik.
  • createdAt diformat 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.

💡 Catatan: Setiap kali aplikasi dijalankan ulang, data tetap ada karena tersimpan di file 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-html jika 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 start di package.json: "start": "node app.js".
  • Membuat file .gitignore (masukkan node_modules dan .env).
  • Push ke GitHub, lalu deploy.

🧪 Latihan Mandiri

  1. Tambahkan fitur edit catatan (buat route GET /edit/:id untuk menampilkan form dengan data lama, dan route POST /edit/:id untuk menyimpan perubahan).
  2. Tambahkan filter atau pencarian catatan berdasarkan judul.
  3. Gunakan Bootstrap untuk tampilan yang lebih profesional.
  4. 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.

Lebih baru Lebih lama

نموذج الاتصال