Trang giới thiệu song ngữ với tính năng backend thật: handshake xác thực mã hoá, admin CMS tự host với lên lịch đăng và chiến dịch email, lưu trữ đa hệ, bình luận real-time, và pipeline Docker + CI/CD đầy đủ. Bề mặt công khai chính là sản phẩm.
Thiết kế & kỹ sư
- Next.js
- NestJS
- Prisma
- Postgres
- MongoDB
- Redis
- Socket.IO
- Docker
- Turborepo
- 01Handshake mã hoá: ECDH P-256 → HKDF → AES-256-GCM, forward secrecy + chống replay
- 02Một hợp đồng API kiểu CQRS: response envelope có type + catalog mã lỗi đầy đủ
- 03Admin CMS tự host: lên lịch đăng, gửi mail hàng loạt, đánh giá, drill-down analytics
- 04Lưu trữ đa hệ (Postgres · MongoDB · Redis) + bình luận real-time Socket.IO
- 05Monorepo, Docker multi-stage, GitHub Actions gates, Lighthouse ≥ 95
Payload xác thực được mã hoá đầu-cuối
Đăng ký và đăng nhập đi qua một lớp envelope ở tầng ứng dụng trên nền TLS: ECDH P-256 tạm thời → HKDF-SHA256 → AES-256-GCM, chống replay bằng timestamp + nonce gắn vào GCM AAD. SDK mã hoá nằm trong một package dùng chung nên client và server không lệch nhau.
- 01Client generates an ephemeral ECDH P-256 key pair
- 02ECDH(client_eph, server_pub) → HKDF-SHA256 → AES-256-GCM key
- 03Encrypt payload; bind ts + nonce into the GCM AAD
- 04Server checks ts window + unused nonce (Redis), derives the same key, decrypts
- 05Server encrypts the response under the same key — forward secrecy per request
- 06Shared crypto SDK in packages/, imported by both web and api — no client/server drift
Phiên đăng nhập được làm chặt, không chỉ phát ra
Ngoài handshake, lõi auth còn xoay refresh token kèm phát hiện reuse theo family và TOTP MFA tuỳ chọn — những thứ thường bị bỏ qua ở một trang portfolio.
- 01Refresh tokens rotate on every use; each belongs to a session family
- 02Reuse of a retired token kills the whole family in one transaction (theft response)
- 03Optional TOTP MFA (authenticator app) with audit-logged enable/disable
- 04Every public endpoint is rate-limited; auth + subscribe carry Cloudflare Turnstile
- 05No token, key, nonce, or password hash ever reaches logs or the client bundle
Một hợp đồng API, định hình theo CQRS
Mọi endpoint nói chung một envelope, áp đặt bởi một interceptor + exception filter toàn cục — không viết tay từng controller. Read trả data; write trả success + message; list kèm pagination; lỗi kèm mã ổn định từ một catalog duy nhất.
- 01Query → { data } · Mutation → { success, message, data }
- 02Paginated → { success, data, pagination: { page, pageSize, totalItems, totalPages } }
- 03Error → { success: false, message, error: { code } } from one ErrorCode catalog
- 04Validation → { success: false, errors: [{ field, message }] }
- 05The encrypted route nests its own interceptor so the global envelope wraps the sealed blob
- 06Prisma P2025/P2002 mapped to 404/409; /health passes through untouched (Terminus format)
Trang tự chạy admin CMS của riêng nó
Một app admin theo allow-list quản lý user, bài viết và subscriber dưới dạng bảng có search + phân trang, lên lịch đăng bài theo từng phút, và gửi chiến dịch email hàng loạt — dựa trên cùng API đã làm chặt.
- 01Users · Posts · Subscribers tables: offset pagination + search, behind an AdminGuard
- 02Scheduled publishing: @nestjs/schedule cron + atomic claim (multi-instance safe)
- 03Bulk campaigns: background send via Resend, fire-and-forget, bootstrap reconciliation
- 04Stateless unsubscribe: HMAC token id.HMAC("unsub:"+id) — no per-send DB write
- 05Blog ratings (1–5, one per user) + per-user activity (comments, reads, ratings)
Đúng kho cho đúng việc
PostgreSQL giữ lõi giao dịch; MongoDB giữ dữ liệu append-heavy và document; Redis giữ nonce và bộ đếm rate-limit. Mỗi mối quan tâm một writer — không entity nào bị ghi kép.
- 01Postgres (Prisma): users · refresh tokens (family + rotation) · posts · subscribers · ratings
- 02MongoDB (Mongoose): analytics_events · contact_messages
- 03Redis (ioredis): handshake nonces + per-endpoint rate-limit windows
- 04Free-tier discipline: pooled connections, lean documents, indexes on hot paths
Bình luận real-time và đếm lượt đọc trung thực
Bình luận stream qua Socket.IO nên luồng cập nhật mà không cần refresh. Lượt đọc tôn trọng ISR: thay vì tăng trên một render server đã cache, một beacon client đếm một lượt đọc mỗi phiên.
- 01Socket.IO gateway broadcasts new comments to everyone viewing a post
- 02Comment list is keyset-paginated; the realtime feed merges without duplicates
- 03ISR (revalidate 300s) makes server-side counting wrong → client read-beacon instead
- 04sessionStorage dedupe = one read per visitor per post; the POST /view route is throttled
Xây và ship như production
NestJS clean/hexagonal, structured logging, health probe, và pipeline container + CI/CD đầy đủ — ghi trong ADR, không tuỳ hứng.
- 01Architecture: NestJS clean/hexagonal · SOLID · DI · shared types in packages/
- 02Observability: nestjs-pino structured logs · @nestjs/terminus health (Postgres + Mongo)
- 03Delivery: multi-stage Docker per app · GitHub Actions CI gates
- 04Quality: Lighthouse ≥ 95 · typed end to end · EN/VI metadata, hreflang, JSON-LD
≥95
mục tiêu Lighthouse3
kho dữ liệu, mỗi cái một writer0
credential plaintext trên đường truyền