B2. WEB ARCHITECTURE (NEXT.JS APP ROUTER)
Website được xây dựng trên Next.js 16 với App Router và xuất ra HTML tĩnh hoàn toàn (output: "export"), tối ưu cho tốc độ và chi phí vận hành bằng 0.
1. CẤU TRÚC THƯ MỤC (DIRECTORY STRUCTURE)
text
website/
├── next.config.ts # output: "export", images.unoptimized: true
├── public/
│ ├── _headers # Cache header cho Cloudflare Pages
│ ├── api/*.json # JSON API công khai (profile, courses, showcase)
│ ├── books/ld-*.pdf # Learning Design Series
│ ├── images/, screenshots/
│ └── avatar.png
└── src/
├── app/
│ ├── layout.tsx # Root layout (font Inter + JetBrains Mono)
│ ├── globals.css # Design tokens (B5)
│ ├── (main)/ # Nhóm trang có Navbar + Footer
│ │ ├── layout.tsx
│ │ ├── page.tsx # Home
│ │ ├── about/ masters/ life-mentors/ products-hub/
│ │ ├── books/ tools/ list/ community/ family/ updates/
│ ├── books/viewer/[id]/ # Trình đọc PDF toàn màn hình (không Navbar)
│ └── api-docs/ # Trang tài liệu JSON API
├── components/ # Navbar, PageNavigation, OutcomeCard, ProductDetail, Quiz3LayerModal…
│ ├── community/ # CommunityCards, GalleryModal
│ └── family/ # MarioKartQuiz
├── data/ # Toàn bộ nội dung (xem B3)
└── utils/identity.tsQuy ước trang động: page.tsx là Server Component gọi generateStaticParams() và truyền dữ liệu cho ClientPage.tsx (Client Component) để xử lý tương tác.
2. CHIẾN LƯỢC HIỂN THỊ (RENDERING STRATEGY)
- Static Export: Áp dụng 100% cho toàn bộ website.
npm run buildsinh thư mụcwebsite/out/gồm HTML/CSS/JS tĩnh để Cloudflare Pages phục vụ. - Client-side Interactivity: Các tương tác (bộ lọc sản phẩm, modal, quiz, game) dùng Client Components (
"use client"ở dòng đầu file), dữ liệu vẫn được import tĩnh lúc build.
3. QUẢN LÝ TRẠNG THÁI (STATE MANAGEMENT)
- UI State:
useStatecủa React trong từng component. Không dùng Zustand hay thư viện state toàn cục. - URL State: Bộ lọc và tab được đồng bộ với URL để chia sẻ được (
/products-hub?cat=gems,/about#beliefs). - Local Persistence (
localStorage, chỉ trên trình duyệt người xem):
| Key | Dùng ở | Ý nghĩa |
|---|---|---|
ld_progress | /books | Chương đã mở khóa và hoàn thành |
ld_note_<chapterId> | /books/viewer/[id] | Ghi chú cá nhân theo chương |
course_comments_<id>, course_votes_<id>, course_hasVoted_<id> | CourseCard | Vote và bình luận khóa học |
product_favourites, product_count_<slug> | FavouriteButton | Sản phẩm yêu thích |
Vì trang được render tĩnh, các giá trị này chỉ đọc được sau khi component mount (trong useEffect).
4. TỐI ƯU HÓA HIỆU SUẤT (PERFORMANCE)
- Images: Static export không hỗ trợ tối ưu ảnh của
next/image(images.unoptimized: true), nên ảnh dùng thẻ<img>thường. Ảnh cần được nén trước khi đưa vàopublic/hoặcmedia/. - Caching:
public/_headersđặt cache 1 năm cho/_next/static/*. - Pre-fetching: Dùng
<Link>của Next.js cho mọi điều hướng nội bộ (ESLint chặn thẻ<a>trỏ tới trang nội bộ).