Giới thiệu
Trong thế giới phát triển ứng dụng web hiện đại, việc xây dựng một ứng dụng quản lý công việc (todo app) là một trong những bài tập kinh điển để làm quen với công nghệ. Nếu bạn đang tìm kiếm một giải pháp toàn diện, vừa có backend mạnh mẽ, vừa có frontend hiện đại, thì sự kết hợp giữa Supabase và Next.js sẽ là lựa chọn hoàn hảo. Supabase cung cấp cơ sở dữ liệu PostgreSQL, xác thực người dùng, và API tự động, trong khi Next.js giúp bạn xây dựng giao diện nhanh chóng và tối ưu SEO. Bài viết này sẽ hướng dẫn bạn từng bước tạo một ứng dụng todo app hoàn chỉnh, giúp bạn nắm vững cả hai công nghệ này.
Chuẩn bị môi trường
Trước khi bắt đầu, hãy đảm bảo rằng bạn đã cài đặt Node.js (phiên bản 18 trở lên) và có một tài khoản Supabase. Nếu chưa có, hãy truy cập trang chủ Supabase và đăng ký một tài khoản miễn phí. Tiếp theo, mở terminal và tạo một dự án Next.js mới bằng lệnh:
npx create-next-app@latest todo-app
Sau khi dự án được khởi tạo, di chuyển vào thư mục dự án và cài đặt các thư viện cần thiết:
npm install @supabase/supabase-js
npm install shadcn/ui
Shadcn/ui là một thư viện UI components được xây dựng trên Tailwind CSS, giúp giao diện của bạn trở nên chuyên nghiệp và nhất quán.
Thiết lập Supabase
Đăng nhập vào dashboard của Supabase, tạo một project mới và lưu lại URL và anon public key—đây là thông tin cần thiết để kết nối ứng dụng với Supabase. Tiếp theo, tạo một bảng todos trong cơ sở dữ liệu với các cột: id (UUID, primary key), title (text), description (text), is_completed (boolean, default false), và created_at (timestamp, default now()). Supabase sẽ tự động tạo API REST cho bảng này, giúp bạn dễ dàng thao tác dữ liệu.
Xây dựng frontend với Next.js
Mở file lib/supabase.js và khởi tạo client Supabase:
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
Để bảo mật, lưu URL và key vào file .env.local. Tiếp theo, tạo một trang todo tại app/todos/page.js:
import { useState, useEffect } from 'react'
import { supabase } from '@/lib/supabase'
export default function TodosPage() {
const [todos, setTodos] = useState([])
const [title, setTitle] = useState('')
Quảng cáo
300x250 In-Content Advertisement
useEffect(() => {
fetchTodos()
const subscription = supabase
.from('todos')
.on('*', (payload) => fetchTodos())
.subscribe()
return () => supabase.removeSubscription(subscription)
}, [])
async function fetchTodos() {
const { data, error } = await supabase.from('todos').select('*')
if (error) console.error(error)
else setTodos(data || [])
}
async function addTodo() {
if (!title.trim()) return
const { error } = await supabase.from('todos').insert([{ title, is_completed: false }])
if (error) console.error(error)
setTitle('')
}
async function toggleTodo(id, isCompleted) {
await supabase.from('todos').update({ is_completed: !isCompleted }).eq('id', id)
}
return (
<div className="p-6">
<h1 className="text-2xl font-bold mb-4">Todo App</h1>
<div className="flex mb-4">
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="Nhập công việc mới..."
className="flex-1 px-3 py-2 border rounded-l-lg"
/>
<button onClick={addTodo} className="px-4 py-2 bg-blue-500 text-white rounded-r-lg hover:bg-blue-600">
Thêm
</button>
</div>
<ul className="space-y-2">
{todos.map((todo) => (
<li key={todo.id} className="flex items-center justify-between">
<div className="flex items-center">
<input
type="checkbox"
checked={todo.is_completed}
onChange={() => toggleTodo(todo.id, todo.is_completed)}
className="mr-2"
/>
<span className={todo.is_completed ? 'line-through text-gray-400' : ''}>
{todo.title}
</span>
</div>
</li>
))}
</ul>
</div>
)
}
Đoạn code trên minh họa cách kết nối với Supabase, lắng nghe thay đổi dữ liệu theo thời gian thực, và cập nhật giao diện ngay lập tức. Việc sử dụng useEffect và subscription giúp ứng dụng luôn đồng bộ với cơ sở dữ liệu.
Nâng cao với xác thực người dùng
Để ứng dụng thực tế hơn, bạn có thể thêm tính năng xác thực người dùng. Supabase cung cấp sẵn UI components cho đăng ký và đăng nhập. Thêm một trang auth và bảo vệ trang todo bằng cách kiểm tra session người dùng. Khi người dùng đăng nhập, lưu trữ user.id cùng với mỗi todo, giúp phân biệt công việc của từng người.
Kết luận
Qua bài hướng dẫn này, bạn đã xây dựng được một ứng dụng todo app hoàn chỉnh, sử dụng Supabase cho backend và Next.js cho frontend. Supabase giúp bạn tiết kiệm thời gian với cơ sở dữ liệu, API tự động, và xác thực tích hợp, trong khi Next.js mang lại trải nghiệm người dùng mượt mà và SEO tốt. Bạn có thể mở rộng ứng dụng bằng cách thêm tính năng chỉnh sửa, xóa công việc, hoặc phân loại theo dự án. Hy vọng bài viết này giúp bạn tự tin hơn khi bắt tay vào các dự án thực tế với Supabase và Next.js.