Blog Platform - Tài liệu Yêu cầu và Tổng quan Dự án (Project Specification & Overview)
Table of Contents21 sections
Blog Platform - Tài liệu Yêu cầu và Tổng quan Dự án (Project Specification & Overview)
Phiên bản: 3.0
Ngày cập nhật: 2026-06-17
Trạng thái: Hoàn thiện đặc tả
1. Giới thiệu (Introduction)
1.1 Bối cảnh (Background)
Dự án Blog Platform là nền tảng quản lý nội dung (CMS) và xuất bản bài viết nội bộ cho công ty (Classmethod Vietnam / CMDN). Hệ thống cho phép các thành viên trong công ty dễ dàng chia sẻ kiến thức, viết bài kỹ thuật và cập nhật thông tin nội bộ.
1.2 Mục tiêu dự án (Project Goals)
Tối ưu hóa trải nghiệm viết bài (Authoring Experience): Cung cấp trình soạn thảo WYSIWYG trực quan, hỗ trợ kéo thả hình ảnh và quản lý thẻ (tags).
Hiệu năng cao & Chuẩn SEO (Performance & SEO): Trang hiển thị cho người đọc (public) phải có tốc độ tải trang cực nhanh, tối ưu hóa điểm số Lighthouse và SEO tốt.
Tối ưu chi phí vận hành (Serverless Cost Optimization): Thiết kế dựa trên mô hình Serverless hoàn toàn trên AWS, đảm bảo chi phí gần như bằng 0 khi không có lưu lượng và tự động mở rộng khi cần.
Đơn giản trong vận hành (Operational Simplicity): Sử dụng các dịch vụ Managed Services của AWS như Lambda, DynamoDB, S3, CloudFront và tích hợp Auth0 cho xác thực.
2. Đối tượng sử dụng (Target Users)
Hệ thống phục vụ hai nhóm người dùng chính:
Nhóm người dùng | Mô tả | Yêu cầu chính |
|---|---|---|
Độc giả (Public Readers) | Khách truy cập bên ngoài hoặc nhân viên công ty đọc bài viết. Không cần đăng nhập. | Tốc độ tải trang nhanh, hiển thị đẹp trên mobile/desktop, tìm kiếm chính xác, lọc bài theo tag. |
Tác giả (Authors / Admins) | Nhân viên công ty có tài khoản email thuộc domain được cấu hình (ví dụ: | Đăng nhập an toàn, tạo/sửa/xóa bài viết, tải lên hình ảnh, lưu bản nháp (draft), xuất bản (publish). |
3. Yêu cầu chức năng (Functional Requirements)
3.1 Giao diện Độc giả (Public Site - /)
Trang chủ (Homepage):
Hiển thị danh sách các bài viết đã xuất bản (Published Posts) theo thứ tự thời gian mới nhất lên đầu.
Phân trang (Pagination) mượt mà hỗ trợ cuộn hoặc chuyển trang.
Hiển thị thông tin tóm tắt: Tiêu đề, ảnh bìa (cover image), ngày đăng, tác giả và các thẻ (tags).
Trang chi tiết bài viết (Post Detail -
/blog/:slug):Hiển thị toàn bộ nội dung chi tiết bài viết được format chuẩn từ Markdown/HTML.
Hỗ trợ hiển thị mục lục tự động (TOC), hình ảnh, code block có highlight cú pháp.
Tối ưu hóa SEO bằng thẻ Meta (Title, Description, OpenGraph).
Tìm kiếm bài viết (Search -
/search):Cho phép tìm kiếm bài viết theo từ khóa trong tiêu đề và nội dung.
Lọc bài viết theo tên tác giả.
Lọc bài theo thẻ (Tag Filtering -
/public/posts/by-tag):Xem danh sách các bài viết có gắn tag cụ thể.
Danh sách thẻ (Tags -
/public/tags):Hiển thị toàn bộ danh sách các tags đang được sử dụng trong hệ thống kèm theo số lượng bài viết của mỗi tag.
3.2 Giao diện Tác giả (Admin Dashboard - /admin/*)
Xác thực (Authentication):
Đăng nhập/Đăng xuất bảo mật qua hệ thống Auth0 (SSO).
Chỉ chấp nhận các email có domain thuộc cấu hình quy định (ví dụ:
ALLOWED_EMAIL_DOMAIN).
Quản lý bài viết (Post Management):
Xem danh sách toàn bộ bài viết do chính tác giả đó tạo (gồm cả Draft và Published).
Tìm kiếm, lọc danh sách bài viết theo trạng thái (Draft, Published).
Tạo bài viết mới (Create Post).
Chỉnh sửa bài viết hiện có (Update Post) - chỉ cho phép chỉnh sửa bài do chính mình viết (Owner).
Xóa bài viết (Delete Post) - Xóa bài viết khỏi cả bảng dữ liệu nháp và bảng xuất bản công khai.
Trình soạn thảo bài viết (Rich Text Editor):
Sử dụng TipTap 3 trực quan.
Hỗ trợ định dạng văn bản: Heading, Bold, Italic, Underline, Strikethrough, Superscript, Subscript.
Hỗ trợ tạo bảng (Table), căn lề văn bản (Text Align), tô sáng chữ (Highlight).
Kéo thả hoặc chọn tệp để chèn hình ảnh trực tiếp vào bài viết.
Quản lý Media (Media Upload):
Tự động sinh Presigned POST URL từ S3 để browser upload ảnh trực tiếp lên AWS S3 mà không cần đi qua Lambda (giúp tiết kiệm RAM, băng thông và tránh giới hạn payload 6MB của API Gateway).
4. Yêu cầu phi chức năng (Non-Functional Requirements)
4.1 Hiệu năng và Khả năng chịu tải (Performance & Scalability)
Static Export & CDN: Nhằm tối đa hóa tốc độ tải trang cho Độc giả, ứng dụng Frontend Next.js được cấu hình ở chế độ
output: "export". Toàn bộ file tĩnh (HTML, CSS, JS, Images) được lưu tại S3 Static Bucket và phân phối qua CloudFront CDN.Không dùng SSR trên Production: Giảm thiểu độ trễ phản hồi từ server bằng cách chuyển việc xử lý động về phía Browser (CSR) đối với trang Admin, trang Search và trang Author.
Dual-Table DynamoDB: Phân tách dữ liệu thành bảng Working (lưu bản nháp/author CRUD) và bảng Published (lưu bài đã xuất bản, được tối ưu chỉ mục đọc nhanh).
4.2 Bảo mật (Security)
Giao thức bảo mật: Bắt buộc sử dụng HTTPS trên toàn bộ hệ thống thông qua CloudFront và API Gateway.
Xác thực API: Các API chỉnh sửa bài viết (
/posts/*) và media (/media/*) được bảo vệ bằng JWT Authorizer tích hợp trên API Gateway, verify chữ ký số của token phát hành bởi Auth0.Lưu trữ riêng tư: S3 Media Bucket được cấu hình Private hoàn toàn, chặn mọi truy cập trực tiếp từ Internet (Block Public Access) và chỉ cho phép đọc qua CloudFront OAC (Origin Access Control) hoặc sinh URL có thời hạn.
Phân quyền chặt chẽ: Kiểm tra quyền sở hữu bài viết (Post Ownership) ở tầng Lambda Use Case để đảm bảo tác giả không thể sửa hay xóa bài viết của tác giả khác.
4.3 Độ sẵn sàng và Vận hành (Reliability & Operations)
Không Máy Chủ (Serverless): Toàn bộ stack backend sử dụng mô hình Serverless giúp hệ thống có khả năng tự động co giãn (Auto-scaling) từ 0 đến hàng ngàn request đồng thời.
Cơ chế Rebuild Tự động (Auto-Rebuild): Vì Frontend là static website, khi tác giả nhấn "Publish" một bài viết mới, hệ thống sẽ tự động gửi một thông điệp vào SQS Queue, trigger Lambda gửi API tới GitHub Actions để tự động kích hoạt tiến trình Build & Deploy lại Frontend nhằm cập nhật bài mới trên trang chủ.
Giám sát & Logging: Sử dụng AWS CloudWatch Logs (retention 14-30 ngày) lưu trữ logs có cấu trúc JSON của Lambda & API Gateway, kết hợp AWS X-Ray để trace lỗi request.
5. Kiến trúc Hệ thống tóm tắt (System Architecture)
5.1 Sơ đồ luồng hoạt động chính (High-level Architecture)
5.2 Stack công nghệ sử dụng (Technology Stack)
Frontend:
Next.js 15.5.x (App Router, Static HTML Export).
React 19 & Tailwind CSS v3 (với CSS PostCSS setup).
TipTap 3 (Trình soạn thảo WYSIWYG).
SWR (Thư viện Fetch & Cache dữ liệu ở phía Client).
Zod (Validate dữ liệu đầu vào).
Custom OAuth 2.0 PKCE: Tự triển khai luồng đăng nhập PKCE sử dụng Web Crypto API trong browser (không qua SDK ngoài, lưu trữ ID Token trong
localStorage).
Backend:
AWS SAM (Infrastructure as Code - Quản lý tài nguyên AWS).
AWS Lambda Node.js 22.x (ARM64), viết theo nguyên lý Clean Architecture kết hợp Inversify JS (Dependency Injection).
Amazon API Gateway (HTTP API).
Amazon DynamoDB (Thiết kế dual-table:
blog-tablevàblog-published).Amazon S3 (Lưu trữ ảnh tải lên và file tĩnh của Web).
Amazon SQS (Hàng đợi tin nhắn xử lý rebuild bất đồng bộ).
CI/CD:
GitHub Actions (Tự động hóa build & deploy cả frontend và backend).
6. Vòng đời Bài viết & Luồng dữ liệu nghiệp vụ (Key Workflows)
6.1 Vòng đời bài viết (Post Lifecycle)
Draft (Nháp): Khi tác giả viết bài mới và bấm "Save", dữ liệu chỉ được lưu vào bảng Table A (Working) dưới dạng item có SK là
#DRAFT. Bài viết này chưa hiển thị trên trang công khai.Publish (Xuất bản): Khi tác giả bấm "Publish":
Lambda ghi bản copy tối ưu hóa sang Table B (Published).
Đồng thời ghi nhận phiên bản xuất bản
#PUBLISHEDtrong Table A.Gửi message vào SQS để kích hoạt rebuild Frontend Next.js tĩnh.
Unpublish (Hạ bài): Khi tác giả chọn hạ bài viết đã xuất bản:
Lambda xóa bài viết khỏi bảng Table B (Published).
Xóa item
#PUBLISHEDvà các tag tương ứng trong Table A (nhưng giữ lại bản nháp#DRAFT).Kích hoạt build lại Frontend để gỡ bài khỏi danh sách công khai.
Delete (Xóa bài): Tác giả chọn xóa hoàn toàn bài viết:
Lambda tiến hành xóa toàn bộ item liên quan đến bài viết đó ở cả hai bảng Table A và Table B.
6.2 Quy trình tải ảnh lên (S3 Presigned URL Flow)
Tác giả chèn ảnh vào trình soạn thảo -> Frontend gọi API
POST /media/upload-url.Lambda trả về S3 Presigned URL và thông tin trường cần thiết để POST.
Frontend gửi trực tiếp file ảnh lên S3 Bucket thông qua URL này (Lưu vào thư mục tạm
media/temp/).Khi bài viết được lưu (Save hoặc Publish), Lambda sẽ chuyển (promote) ảnh từ thư mục tạm
media/temp/sang thư mục chính thứcmedia/để lưu giữ lâu dài, các file thừa trong thư mục tạm sẽ tự động bị xóa sau 24h bởi S3 Lifecycle Policy.
7. Các lưu ý quan trọng (Important Operational & Testing Notes)
Dưới đây là các đặc thù kiến trúc của hệ thống cần đặc biệt lưu ý trong quá trình vận hành, kiểm thử và nghiệm thu:
7.1 Độ trễ cập nhật trên trang Độc giả (Publish / Unpublish / Delete Delay)
Trễ đồng bộ từ 2 - 5 phút: Do Frontend chạy mô hình Static HTML Export trên S3 + CloudFront CDN, mọi thao tác thay đổi dữ liệu công khai bao gồm Publish (Xuất bản), Unpublish (Hạ bài), và Delete (Xóa bài) sẽ không xuất hiện ngay lập tức trên trang Public.
Cơ chế hoạt động:
Tác giả thao tác trên Admin $\rightarrow$ Hệ thống gửi tin nhắn vào AWS SQS.
Lambda nhận tin nhắn từ SQS $\rightarrow$ Gọi API kích hoạt workflow
deploy-frontend.ymltrên GitHub Actions.GitHub Actions chạy build lại toàn bộ Next.js tĩnh $\rightarrow$ Đồng bộ lên S3 $\rightarrow$ Gửi lệnh Invalidate cache CloudFront (
/*).
Sự khác biệt giữa Admin và Public:
Trang Admin Dashboard (
/admin) cập nhật ngay lập tức vì chạy dạng Single Page App (SPA) gọi trực tiếp API lấy dữ liệu thời gian thực từ DynamoDB Table A.Trang Public (
/và/blog/:slug) cập nhật sau khi build pipeline trên GitHub Actions hoàn tất (trạng thái màu xanh).
Cách kiểm tra: Theo dõi trạng thái workflow chạy trên GitHub hoặc đợi khoảng 3 - 5 phút rồi thực hiện Hard Reload (
Ctrl + F5hoặcCmd + Shift + R) trang Public để kiểm tra kết quả.
7.2 Cơ chế tự động dọn dẹp hình ảnh tạm (Temporary Media Cleanup)
Thư mục tạm: Khi chèn ảnh vào trình soạn thảo, ảnh được tải trực tiếp lên thư mục tạm
media/temp/trên S3 thông qua Presigned POST URL.Lưu trữ chính thức: Chỉ khi tác giả nhấn Lưu hoặc Xuất bản, Lambda mới thực hiện chuyển (promote) ảnh từ
media/temp/sang thư mục lưu trữ vĩnh viễnmedia/.Tự động xóa rác: Nếu tác giả chèn ảnh vào trình soạn thảo nhưng tắt trình duyệt (không bấm Lưu/Xuất bản), ảnh tạm này sẽ tự động bị xóa sau 24 giờ bởi chính sách S3 Lifecycle Policy để tránh phát sinh chi phí lưu trữ rác.
7.3 Phân quyền và Giới hạn truy cập (Authorization & Domain Restrictions)
Bảo vệ Route: Toàn bộ route
/admin/*đều được bảo vệ nghiêm ngặt ở client-side. Nếu chưa đăng nhập hoặc token hết hạn, hệ thống sẽ tự động chuyển hướng người dùng sang trang đăng nhập của Auth0.Giới hạn Email Domain: Hệ thống chỉ chấp nhận tài khoản có đuôi email thuộc domain được định cấu hình trong biến môi trường
ALLOWED_EMAIL_DOMAIN(ví dụ:@classmethod.vn). Các email khác sẽ bị từ chối truy cập ngay lập tức sau bước đăng nhập Auth0.Kiểm soát quyền sở hữu (Owner Validation): Một tác giả không thể chỉnh sửa hoặc xóa bài viết của tác giả khác. Hệ thống kiểm tra ID người dùng ở cả giao diện Admin và tầng xử lý nghiệp vụ của Lambda API (trả về mã lỗi
403 Forbiddennếu cố tình bypass client).Môi trường độc lập: Mỗi môi trường (
dev,staging,prod) có bộ tài nguyên AWS (DynamoDB Table, S3 Bucket, API Gateway, CloudFront) và cấu hình Auth0 hoàn toàn độc lập, được phân biệt bằng hậu tố-{env}.