
Halo teman-teman, selamat datang di seri artikel terbaru di ruanginformatika.com! π
Dalam seri ini, kita akan belajar bareng bagaimana cara membangun aplikasi web fullstack dari nol. Kita akan mulai dari perencanaan, bikin tampilan, ngebangun backend, sampai aplikasi kita bisa online dan diakses semua orang.
Tenang aja, semuanya akan dijelaskan langkah demi langkah dengan gaya santai dan mudah dimengerti, cocok banget buat kamu yang baru mulai belajar fullstack development.
Kita akan bikin aplikasi To-do List dengan fitur login. Jadi user bisa daftar, login, dan membuat daftar tugas harian mereka. Fitur-fitur dasarnya:
Berikut adalah alat-alat utama dalam proyek ini:
Proyek ini akan kita bagi jadi dua folder besar:
/todo-app/ β βββ client/ β Frontend (React + Tailwind) βββ server/ β Backend (Node.js + Express + MongoDB)
Nanti kita akan setup masing-masing bagian dan sambungkan satu sama lain. Di akhir seri, kamu akan punya aplikasi web yang lengkap dan bisa dipamerin di CV atau portofolio! π
Di artikel selanjutnya, kita akan langsung mulai dengan setup frontend menggunakan React dan Tailwind. Kita bakal bikin tampilan awal seperti halaman home, login, dan dashboard.
Untuk lanjutannya di Bagian 2: Membuat UI Frontend dengan React + Tailwind bisa next page ya! Jangan lupa share artikel ini kalau kamu suka dan mau ngajak teman belajar bareng. π
Halo kembali di seri membangun aplikasi web fullstack bareng ruanginformatika.com! π
Sesuai janji di artikel sebelumnya, kali ini kita akan mulai membangun tampilan depan alias frontend dari aplikasi To-do List kita menggunakan React dan Tailwind CSS.
Kita akan menggunakan Vite karena proses setup-nya cepat dan ringan. Jalankan perintah berikut di terminal kamu:
npm create vite@latest client --template react
Lalu masuk ke folder dan install dependensi:
cd client
npm install
Setelah itu, kamu bisa coba jalankan proyeknya:
npm run dev
Jika berhasil, kamu akan melihat tampilan awal React di browser.
Tailwind CSS akan kita gunakan untuk mempercepat proses styling tanpa harus mikirin file CSS manual.
Install Tailwind dengan perintah:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Edit file tailwind.config.js
jadi seperti ini:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
Lalu di file src/index.css
, ganti isinya dengan:
@tailwind base;
@tailwind components;
@tailwind utilities;
Sekarang kamu bisa pakai class Tailwind langsung di JSX!
Buat beberapa file komponen seperti ini:
src/
βββ components/
β βββ Header.jsx
β βββ TodoItem.jsx
βββ pages/
β βββ Home.jsx
β βββ Login.jsx
β βββ Register.jsx
β βββ Dashboard.jsx
Contoh kode sederhana Header.jsx
:
export default function Header() {
return (
<header className="bg-blue-600 text-white p-4">
<h1 className="text-xl font-bold">To-do App</h1>
</header>
);
}
Lalu tampilkan komponen Header
di App.jsx
.
Install React Router untuk navigasi antar halaman:
npm install react-router-dom
Atur routing di App.jsx
:
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import Login from "./pages/Login";
import Register from "./pages/Register";
import Dashboard from "./pages/Dashboard";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</BrowserRouter>
);
}
export default App;
Sekarang kamu bisa navigasi antar halaman seperti aplikasi beneran!
Sampai di sini, kita sudah berhasil:
Di artikel berikutnya, kita akan mulai membangun bagian backend API menggunakan Express dan MongoDB.
Jangan lupa simpan dan commit proyek kamu ke GitHub ya. Silahkan di next untuk lanjut ke Bagian 3! π₯
Halo sobat ruanginformatika! π
Kita udah selesai bikin tampilan depan aplikasi to-do list pakai React dan Tailwind. Sekarang saatnya kita ngebangun backend-nya menggunakan Node.js + Express, dan tentu aja kita juga bakal sambungin ke database MongoDB.
Masuk ke direktori utama proyek dan buat folder baru untuk server:
mkdir server
cd server
npm init -y
Install dependensi utama:
npm install express mongoose dotenv cors
Tambahkan juga package untuk development:
npm install --save-dev nodemon
Edit file package.json
dan tambahkan script:
"scripts": {
"dev": "nodemon index.js"
}
Buat file index.js
di root folder server
:
const express = require('express');
const mongoose = require('mongoose');
const cors = require('cors');
require('dotenv').config();
const app = express();
const PORT = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
app.get('/', (req, res) => {
res.send('API berjalan dengan baik π');
});
mongoose.connect(process.env.MONGO_URI)
.then(() => {
app.listen(PORT, () => {
console.log(`Server jalan di http://localhost:${PORT}`);
});
})
.catch((err) => console.log(err));
Daftar akun di MongoDB Atlas (kalau belum punya), lalu buat cluster gratis dan database baru.
Setelah itu, buat file .env
:
MONGO_URI=isi_dengan_uri_mongodb_kamu
Pastikan file .env
masuk ke .gitignore
agar tidak ke-upload ke GitHub.
Buat folder models
dan file Todo.js
:
const mongoose = require('mongoose');
const todoSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
completed: {
type: Boolean,
default: false
}
}, { timestamps: true });
module.exports = mongoose.model('Todo', todoSchema);
Buat folder routes
dan file todoRoutes.js
:
const express = require('express');
const router = express.Router();
const Todo = require('../models/Todo');
// Ambil semua todo
router.get('/', async (req, res) => {
const todos = await Todo.find();
res.json(todos);
});
// Tambah todo baru
router.post('/', async (req, res) => {
const newTodo = new Todo({ title: req.body.title });
const saved = await newTodo.save();
res.json(saved);
});
// Hapus todo
router.delete('/:id', async (req, res) => {
await Todo.findByIdAndDelete(req.params.id);
res.json({ message: 'Todo dihapus' });
});
// Toggle status selesai
router.put('/:id', async (req, res) => {
const updated = await Todo.findByIdAndUpdate(
req.params.id,
{ completed: req.body.completed },
{ new: true }
);
res.json(updated);
});
module.exports = router;
Lalu import route ini di index.js
:
const todoRoutes = require('./routes/todoRoutes');
app.use('/api/todos', todoRoutes);
Gunakan Postman atau Thunder Client (VS Code extension) untuk mengetes endpoint:
GET /api/todos
POST /api/todos
dengan body: { "title": "Belajar coding" }
DELETE /api/todos/:id
PUT /api/todos/:id
dengan body: { "completed": true }
Sampai di sini, kita sudah:
Di artikel berikutnya, kita akan belajar membuat fitur login & register user menggunakan JWT π.
Jangan lupa push proyek kamu ke GitHub dan simpan baik-baik file .env
-nya. Silahkan next page untuk ke Bagian 4!
Halo teman-teman! π
Di artikel sebelumnya, kita udah bikin backend API untuk CRUD data to-do. Tapi saat ini semua orang bisa akses tanpa login π±. Jadi, di bagian ini kita bakal bikin sistem autentikasi user pakai JWT (JSON Web Token) di Express.
Buat file baru models/User.js
:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true },
password: { type: String, required: true }
}, { timestamps: true });
module.exports = mongoose.model('User', userSchema);
Install dua package penting untuk enkripsi dan token:
npm install bcryptjs jsonwebtoken
Buat file routes/authRoutes.js
:
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const User = require('../models/User');
const router = express.Router();
// Register
router.post('/register', async (req, res) => {
try {
const { email, password } = req.body;
const exist = await User.findOne({ email });
if (exist) return res.status(400).json({ message: 'Email sudah terdaftar' });
const hashed = await bcrypt.hash(password, 10);
const newUser = new User({ email, password: hashed });
await newUser.save();
res.json({ message: 'User berhasil dibuat' });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Login
router.post('/login', async (req, res) => {
try {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user) return res.status(400).json({ message: 'Email tidak ditemukan' });
const match = await bcrypt.compare(password, user.password);
if (!match) return res.status(400).json({ message: 'Password salah' });
const token = jwt.sign({ userId: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' });
res.json({ token });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
module.exports = router;
Tambahkan route ini di index.js
:
const authRoutes = require('./routes/authRoutes');
app.use('/api/auth', authRoutes);
Buat file middleware/authMiddleware.js
:
const jwt = require('jsonwebtoken');
function authMiddleware(req, res, next) {
const token = req.header('Authorization')?.split(' ')[1];
if (!token) return res.status(401).json({ message: 'Token tidak ada' });
try {
const verified = jwt.verify(token, process.env.JWT_SECRET);
req.user = verified;
next();
} catch (err) {
res.status(401).json({ message: 'Token tidak valid' });
}
}
module.exports = authMiddleware;
Di route to-do, import middleware ini dan gunakan:
const auth = require('../middleware/authMiddleware');
router.get('/', auth, async (req, res) => {
// hanya user yang sudah login bisa akses
});
Kamu bisa tes pakai Postman atau Thunder Client:
POST /api/auth/register
β body: { “email”: “tes@mail.com”, “password”: “123456” }POST /api/auth/login
β dapatkan tokenAuthorization: Bearer <token>
saat akses todoJWT_SECRET
di file .env
:JWT_SECRET=rahasia_super_aman
Gunakan string acak dan jangan bagikan token secara sembarangan.
Sekarang kita sudah punya sistem login dan register yang aman! Di artikel selanjutnya, kita akan sambungkan frontend dengan backend supaya user bisa login langsung dari React dan melihat to-do mereka masing-masing.
Sampai ketemu di Bagian 5: Menghubungkan Frontend dan Backend ya! π
Halo sobat ruanginformatika! π
Sekarang kita sudah punya frontend dan backend yang masing-masing berjalan sendiri. Saatnya kita sambungkan keduanya agar user bisa login, melihat todo miliknya, dan mengelola data lewat UI React.
Agar request ke server backend lebih simpel, tambahkan proxy
di file client/package.json
:
"proxy": "http://localhost:5000",
Buat komponen Login.jsx
dan Register.jsx
di folder client/src/pages
:
Contoh: Register.jsx
import { useState } from 'react';
import axios from 'axios';
function Register() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleRegister = async (e) => {
e.preventDefault();
try {
await axios.post('/api/auth/register', { email, password });
alert('Registrasi berhasil! Silakan login.');
} catch (err) {
alert(err.response.data.message || 'Registrasi gagal');
}
};
return (
<form onSubmit={handleRegister}>
<input type="email" value={email} onChange={e => setEmail(e.target.value)} placeholder="Email" />
<input type="password" value={password} onChange={e => setPassword(e.target.value)} placeholder="Password" />
<button type="submit">Daftar</button>
</form>
);
}
export default Register;
Saat login berhasil, simpan token ke localStorage
:
const res = await axios.post('/api/auth/login', { email, password });
localStorage.setItem('token', res.data.token);
Buat instance axios dengan token:
const token = localStorage.getItem('token');
const api = axios.create({
baseURL: '/',
headers: {
Authorization: `Bearer ${token}`
}
});
Gunakan instance api
untuk ambil to-do:
useEffect(() => {
api.get('/api/todos')
.then(res => setTodos(res.data))
.catch(err => {
if (err.response.status === 401) {
alert('Silakan login terlebih dahulu');
}
});
}, []);
Gunakan react-router-dom
untuk navigasi antar halaman:
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Login from './pages/Login';
import Register from './pages/Register';
import Home from './pages/Home';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</BrowserRouter>
);
}
export default App;
Di bagian ini, kita berhasil menghubungkan frontend dan backend dengan alur:
Untuk versi lanjutan, kamu bisa tambahkan fitur seperti logout, validasi form, atau bahkan refresh token.
Di Bagian 6, kita akan deploy aplikasi ini ke internet (frontend dan backend). Klik next page untuk ke Bagian 6! π
Halo para developer! π
Setelah kita membangun aplikasi todo lengkap dari frontend hingga backend, saatnya kita online-kan agar bisa diakses siapa saja. Yuk kita deploy ke internet π
Pastikan struktur project kamu seperti ini:
/todo-app
β
βββ client β React frontend
βββ models
βββ routes
βββ .env
βββ index.js β Entry point Express
βββ package.json
Frontend dan backend dalam satu folder ya, tapi kita akan deploy secara terpisah.
npm install
node index.js
Lalu tambahkan Environment Variables:
MONGO_URI
: (link MongoDB Atlas)JWT_SECRET
: rahasia kamuPORT
: 10000 atau biarkan kosongRender akan otomatis build dan deploy. Kamu akan mendapatkan URL misalnya https://todo-api.onrender.com
client
)Isi pengaturan:
npm run build
build
Set environment variable agar React tahu URL backend-nya:
REACT_APP_API_BASE
: URL dari backend Render kamuDi kode React, kamu ambil URL backend seperti ini:
const API = axios.create({
baseURL: process.env.REACT_APP_API_BASE,
headers: {
Authorization: `Bearer ${localStorage.getItem('token')}`
}
});
npm install cors
const cors = require('cors');
app.use(cors());
Selamat! π Kamu sudah berhasil deploy aplikasi todo ke internet. Sekarang kamu bisa share link-nya ke teman atau portofolio.
Apa selanjutnya?
Sekian seri membangun aplikasi to-do fullstack dari ruanginformatika.com. Semoga bermanfaat dan menginspirasi!
Ditulis oleh ruanginformatika.com