---
url: https://docs.nemo12.com/ops/books.md
description: >-
  Thư viện sách dùng chung @nemo12/books (SRC-1189): sáu quyển mỗi chương trình
  ở mục Tài nguyên, bìa SVG sinh bằng thuật toán.
---

# Thư viện sách dùng chung

SRC-1189 (chủ dự án, 02.10.2026): mỗi chương trình trên nemo12.com có **sáu quyển sách** ở mục
Tài nguyên (`/<chương trình>/resources`), mỗi quyển có tên, metadata và bìa SVG sinh bằng thuật toán.
Chỉ đạo kèm theo: thư viện sách đã có thì **gộp và tái dùng**, không dựng kho thứ hai.

## Một nguồn

Gói `packages/books` (`@nemo12/books`). Sách không nằm trong D1: trước đợt này chúng là file
TypeScript trong `apps/learn/src/books/`, nay chuyển ra gói để learn và web cùng đọc.

| Người đọc | Dùng gì |
| --- | --- |
| learn `/books` | `SHELVES`, `ALL_BOOKS`, `coverSvg` (sách đã có vỏ chương) |
| web `ProgramTabPage`, tab `resources` | `programBooks(id)`, `coverDataUri` |

`PROGRAM_SHELVES` khai đúng sáu slug cho mỗi chương trình. Chương trình đã có kệ ở learn (IELTS,
SAT, Grammar, Speak) thì chọn từ kệ ấy; thiếu thì thêm sách `status: "planned"` (chỉ tên, metadata,
bìa; chưa có chương). Đợt này thêm 27 quyển planned: Essay, AP, Math, AI Teen mỗi bộ 6, Speak 3.

## Metadata và bìa

`BookMeta` giữ series, subtitle, audience, level, keywords, status, ngày, và bìa
`cover: { palette, figure, idea }`. Bìa vẽ bằng `draw.ts`: 16 bảng màu, 50 hình chính có nghĩa (từ SRC-1272)
(loa cho My Voice, cá nổi bật cho Stand Out, domino cho Proof). `coverPrompt` sinh bằng
`composeCoverPrompt` từ chính ba trường ấy, nên lời tả luôn khớp thứ thuật toán vẽ.

### Chuẩn bìa (áp chung cho bìa sách và hero banner)

1. **Bảng màu có tên, chọn trong dữ liệu theo nghĩa**: một trong 16 `PALETTES`, không bao giờ ngẫu nhiên.
2. **Hình chính có nghĩa**: một trong các `MOTIFS`, nói đúng điều trang hay sách nói tới.
3. **Hạt giống ổn định**: hoa văn và hoa giấy sinh từ khoá (FNV-1a + mulberry32), cùng khoá ra cùng ảnh trên mọi máy.
4. **Chữ đọc được**: chữ nằm trên cặp `panel`/`panelInk`, tương phản từ 4,5:1 trở lên, khoá bằng test.
5. **XML sạch**: không thẻ nào khai trùng thuộc tính (xem Bẫy đã gặp).

## Hero banner (SRC-1239)

Chủ dự án 05.10.2026: mọi trang www `/ielts` và trang con có một banner, cùng công nghệ và cùng
chuẩn với bìa sách. `heroBannerSvg({ title, kicker, motif, palette, seed, aspect })` trong
`packages/books/src/banner.ts` dùng lại đúng hàm vẽ hình chính, bảng màu và bộ sinh số của
`draw.ts`; chỉ khung đổi: `wide` 1200x240 trên máy tính, `compact` 690x300 ở 375px. Banner là
trang trí (`aria-hidden`), chỉ có nhãn nhỏ `kicker`; tên trang vẫn là `<h1>` chữ thật của trang.
Bảng trang nằm ở `apps/web/src/site/ieltsBanners.ts`: mỗi tab một hình riêng, trang sách lấy đúng
hình và màu trên bìa của quyển ấy, bài viết và số "Có gì mới" nhận banner theo tiền tố. Test
`ieltsBanners.test.ts` kiểm mọi route `/ielts` trong prerender đều có banner.

Khung thứ ba `tile` 360x300 (SRC-1245): hình minh hoạ đặt cạnh một thẻ sự thật IELTS, hình chính ở
giữa, không có nhãn. Hai hình chính mới cho thẻ ấy: `balance` (cân hai đĩa có dấu %) và `bridge` (cầu
vòm nối hai bờ).

### Thẻ khả năng của AI Teen (SRC-1272)

