Bỏ qua, đi thẳng tới nội dung
shigakogen

Architecture

Site này (portfolio + blog cá nhân) được build bằng Next.js trên Vercel, dữ liệu và backend logic nằm hoàn toàn ở Supabase Cloud. Trang này giải thích site chạy như thế nào — dành cho ai tò mò về kiến trúc.

Sơ đồ

Browser
Vercel — Next.js (SSR / ISR / Server Actions)
Postgres
(RLS)
Edge Functions
(Deno)
Auth
Storage

Ngoài luồng chính: GitHub Actions build/deploy + backup DB hằng tuần · Sentry nhận lỗi runtime · Umami nhận pageview.

Stack

FrontendNext.js (App Router) + TypeScript strict
StylingTailwind CSS v4 + shadcn/ui
ContentSupabase Postgres (bài viết lưu dạng Markdown/MDX text)
Render MDXnext-mdx-remote (RSC) + rehype-pretty-code (Shiki)
Backend APISupabase Edge Functions (Deno + TypeScript)
AuthSupabase Auth (magic link, 1 admin user)
StorageSupabase Storage (ảnh bài viết, resume PDF)
ObservabilitySentry (error tracking) + Umami (analytics)
Deploy FEVercel (Git-connected, ISR)
Deploy BEsupabase functions deploy (qua GitHub Actions)

Luồng dữ liệu chính

Đọc bài viết (public)

  1. 1Next.js SSG lúc build + revalidate mỗi 1h (ISR)
  2. 2Server Component đọc thẳng Postgres qua anon key (client không cookie, không qua Edge Function)
  3. 3RLS chỉ cho đọc bài đã publish

View counter / reaction

  1. 1Client gọi Edge Function increment-view / react
  2. 2Edge Function tự rate-limit (IP + salt, không lưu IP thật) rồi ghi Postgres bằng service role
  3. 3Lỗi ở bước này không làm sập trang — chỉ ẩn số đếm

Đăng / sửa bài viết (admin)

  1. 1proxy.ts chặn /admin/* bằng RPC is_admin() trên session hiện tại
  2. 2Server Action ghi thẳng Postgres qua client có cookie session (RLS kiểm tra quyền admin)
  3. 3revalidatePath() để trang public cập nhật ngay, không đợi hết giờ ISR

Tìm kiếm

  1. 1Client debounce 300ms rồi gọi Edge Function search
  2. 2Edge Function query full-text search trên Postgres, chỉ trong bài đã publish

Toàn bộ source code (frontend, Edge Functions, migrations, CI/CD) đều public trên GitHub.