Trong bài viết này
Kiến thức

Xây Dựng Blog Này Bằng Next.js 16 và Supabase

Blog bạn đang đọc chạy trên cùng một stack với phần còn lại của portfolio: Next.js 16 App Router, React 19 và backend Supabase Postgres. Bài viết này đi qua cách các phần ghép với nhau.

Mô hình nội dung

Bài viết nằm trong hai bảng: một dòng blog_posts trung lập ngôn ngữ cùng các dòng blog_post_translations cho từng ngôn ngữ. Markdown được lưu thô và render khi có yêu cầu, nên bản tiếng Anh và tiếng Việt dùng chung slug, chuyên mục và ảnh bìa.

Vì sao chọn dòng dịch thay vì cột JSON

Cột có kiểu rõ ràng giữ cho truy vấn trung thực. Thiếu bản dịch tiếng Việt chỉ khiến bài bị ẩn khỏi danh sách tiếng Việt thay vì hiển thị nửa dịch nửa chưa dịch.

Đường đọc dữ liệu

Một module repository duy nhất sở hữu mọi truy vấn công khai. Nó map dòng dữ liệu thành view model, tính thời gian đọc từ thân markdown và không bao giờ để lộ dòng dữ liệu thô ra component.

const listing = await getPublishedPosts(locale, page);

Danh sách được bọc trong cache có tag để mọi chỉnh sửa từ admin revalidate thông qua đúng một tag.

Kết luận

  • Định nghĩa bản dịch thành dòng, không phải document
  • Render markdown phía server, trả HTML về client
  • Một accessor có cache cho mỗi đường đọc giúp việc vô hiệu hóa đơn giản

Bài viết liên quan

Kỹ thuật

Mẹo TypeScript Cho React Server Components

Những thói quen kiểu hóa nhỏ giúp server và client component trung thực: ranh giới prop, async params và kiểu trả về có thể serialize.

2 phút đọc