Chủ dự án 07.10.2026: tám thẻ ở bước GOAL · Discover của `learn.nemo12.com/ai-teen` ("AI có thể giúp
em làm được gì?") mỗi thẻ mở đầu bằng một hình minh hoạ khung `tile`, đúng năm điều của chuẩn bìa.
Bốn hình chính mới trong `draw.ts`, mỗi hình có câu tả trong `FIGURE_DESC`:

| Hình chính | Vẽ gì | Thẻ |
| --- | --- | --- |
| `browser` | cửa sổ trình duyệt: ba chấm, thanh địa chỉ, khối tiêu đề có sao, ba thẻ nội dung, con trỏ đang bấm | Make websites |
| `easel` | giá vẽ ba chân với bức tranh hoàng hôn, bảng pha màu bốn đốm sơn, cây cọ | Make images |
| `clapper` | bảng clapper đang mở, nút phát trong vòng tròn, dải phim cuộn ra | Make videos |
| `gamepad` | tay cầm chơi game (phím chữ thập, bốn nút) và bong bóng chatbot đang gõ | Build projects |

Bốn thẻ còn lại dùng hình có sẵn: `pen` (Create), `bulb` (Learn), `magnifier` (Research), `puzzle`
(Solve problems). Mỗi thẻ một bảng màu chọn theo nghĩa (hoàng hôn ấm cho ý tưởng vừa loé, vàng chanh
cho lúc hiểu ra, đêm cho phòng chiếu phim...), khai ở `CAPABILITIES` trong
`apps/learn/src/aiTeen/journey.ts`, hạt giống `ai-teen|capability|<tên>`.

* **Lời tả ảnh nằm cạnh dữ liệu**: mỗi thẻ có `prompt`, sinh bằng `composeTilePrompt` (`banner.ts`)
  từ chính hình chính, bảng màu, hạt giống và ý nghĩa, như `coverPrompt` của sách. Lời tả nói cả kiểu
  hoa văn nền mà hạt giống ấy cho ra (`bannerPattern`), nên nó khớp từng tấm ảnh.
* **Tương phản**: vì khung `tile` không có chữ, test đo nét viền hình chính (`ink`) với cả hai màu
  nền: từ 3:1 trở lên (ngưỡng của đồ hoạ). Bảng màu có `ink` quá gần nền (`grape`, `berry`,
  `forest`, `lagoon`, `ocean`) không dùng cho thẻ khả năng.
* Ảnh là trang trí: `<img alt="" aria-hidden>` với data URI, SVG mang `aria-hidden`.
* learn nhập qua đường con `@nemo12/books/banner` và `@nemo12/books/draw` (thêm `./banner` vào
  `exports`), không qua gốc gói: gốc kéo cả thư viện sách vào bundle của AI Teen.
* Test: `packages/books/src/banner.test.ts` (bốn hình mới ổn định theo hạt giống, XML sạch ở mọi
  bảng màu, lời tả nói đúng thứ được vẽ), `apps/learn/src/aiTeen/capabilities.test.ts` (tám thẻ, mỗi
  thẻ một hình và một bảng màu, ảnh ổn định, prompt đủ chi tiết, tương phản).

## Deploy

`.github/app-paths.json` khai `shared.books`: sửa gói là deploy lại CẢ learn và web
(`scope.sh`, `check-production-drift.mjs` cùng biết nguồn này).

## Bẫy đã gặp

Bìa khai trùng thuộc tính trên một thẻ (`stroke-width` hai lần) là XML hỏng: trình duyệt bỏ cả tấm
ảnh, còn trình xem ảnh của macOS vẫn vẽ ra, nên xem thử ở máy không bắt được. Bốn bìa đã vỡ trên
production như vậy (PR #372). Test `programNav.test.ts` nay kiểm mọi bìa không khai trùng thuộc tính.

## Nội dung đầy đủ (sách ngắn đọc công khai)

SRC-1192 (chủ dự án, 03.10.2026): viết thử một quyển có đủ nội dung, tiếng Việt, ngắn gọn, nhiều
phần đóng khung, rồi deploy để duyệt. Quyển đầu tiên: **My Story** (NEMO ESSAY 01), đọc ở
`nemo12.com/essay/books/my-story`, trạng thái `draft` tới khi chủ dự án duyệt.

Mười lựa chọn chủ dự án chốt trước khi viết (dùng làm mặc định cho quyển sau): học sinh tự đọc,
đăng công khai trên nemo12.com, khoảng 15 phút, đủ bốn nhóm khung, ví dụ bài luận tiếng Anh kèm
giải thích tiếng Việt, giọng anh chị hướng dẫn ngồi cạnh, một nhân vật xuyên suốt, một trang cuộn
có mục lục dính, cuối sách có tóm tắt, bài tập tổng hợp, quyển sau và nút học thử.

* Khuôn là CODE: `packages/books/src/content.ts` (`BookContent`, tám loại `Block`,
  `CONTENT_LIMITS`). Nội dung từng quyển: `packages/books/src/content/<slug>.ts`, nạp lười.
* Trang đọc: `apps/web/src/site/BookReaderPage.tsx`; route `/<chương trình>/books/<quyển>` khai
  trong `routes.ts` để prerender. Trang Tài nguyên tự gắn link "Đọc ngay" cho quyển có nội dung.
* Cổng: `apps/web/src/site/bookContent.test.ts` đo độ dài từng ô, khung bắt buộc (`key`, `try`),
  ví dụ mẫu phải là tiếng Anh, chữ cấm.
* Cận dưới tổng chữ để thấp (6.000 ký tự) có chủ ý: luật là ngắn gọn, đủ ý thì dừng.

SRC-1196 (chủ dự án, 03.10.2026): My Story được **duyệt** (`status: "published"`), và viết tiếp
quyển 2 **Storytelling** (`nemo12.com/essay/books/storytelling`, `draft`). Khánh Linh đi tiếp từ
quyển 1: dựng chuyện đã chọn thành bài theo dàn bài năm khúc. Mười lựa chọn ở trên dùng nguyên,
không hỏi lại.

SRC-1202 (chủ dự án, 03.10.2026): Storytelling được **duyệt** (`published`), viết tiếp quyển 3
**My Voice** (`nemo12.com/essay/books/my-voice`, `draft`): giọng văn, đọc to, lối dịch từng chữ,
chi tiết chỉ mình có. Khánh Linh đi tiếp với bản nháp 630 từ của quyển 2.

SRC-1206 (chủ dự án, 03.10.2026): My Voice được **duyệt** (`published`), viết tiếp quyển 4
**Stand Out** (`nemo12.com/essay/books/stand-out`, `draft`): chủ đề quen, góc nhìn riêng, câu kết
không đoán trước, đọc lại bài như người chấm.

SRC-1208 (chủ dự án, 03.10.2026): Stand Out được **duyệt** (`published`), viết tiếp quyển 5
**Admissions** (`nemo12.com/essay/books/admissions`, `draft`): hồ sơ gồm những gì, người đọc tìm
gì, bài phụ của từng trường, một hồ sơ một con người. Mọi điều về tuyển sinh viết ở mức chung,
không con số.

SRC-1212 (chủ dự án, 03.10.2026): Admissions được **duyệt**, và chỉ đạo **viết tất cả 43 quyển
còn lại trên kệ chương trình**, duyệt theo bộ (mỗi bộ xong thì deploy dạng nháp, duyệt cả bộ rồi
mới làm bộ sau). Quyển đã có khung chương bên learn (`book-shell`) thì viết theo đúng câu hỏi chương
và key concept của khung, ở dạng sách ngắn nhiều khung. Bộ đầu hoàn thành: quyển 6 **Good Enough?**
(`nemo12.com/essay/books/good-enough`) khép bộ NEMO ESSAY.

Kết quả (03.10.2026): đủ **48 quyển** trên 8 kệ chương trình có nội dung đọc được ở
`nemo12.com/<chương trình>/books/<quyển>`. 42 quyển của 7 bộ sau Essay được viết song song, mỗi bộ
một agent viết và một agent KHÁC audit rồi sửa (sự thật về kỳ thi, toán, ngữ pháp, mạch nhân vật).
Mỗi bộ một nhân vật xuyên suốt: IELTS Minh Quân, SAT Bảo Anh, Grammar Gia Huy, Speak Thu Hà, Math
Khoa, AP Thanh Tâm, AI Teen Bin. Khung `compare` có `lang: "vi"` cho bộ mà ví dụ là tiếng Việt
(Math, AI Teen). Mọi quyển chưa `published` hiện nhãn "Bản nháp chờ duyệt".

Cách thêm sách, đặt tên, chọn hình: skill `.claude/skills/program-books`. Cách viết nội dung:
skill `.claude/skills/book-content`.

## Bộ sách và album trên trang tổng quan (SRC-1199)

Chủ dự án 03.10.2026: trang tổng quan của mỗi chương trình (bản học sinh và bản bố mẹ) hiện dải
**Bộ sách** gồm ba quyển ĐẦU kệ (`PROGRAM_SHELVES`, kệ xếp từ nhập môn trở lên), và một dải album
ảnh. Bìa có nội dung thì dẫn vào trang đọc `/<chương trình>/books/<quyển>`, chưa có thì dẫn sang
mục Tài nguyên. Code: `apps/web/src/site/ProgramShowcase.tsx`.

Album đọc từ `apps/web/src/site/programAlbums.ts` và theo đúng luật ảnh của `media.ts`: không ảnh
stock, không ảnh người do AI sinh. Ngày 03.10.2026 kho chưa có ảnh chụp thật nào, nên chỉ NEMO
SPEAK có album (tám tranh vẽ NEMO WALK có sẵn); IELTS, SAT, GRAMMAR, ESSAY, AP, MATH, AI TEEN
chưa có album và dải tự ẩn. Ảnh thật về thì thêm dòng vào `programAlbums.ts`, không sửa JSX.
