Dọn màu www.conan.school về token: 08.09.2026
Tiếp theo rà soát đồng bộ tài liệu ↔ mã, lượt này dọn trọn một site. www.conan.school từ 1.127 chỗ dùng màu ngoài token xuống 0, và là site đầu tiên có mốc bằng 0 trong scripts/color-token-baseline.json.
Dọn màu hoá ra không phải việc đổi tên lớp. Nó bới ra bốn lỗi thật, cả bốn đều thuộc loại hỏng mà trang vẫn hiển thị bình thường.
Bốn lỗi tìm được trong lúc dọn
1. 55 lớp Tailwind không sinh ra CSS nào
Tailwind chỉ có các bậc 50, 100, 200 … 900, 950. Các trang Books dùng text-purple-650, text-slate-655, text-slate-450, hover:text-purple-755, border-slate-150, text-slate-850, text-slate-350, bg-purple-650…, 55 lớp với bậc số không tồn tại, tập trung hoàn toàn ở books.$slug.tsx, books.$slug.chapters.$chapterNumber.tsx, books.$slug.sections.$sectionId.tsx và PublicEbookQuiz.tsx.
Tailwind không cảnh báo lớp lạ, nó chỉ không sinh gì. Kiểm bằng bản dựng thật:
grep -o "purple-650" build/client/assets/*.js # có (chuỗi class trong bundle)
grep -o "purple-650" build/client/assets/*.css # KHÔNG có (không rule nào)Nghĩa là hàng chục phần tử trong trải nghiệm đọc sách không có màu, chỉ thừa hưởng màu cha. Không lỗi, không cảnh báo, trang vẫn đọc được, nên không ai báo.
2. 52 lớp dark: trên một site không có chế độ tối
www không cấu hình dark mode ở đâu cả: không darkMode, không class .dark, không @custom-variant dark, và theme.css chỉ có một bộ token sáng. Nhưng trong Tailwind v4, dark: mặc định gắn với @media (prefers-color-scheme: dark), nó vẫn sinh CSS:
@media (prefers-color-scheme:dark){ … .dark\:border-amber-500\/20{border-color:#f99c0033} … }Nên với người dùng để máy ở chế độ tối, www hiện trang nền sáng với vài chục chỗ chữ và viền nhảy sang màu dành cho nền tối, text-blue-400 trên nền trắng. Một nửa chế độ tối, đúng những chỗ lẻ tẻ. Đã gỡ sạch 52 lớp; các lớp dark: còn lại đều dùng token (từ shadcn) nên giữ nguyên.
3. Một hệ thống email thứ hai, chết, nằm trong www
www.conan.school/lib/email-events.ts (566 dòng) khai hơn 20 loại email với EMAIL_EVENTS, buildSubject() và generateEmailHtml() riêng, cùng lib/quiz-email-helper.ts (45 dòng). Chúng đóng góp ~90 mã hex.
Hai chuyện cùng lúc: (a) CLAUDE.md → LUẬT EMAIL nói mọi email đi qua một danh mục EMAIL_CATALOG ở api, đây là danh mục thứ hai, ở sai chỗ; (b) grep toàn repo cho thấy không file nào import chúng, và chúng không có trong bundle đã dựng. Mã chết mô phỏng một hệ thống đã có thật ở nơi khác. Đã xoá cả hai file.
4. Hex dự phòng đã lệch khỏi token nó dự phòng
lib/score-config.ts viết var(--color-score-profile, #22d3ee). Token thật trong theme.css là #818cf8. Bốn trong bốn giá trị dự phòng đều lệch. Chúng chỉ hiện ra nếu theme.css không nạp, và đúng lúc đó, thứ hiện ra là màu sai, không phải màu an toàn. Đã bỏ các nhánh dự phòng.
Gác đã bỏ sót 792 chỗ, nay không nữa
Gác thêm sáng 08.09 bắt hai dạng: bậc số Tailwind, và hex trong khai báo CSS. Nó không bắt bg-[#faf7f0], lớp Tailwind giá trị tuỳ ý. Mà đó chính là dạng phổ biến nhất ở www:
| Thư mục | Chỗ dạng util-[#hex] mà gác cũ bỏ sót |
|---|---|
www.conan.school | 513 |
play.conan.school | 213 |
com.conan.school | 61 |
packages | 5 |
Một mã hex trong className cũng là một mã hex. Đã thêm mẫu này vào gác, và vì thế mốc của com (325 → 386) và play (57 → 270) tăng. Đây là gác nhìn rõ hơn, không phải mã xấu đi.
Mốc "chỉ được hạ" nay do công cụ giữ, không do người sửa tự nhớ
Đúng tình huống trên cho thấy vấn đề: một lần nâng mốc hợp lệ trông y hệt một lần nâng mốc để đi tiếp cho xong. Nên --update-baseline giờ từ chối mọi lần nâng:
Từ chối NÂNG mốc:
- com.conan.school: 325 → 386 (+61)
- play.conan.school: 57 → 270 (+213)
Mốc chỉ được hạ. Nếu số đi lên vì gác vừa được mở rộng để bắt thêm một dạng vi
phạm (chứ không phải vì mã xấu đi), chạy lại với --allow-raise và ghi lý do vào
báo cáo, nếu không, hãy dọn cho số xuống dưới mốc cũ.Thư mục đã sạch được giữ lại trong mốc với giá trị 0 thay vì bị xoá khỏi file: một dòng 0 nói rõ "chỗ này đã dọn xong, đừng để bẩn lại"; một dòng biến mất thì không nói gì.
Cách quy đổi
| Màu gốc | Token | Ghi chú |
|---|---|---|
slate/gray/zinc/neutral/stone ≥800 | foreground | |
slate/… 300–700 | muted-foreground (chữ) · border (viền) · muted (nền) | |
purple/violet/fuchsia/pink | primary | Books dùng tím làm màu nhấn, vai trò đó là của primary |
blue/sky/indigo/cyan | cyan | |
emerald/green/teal/lime | emerald | |
amber/yellow/orange | amber | |
red/rose | destructive | |
#c84632 #d94f2b #a03828 #f47b4f… | primary | cả họ đất nung |
#faf7f0 #f0ebe3 #fdfbf7… | accent | nền nhạt thương hiệu |
#1a1a2e #16213e #1e1e2e | surface-inverse | bề mặt tối đã có token sẵn |
text-white trên nền token | text-background / text-primary-foreground | 97 chỗ |
Bậc nhạt giữ đúng sức nặng bằng độ mờ. bg-emerald-50 → bg-emerald/10, không phải bg-emerald. Và khi lớp gốc đã có độ mờ riêng (bg-purple-200/30) thì nhân hai độ mờ (bg-primary/6) chứ không bỏ một, bản nháp đầu bỏ qua chỗ này và biến một vệt gradient rất nhạt thành một mảng cam đậm.
Hover phải còn tác dụng. bg-purple-650 hover:bg-purple-750 quy về cùng một token là hover biến mất. 58 chỗ như vậy được đổi thành hover:opacity-90 (nền) / hover:opacity-80 (chữ).
Ba ngoại lệ, có lý do
lib/doc-themes.ts, bộ theme người dùng tự chọn cho tài liệu (Conan Warm / Modern Blue / Forest Green…). Quy về token là gộp mọi theme thành một và xoá sổ tính năng. Khai vào danh sáchexemptcủa gác, kèm lý do.--color-vendor-facebook·--color-vendor-zoom, màu thương hiệu của dịch vụ bên thứ ba. Một nút Facebook màu đất nung thì người dùng không nhận ra. Khai một lần vàotheme.cssđể chúng là token chứ không phải hex rải rác.packages/design-system/theme.css, nguồn của token, phải chứa hex.
Bảng phong cách admin tài liệu hoá một bảng màu không tồn tại
Lần thứ ba packages/admin-shared/.../StyleGuidePage.tsx sai. Nó in cứng:
| Bảng phong cách nói | theme.css thật sự có |
|---|---|
Primary #f26625 | #d94f2b |
Foreground #111827 | #111111 |
Secondary #f9fafb | #f2f2f2 |
Border #e5e7eb | #f2f2f2 |
Bảng hướng dẫn dùng chung của cả cụm admin dạy một bảng màu không tồn tại, và mọi trang chép theo nó đều lệch. Đây gần như chắc chắn là nguồn của một phần trong 1.602 chỗ còn lại ở admin.
Đã sửa để các ô màu đọc từ token (bg-primary, bg-foreground, bg-muted, bg-accent, bg-border) và nhãn ghi tên token thay vì mã hex, nên khi theme.css đổi thì trang này đổi theo, không thể lệch lại được nữa.
Kiểm chứng
npm run buildxanh;tsc --noEmit0 lỗi.- 55 lớp bậc số không tồn tại: đã biến mất khỏi bundle.
- Token phân giải thật trên trang đang chạy:
text-primary → rgb(217, 79, 43),text-muted-foreground → rgb(107, 107, 107),bg-accent → rgb(255, 247, 237),border-border → rgb(242, 242, 242). - Cả 79 lớp token đang dùng đều có khai báo tương ứng trong
theme.css(không lớp nào trỏ vào token không tồn tại). - Gác tự kiểm hai chiều: thêm một chỗ vi phạm vào
www→ đỏ với mốc 0; gỡ ra → xanh. - Ảnh chụp trang chủ và kệ Deep Books: đúng màu thương hiệu.
Trang chi tiết sách không dựng được ở máy (loader gọi api.conan.school, ETIMEDOUT trong môi trường chạy thử), nên phần đó chỉ được kiểm bằng bản dựng, tsc, và phép đối chiếu CSS ở trên, không bằng mắt.