Cách dùng file này (mọi agent): đọc mục ▶ trước khi động vào code. Sau mỗi bước có ý nghĩa (xong task/section/trang, sửa bug, đổi hướng, gặp blocker):
- sửa bảng trạng thái;
- thêm 1 dòng vào Nhật ký, có ngày, việc đã làm và cách kiểm chứng;
- sửa mục ▶ cho đúng việc tiếp theo.
Dòng nào lỗi thời thì xoá hoặc sửa, không viết chồng. Nhật ký chỉ giữ ~15 dòng mới nhất; chi tiết cũ nằm ở git history và plan/spec trong
docs/superpowers/. Không ghi “xong” nếu chưa kiểm chứng.
Stack hiện tại: một repo Next.js 16 + Supabase (Postgres/Auth/Storage/Realtime/Edge Function), không còn backend Java. Repo ../Thiep-cuoi-online-backend là bản Spring Boot cũ, không dùng và không phát triển thêm.
Production: Cloudflare Workers, https://taothiepcuoimienphi.raystudio.com.vn (cách deploy ở DEPLOY.md mục 4c; domain cũ taothiepcuoi.raystudio.com.vn giữ redirect 301 về mới). Vercel và Netlify chỉ là đích dự phòng trong DEPLOY.md.
Cổng: npm run dev 3000; next start tay 3001; Playwright e2e tự dựng server ở 3100. Chạy local: README.md.
Gate: npm test (257 test) + npm run typecheck + npm run build:next; e2e npm run e2e -- --project=<tên> (xem mục 5).
251096d7Lỗi nghiêm trọng đã sửa: từ bản deploy tối ưu Cloudflare (2026-10-11), cả 50 trang /templates/[id] trên prod trả bản /live có noindex. Nguyên nhân: matcher has: query của OpenNext coi has không có value là luôn khớp. Sửa: value: ".+" trong next.config.ts, kèm test tests/static-routes.test.ts (đỏ→xanh). Kiểm chứng prod: 3 trang mẫu không còn robots meta, ?preview=1 vẫn noindex.
Đã làm: section “Về mẫu thiệp …” dưới khối design (components/templates/TemplateAbout.tsx, copy ở lib/template-copy.ts: 50 đoạn viết riêng + 6 đoạn theo phong cách + 3 mẫu liên quan, Product isRelatedTo), ~298 từ/trang (trước ~80); HSTS max-age=31536000 (không includeSubDomains) + redirect http→https qua header cf-visitor (prod trả 308); email liên hệ nanz99.1368@gmail.com (trong .env.local, có trên /ve-moc, /tro-giup, pháp lý + contactPoint); /ve-moc, Organization dùng chung, ảnh chia sẻ riêng, FAQ /bang-gia (mục Nhật ký 2026-10-12). Bản deploy lấy từ working tree nên có luôn /ung-ho mới và việc xoá media khi admin xoá thiệp. Kiểm chứng: npm test 372/372, typecheck, build Cloudflare (worker 1.85 MiB gzip), e2e all-pages chrome + mobile-chrome 24/24, smoke prod 200 + sitemap có /ve-moc.
Chờ chủ dự án: commit để git khớp prod; Search Console gửi lại sitemap + yêu cầu lập chỉ mục lại các trang /templates/* (bị noindex ~1 ngày); www (DNS); tên tác giả blog thật; chạy lại /seo audit để chấm điểm mới. Copy “miễn phí toàn bộ” vẫn mâu thuẫn với migration invitation-tiers: phải sửa copy trước khi đẩy migration đó. Thêm ở 251096d7: /llms.txt (tự sinh từ SEO_PAGES + mẫu + blog, lib/llms.ts + test, GET 200, 77 link; HEAD trả 404 qua OpenNext, crawler dùng GET nên để vậy), sitemap lastmod 50 trang mẫu = 2026-10-12. Còn lại không làm bằng code: www (DNS + chứng chỉ subdomain cấp 2, tự gắn bằng wrangler có thể gỡ custom domain đang có), bớt font preload (chờ đo PSI thật), tên tác giả blog. Rollback: DEPLOY.md mục 6 (trước SEO: d447c6cc; trước llms: 69896e0d).
/ung-ho cập nhật theo design/Ung Ho.dc.html mới (2026-10-11, chưa commit, chưa deploy)Hero mới (“Giữ Mộc sống, miễn phí mãi mãi”, nút “Ủng hộ ngay ↓” cuộn tới thẻ), thẻ chuyển khoản có 4 mức ủng hộ + dòng tác động + hàng “Số tiền” + viền phát sáng, câu trích mới + nút đỏ. QR là VietQR thật và mã hoá luôn mức tiền (vietQrUrl(…, amount)). Deviation (DESIGN.md): bỏ dòng “238 người đã ủng hộ” + avatar và dòng ký tên “Thu Hà & Quốc Bảo” vì là số liệu/nhân vật bịa. Kiểm chứng: npm test + typecheck xanh (thêm 2 test donate); Chrome DevTools 1280 + 390px: chọn/bỏ mức, QR đổi amount=, hàng Số tiền hiện/ẩn, 0 tràn ngang, 0 ảnh hỏng, vùng chạm ≥44px. Chưa chạy: npm run build:next, so sánh chiều cao section với design.
d447c6ccCloudflare Workers Free dính 1102 ngắt quãng (503) vì open-next.config.ts rỗng → trang tĩnh render lại mỗi request. Sửa: staticAssetsIncrementalCache + populateCache local trong script build. Kiểm chứng: 144/144 request song song = 200; e2e production chrome + mobile-chrome 59 pass, 0 fail. Chờ chủ dự án: supabase db push migration 202610090001_admin.sql + tạo admin (DEPLOY.md mục 7); khu /admin trên prod chưa chạy tới khi xong. Rollback: DEPLOY.md mục 6 (version trước c9efee02, a904e420).
/admin: QA kỹ + sửa lỗi, sẵn sàng release (2026-10-11, chưa commit, chưa deploy)Spec docs/superpowers/specs/2026-10-09-admin-design.md. Test trên Supabase local (Docker, npx supabase start + db reset), KHÔNG đụng DB production. Đã sửa: (1) search thiệp: %/_ là wildcard + tìm theo tên mẫu có dấu cách (“song hy”) không ra (lib/server/admin-card-search.ts mới, có unit test thật); (2) mobile ≤768px: bảng đổi thành thẻ xếp dọc (data-label), hết tràn ngang/cắt cột, nút ≥44px, input 16px; (3) dòng admin tự khoá/xoá bị vô hiệu (isSelf); (4) ConfirmDialog focus nút Huỷ + trap Tab + trả focus; (5) search 1 ký tự không còn hiện lỗi; (6) dashboard: thứ tự tên cô dâu & chú rể khớp trang Thiệp, lời chào dùng tên; (7) nút “Ẩn xuất bản” đúng design, link Xem mở tab mới; (8) supabase/tests/admin.sql hết giả định bảng rỗng.
Kiểm chứng: npm test 350 pass, typecheck sạch, build:next xanh; API: ma trận 401/403, fuzz, origin, rate limit 429, ban/xoá/publish/template CRUD trên DB thật local; e2e thật mới e2e/admin-panel.spec.ts (cần E2E_ADMIN_EMAIL/PASSWORD + server trỏ Supabase local) 6/6 trên chrome, mobile-chrome, mobile-safari; e2e/admin.spec.ts 14/14. Chrome DevTools 360px: 0 tràn ngang, 0 vùng chạm <44px.
Còn mở: (a) chỉnh sửa ở Mẫu thiệp (ẩn/tên/nhãn) CHƯA áp dụng ra /templates công khai (quyết định V1, spec mục 1.2), toast vẫn ghi “khỏi trang Mẫu thiệp”; (b) supabase/tests/backend.sql lỗi sẵn có: purge_expired_invitations xoá thẳng storage.objects bị Storage API chặn; (c) trước khi release: đẩy migration 202610090001_admin.sql lên prod, tạo admin + đổi mật khẩu mạnh (DEPLOY.md); chưa thử iPhone/Android thật.
DELETE /api/admin/cards/[id] gọi deleteInvitationMedia(admin, id) sau khi xoá row; lỗi Storage chỉ log server, vẫn trả 204 (không hồi sinh row đã xoá). Kiểm chứng: test pin-source mới trong tests/admin-cards.test.ts, target 20/20, full suite 356/356, typecheck sạch.Spec docs/superpowers/specs/2026-10-07-mobile-first-design.md, plan docs/superpowers/plans/2026-10-07-mobile-first-plan.md (14 task, đã làm hết). Chỉ cộng thêm: mọi rule trong block @media (max-width: 767px) cuối file CSS (git diff -U0 HEAD -- '*.css' không có dòng bị xoá). Làm: token --m-*, viewport export (themeColor + interactiveWidget), header/menu sheet có nền tối/footer, hero Trang chủ (h1 ≤4 dòng, 2 nút cạnh nhau 44px), lưới mẫu 2 cột, /studio chọn mẫu trước, Editor và dialog thành sheet, form 16px, công cụ/blog/marketing. Sửa luôn lỗi có sẵn: /templates tràn ngang 712px ở 375px (flex-wrap còn sót của block ≤760px cũ). Công cụ đo mới: scripts/layout-probe.js + scripts/layout-diff.ts + lib/layout-audit.ts.
Kiểm chứng (Chrome DevTools MCP, bản production next start, qua proxy bỏ X-Frame-Options trong scratchpad để dùng iframe): desktop 768/1024/1280/1440px so baseline = 0 khác biệt; audit điện thoại 320/360/375/390/414px và ngang 667×375 = 0 finding (trước phase ở 375px: 969 = 946 vùng chạm + 22 input <16px + 1 tràn ngang); npm test 279 pass, typecheck sạch, build:next xanh; chụp tay 390px: Trang chủ, menu (chạm nền/Escape đóng), /templates, /studio. Miễn trừ có chủ đích: /templates/[id]?preview=1 và preview Studio giữ giá trị design (cùng renderer); nhóm chấm màu ≥24px.
Chưa chạy: Lighthouse (MCP trả toàn 0, không có CLI), Editor mở bằng link sửa thật, trang khách /invite/[slug] thật, form RSVP trên bàn phím ảo, iPhone/Android thật (bàn phím che ô nhập, thanh trình duyệt che thanh dưới Editor), ngang 844×390 và 768 dọc cho audit điện thoại. Console /studio có 4 cảnh báo preload ảnh next/image (eager ở StudioHome), chưa xác minh có sẵn từ trước hay không. Việc tiếp theo: chủ dự án xem tay trên điện thoại thật, commit (loại next-env.d.ts và .codegraph/daemon.pid, build tự sửa), rồi deploy theo DEPLOY.md mục 4c.
Cloudflare Workers thiep-cuoi-online, version a904e420, từ working tree (chưa commit; chủ dự án chọn “deploy nguyên trạng” gồm 3 bài nhạc thương mại + 4 ảnh mới chưa rõ giấy phép, rủi ro bản quyền do chủ dự án chịu). Build: NEXT_PUBLIC_SITE_URL=https://taothiepcuoi.raystudio.com.vn npm run build rồi npx wrangler deploy; env snapshot không có VERCEL_*. Smoke test taothiepcuoi.raystudio.com.vn và *.workers.dev: /, /templates, /studio, /thiet-ke-thiep-rieng, /demo, /blog, /sitemap.xml, nhạc, ảnh mới đều 200; trang Thiết kế riêng có hero mới + nút Zalo. Không đẩy migration: form /thiet-ke-thiep-rieng vẫn lỗi khi gửi cho tới khi push 202610030001_design-requests.sql (các migration chờ ở mục việc chờ). Rollback: DEPLOY.md mục 6. Việc còn lại: commit để git khớp production (git add app components lib public tests ...).
Chrome DevTools MCP: 11 route desktop 1280 + mobile 390 (emulate), 0 tràn ngang, 0 ảnh hỏng, 0 lỗi console; tương tác Studio (đổi mẫu, lọc, gõ tên), gallery (lọc, mount thẻ khi cuộn), form Thiết kế riêng. Playwright Firefox 156 + WebKit trên bản production (.next-perf): 14 route × 2 viewport × 2 engine = 56 lượt, 0 vấn đề; hero Trang chủ không đè chữ ở 360/390/430/500/768px trên cả 3 engine. Đã sửa: (1) hero Trang chủ mobile: thiệp 9:16 trồi lên đè chữ do khung .hm-stage thấp hơn thiệp (lỗi có từ trước), (2) form Thiết kế riêng thiếu name ở input, (3) ảnh đầu Studio thiếu eager (cảnh báo LCP). Chưa chạy: e2e, Lighthouse sau sửa, thiết bị thật (iOS Safari/Android), Edge. Còn nhắc: .next-perf xóa tay được.
/templates (2026-10-04, Claude Code)Đo bằng Lighthouse mobile trên bản production build riêng (NEXT_DIST_DIR=.next-perf next build, không đụng .next của dev; thêm distDir vào next.config.ts, .next-perf vào .gitignore). Trước: điểm 0.73, FCP 3.3s, LCP 5.5s, DOM 2861 node, HTML 661KB (103KB gzip). Sau: ~0.80, FCP ~2.56s, LCP ~4.3-4.9s, DOM ~1500, HTML 479KB (82KB gzip), CLS 0. Làm: (1) GalleryCatalog chỉ render sẵn 8 thẻ đầu + 5 thẻ rank đầu, phần còn lại là khung giấy cùng kích thước (class tp-root) mount khi cuộn gần (IntersectionObserver 800px; cuộn hết trang 42 → 0 khung, CLS 0); (2) content-visibility: auto cho thẻ lưới (padding + margin âm giữ bóng/hover). Còn lại: font ~408KB (Be Vietnam, Playfair, Cormorant, Great Vibes, mỗi họ 3 subset) là phần nặng nhất, cắt nữa phải đổi font/trọng số nên chưa làm; CSS cover (~80KB) bị nhân đôi do experimental.inlineCss. Các trang khác có cover (Trang chủ ~0.76) cùng nguyên nhân, chưa sửa.
Thêm 4 ảnh vào public/photos (nén ≤1200px): phong-phap-kem (mẫu D Hoàng Gia), han-quoc-nude (B Nét Mực), paris-vong-xoay (K Tem Thư, thay nang-chieu có watermark), may-hong-trai-tim (S Thư Tình, cắt 3:4 từ ảnh ngang); album sampleContent (demo + mọi trang /templates/[id]) dùng 4 ảnh này + 2 ảnh cũ. Bỏ 10/14 ảnh còn lại vì có logo/watermark (Weibo, Mimosa, iQIYI, tvN, Miss Studio, st.ggot, Palatino), ảnh sao/phim, hoặc phân giải thấp. Kiểm chứng: typecheck, 261/261 test, chụp 4 trang mẫu. Bản quyền 4 ảnh mới chưa rõ nguồn (gộp vào mục 1 việc chờ chủ dự án).
So design/ (20 mẫu, blog) với app; giữ nguyên catalog 50 mẫu và trang blog theo chủ dự án. Đã port: /thiet-ke-thiep-rieng (hero tối + 4 thẻ nổi, dải số liệu, bảng màu, form 2 cột; nút Zalo chỉ hiện khi có NEXT_PUBLIC_CONTACT_ZALO; số liệu thứ 3 viết “0đ để gửi yêu cầu” vì thiết kế riêng có báo giá), /studio split-screen (panel trái đổi màu theo mẫu + bộ lọc phong cách), rank rail của /templates (blob, shimmer, thanh %, sóng thẻ), Trang chủ (dải mẫu có tiêu đề/mask/hàng nhỏ ngược chiều, vòng xoay + đốm sáng ở band cuối), header (Đăng nhập đứng trước Tạo thiệp), tính năng mới “QR để in” (thẻ bàn tiệc / mặt sau thiệp / nhãn dán, components/studio/PrintQrPanel.tsx, nằm trong panel Phản hồi khi thiệp đã xuất bản). Kiểm chứng: typecheck sạch, 261/261 test, so ảnh design vs app ở 1280px + quét 4 trang ở 390/1280 (0 tràn ngang, 0 lỗi console); chưa chạy next build/e2e/Lighthouse (dev server của chủ dự án đang dùng .next).
Cố ý không port: (1) ô “Chụp thiệp giấy để AI điền sẵn” ở Studio (design chỉ mô phỏng, không có AI thật); (2) banner “Thông tin tiệc vừa cập nhật” + tab “Cập nhật thông tin” + nhắc Zalo/SMS (design chỉ giả lập bằng localStorage, cần backend); (3) công cụ Sơ đồ chỗ ngồi (đã gỡ có chủ đích, commit a1d7e25); (4) trang Quản lý thiệp dạng 4 tab (app đã có Khách/Phản hồi thật trong Studio). Cần chủ dự án xác nhận: số “24 giờ” ở hero Thiết kế riêng.
Root cause: Defer dùng IntersectionObserver từng card với rootMargin chỉ dọc (800px/0px), nhưng track marquee chạy ngang (~105px/s) — card ngoài khung ngang không bao giờ giao cắt observer cho tới khi animation đẩy vào, mất hàng chục giây (báo từ Zalo iPhone).
Fix (đã commit 8eb37a4): gate reveal theo SECTION qua sentinel observer (1200px) + hàng đợi revealSoon mount 6 card/frame qua rAF (kèm timeout flush) thay vì mount ồ ạt.
Verify sau restart: scroll tới track nhỏ → 50/50 card hiện (đếm DOM .tp-root có children; lưu ý covers sau rewrite dùng class tpR__*, không còn .cv-wrap), screenshot .playwright-mcp/qa-marquee-fixed-390.webp thấy đủ 7 card; typecheck 0 lỗi, test 279/279, build:next xanh, git diff --check sạch.
Audit trùng: 9/30 family bị thay bằng mẫu mới từ refs/ (ink-wash, edge-invite, pennant, duotone-script, floral-monogram, octagon-frame, rose-cluster, overlap-rings, floating-card); cả 30 cover viết lại (6 file CSS + 30 tsx, số SVG lượng giác làm tròn bằng r2 để hết hydration mismatch). Kiểm chứng: typecheck sạch, 257/257 test, build:next xanh, sweep 60 trang (30 mẫu × 390/1280px) 0 lỗi console/tràn ngang/ảnh hỏng. Chưa chạy: e2e, Lighthouse. process.md đã khôi phục từ git (test design-workflow-files cần). Mẫu nang-chieu: ảnh có watermark, chủ dự án thay ảnh.
Triển khai 30 mẫu mới XONG 12/12 + deep QA (catalog 50, chờ commit 1 lần): lệnh commit duy nhất ở nhật ký Task 12 (chưa chạy). Gate cuối xanh (typecheck + 257 test + build:next + git diff --check); browser sweep + deep QA Studio/khách/zoom xanh. Chưa deploy; CLAUDE.md (mục One renderer) vẫn ghi kiến trúc cũ — chủ dự án quyết có sửa file hợp đồng này không (agent không tự sửa).
Deep QA domain mới taothiepcuoimienphi.raystudio.com.vn (2026-10-04, đã dọn): sitemap đủ 50 mẫu; flow tạo thiệp full tính năng trên prod bằng template Duyên Tinh Tú (tên QC-Huong/QC-Duc) — Studio bật story/dresscode, thêm mốc, dialog Xuất bản chặn đúng khi thiếu tiêu đề/màu (86%→93%), xuất bản slug qc-duc-qc-huong; trang khách render đủ story/dresscode/tên, desktop + mobile 390 đều 0 tràn/0 ảnh hỏng/0 hydration error; đã unpublish thiệp QC (khách 404), prod sạch. Lưu ý: DNS mới đôi lúc resolve chập chờn từ máy dev (phải pin IP mới curl được, browser thì vào bình thường) — theo dõi. Studio mở bằng edit key thật — outline 18 mục/BƯỚC n/18, toggle 4 section mới, StoryPanel thêm/xóa mốc (1↔2/6), VideoPanel báo lỗi link inline, DressCode color input #1f3a5f + nhãn, VenuePanel đọc đúng event tiệc; dialog Xuất bản liệt kê đúng video thiếu URL/poster; trang khách story-led render đủ 4 section VI + EN, zoom 200% 6/6 collection reps sạch. Phát hiện 1 lỗi hạ tầng: bucket media chặn MIME video + giới hạn 8 MiB → đã thêm migration 202610040001_media-video.sql (chưa push, chung với các migration ở mục việc chờ). Thiệp QC (5k2mb9cl) đã unpublish (khách 404); còn 1 draft vô hình + 1 file poster rác — chủ dự án xoá tay trong Supabase dashboard khi rảnh.
Git khác production. Bản deploy 2026-10-04 build từ cây thư mục cũ; hiện có ~43 file thay đổi chưa commit, trong đó toàn bộ phase 30 mẫu mới (catalog 20→50, content v2, 4 section mới, video upload, 30 covers) vẫn nằm ở working tree. Lệnh commit duy nhất (không tách nhỏ): git add lib components tests docs DESIGN.md Guide-convert-html-design-to-code.md PROGRESS.md && git commit -m "feat: complete fifty-template catalog with thirty new designs" (loại next-env.d.ts, file này build tự sửa). Việc của chủ dự án: commit rồi mới build/deploy từ git, vì CI kéo từ git sẽ thiếu code mới.
Việc đang chờ chủ dự án (theo mức rủi ro):
music/ đã chép sang public/music/ (chưa deploy, chưa commit). Ảnh public/photos nhiều tấm có logo studio/CapCut/Douyin; 6 bài blog (đã lên production) dùng nhóm ảnh không logo nhưng giấy phép chưa rõ. Quyết định: xin phép/mua license hoặc thay bằng nhạc/ảnh miễn phí bản quyền (nhạc: sửa lib/music.ts + file trong public/music/).202610030001_design-requests.sql (chắc chắn chưa, nên form /thiet-ke-thiep-rieng đang lỗi khi gửi), 202609270001_account-analytics-donate.sql (bảng invitation_view_events; ngày 2026-09-27 chưa đẩy, route .../view trả 500), 202609280001_security-abuse-controls.sql (chưa xác minh) và 202610040001_media-video.sql + 202610040002_invitation-tiers.sql (mới 2026-10-04: bucket nhận video 50 MiB; cột tier/expires_at + cron ngày xoá thiệp hết hạn). Lệnh: DEPLOY.md mục 3 (npx supabase db push --db-url ...). Đổi gói tay sau khi push: update public.invitations set tier = 'premium' where slug = '<slug>'; (trigger tự tính lại expires_at; pro = vĩnh viễn).lib/blog/posts/*.ts), đặc biệt phần phong tục và cách dùng tính năng./blog và vài bài; các việc khác ở docs/superpowers/plans/2026-10-01-seo-growth-plan.md.NEXT_PUBLIC_CONTACT_EMAIL, đang trống) và rà soát pháp lý: /quyen-rieng-tu còn dòng “Vì MỘC chưa có tài khoản…” trong khi đã có đăng nhập Google. Agent không tự sửa văn bản pháp lý.Việc kỹ thuật tiếp theo:
/templates/[id] đã khớp mockup ở 390/1280px ngày 2026-10-04. (Riêng đợt 50 mẫu đã có browser sweep cuối phase: xem mục ▶, không thay thế P7 parity với design/.)/blog và vài trang chính (Phase 2 còn 71–86 performance).motion và embla-carousel-react (không còn import); route auth mồ côi register/login/forgot-password/resend-verification/reset-password (không UI nào gọi); docs/DEPLOY.md còn nói Netlify; design-parity-checklist.md còn ghi các mục “blocked: Supabase” đã làm xong.CLAUDE.md đã lỗi thời (dòng “Migration is not started”, “Legacy, still running today”, gate có ./mvnw test). Chủ dự án quyết định có sửa không; agent không tự sửa file hợp đồng này.| Mảng | Trạng thái |
|---|---|
| Catalog 50 mẫu (30 mới) | CODE XONG 12/12, CHƯA COMMIT, chưa deploy. 20 mẫu gốc dùng cover A–T; 5 mẫu Hỷ Sự/Vườn Ươm/Nhung Lam/Thư Tình/Chân Dung đã theo cover P–T của design hiện hành; 30 covers mới (components/templates/covers/, 6 collection) + content v2 (upgradeV1) + 4 section (Story/Video/DressCode/Venue) + video upload 50 MiB + Studio outline 18 mục. Nguồn 30 mẫu mới: ý tưởng rút ra từ việc phân tích 51 thư mục trong refs/ — 21 thư mục refs/chungdoi-com-vi-mau-thiep* (1 trang catalog + 20 mẫu demo Chung Đôi) và 30 thư mục refs/m-invite-com-template-preview-* (30 mẫu M-Invite) — nhưng toàn bộ ornament/CSS do đội tự vẽ (original), ảnh mẫu tái dùng ảnh public/photos/ có sẵn — không copy nguyên mẫu, branding, ảnh hay họa tiết nào từ website tham khảo (chi tiết từng family ở docs/design/template-asset-audit.md). Spec: docs/superpowers/specs/2026-10-04-thirty-new-templates-design.md, plan 12 task: docs/superpowers/plans/2026-10-04-thirty-new-templates-plan.md. Quy ước đang áp dụng: profile chỉ govern <main>; browser QA dồn 1 lần cuối phase (đã sweep xong, evidence .playwright-mcp/qa-50-*.webp). Việc tiếp theo: chạy lệnh commit ở mục ▶ rồi deploy theo DEPLOY.md mục 4c. |
Blog /blog + 6 bài |
XONG, đã deploy. Nội dung là dữ liệu TS (lib/blog/posts/*.ts, không MDX), render bằng components/blog/*, link “Blog cưới” ở cột “Khám phá” của footer. Thêm bài = 1 file trong lib/blog/posts/ + import ở lib/blog/index.ts. design/ không có mockup blog nên dựng từ token + primitive mk-* (ghi ở DESIGN.md). Chưa Lighthouse. |
| Nhạc có sẵn | Code xong, chưa deploy (rủi ro bản quyền ở trên). lib/music.ts (MUSIC_LIBRARY), contentSchema nhận link https hoặc đúng đường dẫn /music/<bài>.mp3, Studio có mục “Nhạc có sẵn” trong MediaPanel. |
Trang thiết kế riêng /thiet-ke-thiep-rieng |
Code đã deploy, backend chưa chạy được (thiếu migration). Form → POST /api/public/design-requests → bảng design_requests (xem đơn ở Supabase dashboard). |
| Hiện tên Google thay email | XONG, đã nằm trong bản deploy 2026-10-04 (chưa kiểm tra trên production vì cần đăng nhập Google thật): lib/server/auth.ts lấy full_name/name, header và /account hiện name ?? email; tài khoản không có tên vẫn hiện email. |
| E2E flow tạo thiệp | XONG. 14 test, API mock hoàn toàn (không chạm Supabase thật). Pass trên chrome, edge, mobile-chrome, coccoc-emulated, safari, mobile-safari, tablet-safari. Chưa chạy firefox và Cốc Cốc thật. Sau phase 50 mẫu (2026-10-04): chrome 26 + mobile-chrome 25 + mobile-safari 24 pass (mỗi project 1 skip có sẵn). |
| Script cào tham khảo | scripts/scrape-invitation.mjs (npm run scrape:ref, chụp/trích font-màu-section của trang thiệp mẫu vào refs/, tôn trọng robots.txt) và scripts/scrape-couple-photos.mjs (npm run scrape:couples, do chủ dự án thêm, chưa rà). refs/ và ảnh cào nằm ngoài git; chỉ để tham khảo, không copy ảnh/hoạ tiết (bản quyền). |
| Bugfix ngày cưới trên iPhone | XONG (2026-10-03): tạo thiệp chuẩn hoá ngày sang ISO và chặn ngày rỗng/không tồn tại. |
| SEO | Phase 1 + 2 + copy 50 trang mẫu ĐÃ DEPLOY 2026-10-12 (69896e0d). Bước 1–2 xong: lib/seo.ts, JSON-LD (lib/jsonld.ts), sitemap, manifest, tests/seo.test.ts. Phạm vi “không blog” ngày 2026-10-01 đã được chủ dự án thay bằng blog (2026-10-04). Plan: docs/superpowers/plans/2026-10-01-seo-pages-plan.md, 2026-10-01-seo-growth-plan.md. |
| Turnstile | Đã gỡ (2026-09-30, lý do và cách bật lại ở docs/security/incident-runbook.md); code xoá trong commit c61368c. .env.local của chủ dự án còn biến NEXT_PUBLIC_TURNSTILE_SITE_KEY thừa, nên xoá khi build Cloudflare (env shell bị snapshot vào bundle). |
design/*.dc.html 100%ScrollReveal, lớp motion (components/site/Motion.tsx), /, /bang-gia, /ung-ho, /tro-giup, /dieu-khoan, /quyen-rieng-tu, 4 landing SEO, /cong-cu-dam-cuoi, 6 /cong-cu/*, /templates (50 mẫu: 20 mẫu gốc A–T + 30 mới, popup “Xem thử”), /demo, nhánh auth (popup đăng nhập Google, /account), renderer thiệp + cổng phong bì + bìa ThiepPreview, Editor v3 (outline 18 mục, “BƯỚC n / 18”, công tắc bật/tắt từng phần, bottom sheet dưới 1024px)./templates/[id] đã đo khớp chiều cao <main> với design ở 390px (1373.546875px) và 1280px (848.890625px), không tràn ngang/ảnh hỏng/console error.design/ (python3 -m http.server 4100 trong design/) + next dev 3000; Chrome DevTools MCP chạy extractor computed style trên cả hai trang, lưu JSON vào .playwright-mcp/parity/, diff offline.?g=<token> (README design ghi ?to=); auth Supabase Google; QR bằng lib/tools/qr; gợi ý lời cảm ơn xoay 3 mẫu (không gọi AI); Q&A trợ giúp, văn bản pháp lý và copy “offline”/”không rời máy” ở hub công cụ theo sự thật sản phẩm; header dưới 760px dùng menu; bỏ SEO copy/liên quan ở 4 landing vì design không có; design/ chỉ đọc. Ảnh mẫu public/photos chỉ dùng ở trang giới thiệu/xem thử/blog; thiệp thật (trang khách + xem trước Editor) để khung trống.Spec docs/superpowers/specs/2026-09-26-supabase-migration-design.md, plan docs/superpowers/plans/2026-09-26-supabase-migration.md (Task 1–9 xong, remote cutover và E2E remote 16/16 xong 2026-09-26; thiệp demo ho6my9vg). Hardening bảo mật: docs/superpowers/plans/2026-09-28-nextjs-supabase-security-hardening.md, runbook ở docs/security/.
#k= (không cần tài khoản để tạo/sửa thiệp); link khách ?g=<token> (tên resolve từ DB, không gắn tên trên URL); public write đi qua Next Route Handler rồi Supabase Edge Function; RLS không cho browser ghi trực tiếp; service-role key chỉ ở server; lib/api.ts là seam duy nhất giữa UI và API.iehmucsshklgjmxqyggp. Key mới: NEXT_PUBLIC_SUPABASE_ANON_KEY = publishable (sb_publishable_...), SUPABASE_SERVICE_ROLE_KEY = secret (chỉ server). Secret tự tạo EDGE_SHARED_SECRET và RATE_LIMIT_HMAC_SECRET; tên SUPABASE_EDGE_SHARED_SECRET bị CLI từ chối vì tiền tố SUPABASE_. Không ghi giá trị secret vào file.202609260001_backend.sql (5 bảng + RLS + Storage + Realtime + rate limit), 202609270001_account-analytics-donate.sql, 202609280001_security-abuse-controls.sql, 202610030001_design-requests.sql. Supabase chưa có down-migration: sửa bằng migration mới.public-write: npx supabase functions deploy public-write; bucket media public; Auth tắt confirm email (mailer_autoconfirm: true)./ung-ho có QR VietQR; webhook app/api/webhooks/[provider] (casso/sepay) đã có, cần CASSO_WEBHOOK_SECRET/SEPAY_WEBHOOK_SECRET nếu bật.| Phase | Nội dung | Trạng thái |
|---|---|---|
| P1 | Design system core: app/styles/tokens.css, motion.css, font script/hand, primitives, guard test |
XONG (2026-09-26) |
| P2 | Hex rời → token | XONG: 0 hex ngoài tokens.css (test tests/design-system.test.ts giữ) |
| P3 | Port từng trang | XONG port; nghiệm thu theo P7 |
| P4 | Studio Editor v3 | XONG layout và các trường (rank, arrivalTime, bật/tắt phần, bố cục album, lịch trình, phong bì) trong contentSchema |
| P5 | Trang khách theo Thiep Khach |
XONG |
| P6 | Nghiệm thu cuối | Checklist docs/superpowers/specs/2026-09-26-design-parity-checklist.md (một số dòng “blocked” đã lỗi thời) + e2e tạo thiệp; còn quét thủ công trang khách và editor trên Supabase thật |
| Phase | Nội dung | Xong | Còn lại |
|---|---|---|---|
| 1 | Lõi thiệp: mẫu, Studio, trang khách, RSVP, lời chúc, QR mừng cưới, bản đồ, đếm ngược, nhạc, album | ~93%, đã deploy production (T28 xong) | Xác minh migration remote; e2e trang khách với dữ liệu thật |
| 2 | Marketing: home, templates, trợ giúp, blog, giá, pháp lý | ~92% | Lighthouse mobile (71–86); email liên hệ; rà soát pháp lý |
| 3 | Guest manager: nhóm/bàn, link ?g=, thống kê RSVP |
~95% | Quyết định chủ dự án (gửi hàng loạt SMS/Zalo, giới hạn số khách) |
| 4 | 6 công cụ miễn phí /cong-cu/* (tạo QR, nén ảnh, nén video, tin nhắn mời, danh sách khách, save the date; sơ đồ chỗ ngồi đã gỡ) |
~100% | Câu hỏi mở ở spec mục 9 |
| 5 | Song ngữ vi/en (?lang=) |
100% | QA trên URL production |
| 6 | Tài khoản Google + claim thiệp + Donate | Xong | QA trình duyệt /ung-ho |
/blog, chỉ dùng token và primitive DS.--hand.--faint #8a7d72, --on-dark-faint #7d7067); không lệch màu để đạt AA.Danh sách việc ưu tiên nằm ở mục ▶. Còn lại:
2026-10-01-seo-growth-plan.md; agent chỉ soạn nội dung.../Thiep-cuoi-online-backend còn code Phase 6A chưa commit; chỉ cần nếu muốn giữ làm tham chiếu (git -C ../Thiep-cuoi-online-backend add -A && git commit).251096d7: thêm /llms.txt + lastmod mẫu; npm test 373/373, build Cloudflare, smoke prod 200.69896e0d: sửa lỗi 50 trang mẫu bị noindex trên prod (OpenNext has: query thiếu value), thêm copy riêng 50 trang mẫu, HSTS + redirect http→https, email liên hệ. Kiểm chứng ở mục ▶.organization() trong lib/jsonld.ts (1 @id toàn site, contactPoint/address/sameAs chỉ có khi env có giá trị) dùng ở / và trang mới /ve-moc (PageHero + mk-prose, link ở cột “Hỗ trợ” footer, ghi lệch design ở DESIGN.md); withShareImage() trong lib/seo.ts cho blog + template; /bang-gia FAQ 3→7 câu từ /tro-giup. Kiểm chứng ở mục ▶.2026-10-11 SEO Phase 1 (code, chưa deploy): port bộ skill claude-seo v2.4.2 sang global opencode + audit production → Health 72/100 (report: qa-evidence/seo-audit-20261009/). Fix 10 mục không cần input chủ: dialog-H2→p toàn site, /docs noindex + self-canonical, dedup robots 404, publisher.logo (public/logo.png mới) + Organization enrich, Product/Offer 0đ /bang-gia + FAQPage (3 câu reuse /tro-giup) + FAQ section, Product + og:image từng template, image vào ItemList 50 mục, alt tiếng Việt 36 chỗ, aspect-ratio chống CLS, CTA meta + H1/H2 keyword (/, /templates, /bang-gia). Kiểm chứng: tsc sạch, 353/353 test, e2e all-pages 161/161 (firefox skip), curl xác nhận Product/FAQPage/ItemList-images/docs-noindex. Còn lại cần chủ: bật Always-HTTPS Cloudflare, email/sđt/địa chỉ + social + review thật, API key Google, copy dài 50 trang template.
design/Thiep Preview.dc.html, giữ ID/copy/profile và trang blog nguyên trạng. TDD registry/renderer đỏ→xanh; gate 261/261 test + typecheck + build:next + diff-check xanh. Playwright 390/1280: 5 trang chi tiết, /templates, /blog đều 200, 0 tràn ngang/ảnh hỏng/console error; catalog render đủ 50 card./templates/[id]: bỏ đoạn SEO copy bị render dư trong nội dung, dùng đúng mô tả bố cục familyLayout như Mau Thiep Chi Tiet.dc.html; SEO copy vẫn giữ trong metadata. Regression test red→green; Playwright đo <main> app/design bằng nhau ở 390px (1373.546875px) và 1280px (848.890625px), 0 tràn ngang/ảnh hỏng/console error.202610040002_invitation-tiers.sql — cột tier (free 7 ngày / plus 30 ngày mặc định / premium 1 năm / pro vĩnh viễn) + expires_at (trigger tự tính khi tạo/đổi gói; thiệp cũ được grace 30 ngày từ lúc push) + cron pg_cron hằng ngày purge-expired-invitations xoá cứng row quá hạn và unlink file media/<id>/* (file vật lý cần vacuum tay, xem comment trong migration). pgTAP supabase/tests/backend.sql lên plan(44) với 8 test tier/purge. Kiểm chứng: node suite 257/257 + typecheck sạch (DB test chưa chạy được local vì không có Docker — chạy npm run db:test hoặc CI sau khi push)./templates → 50 mẫu; marketing còn lại đã dynamic), DESIGN.md + Guide map + PROGRESS cập nhật 50 mẫu/18 mục, sitemap/route-inventory dynamic đủ 50 route, audit cuối (không file nào dưới public/templates/, manifest rỗng hợp lệ), premium audit strict 2 lỗi ngoài phạm vi (form /templates, scrollbar tro-giup, cả hai có sẵn trước phase), gate cuối + e2e 3 project + browser sweep xanh, evidence .playwright-mcp/qa-50-*.webp. Lệnh commit duy nhất:
git add lib components tests docs DESIGN.md Guide-convert-html-design-to-code.md PROGRESS.md && git commit -m "feat: complete fifty-template catalog with thirty new designs"expressive.css. Kiểm chứng: full suite 257/257, typecheck sạch, build:next xanh.story.css. Kiểm chứng: full suite 256/256, typecheck sạch, build:next xanh.quiet-luxury.css, không gradient/trang trí dày. Kiểm chứng: full suite 256/256, typecheck sạch, build:next xanh.editorial.css. Kiểm chứng: full suite 256/256, typecheck sạch, build:next xanh.garden.css, meta + registry + samples + SEO. Kiểm chứng: full suite 256/256, typecheck sạch, build:next xanh.lib/covers.ts (meta thuần, splitCoverDate), covers/{types,slot,index} + heritage.css, 5 covers theo brief (mỗi mẫu 1 signature, ornaments original inline, reduced-motion, tên dài wrap). Kiểm chứng: test đích 22/22, full suite 256/256, typecheck sạch, build:next xanh.lib/maps) + profile-driven renderer (envelope/shell giữ nguyên, <main> map theo profile). Kiểm chứng: test đích 16/16, full suite 252/252, typecheck sạch, build:next xanh.build:next xanh.File.type), tối đa 50 MiB cả server/client/route, uploader dùng chung primitive. Kiểm chứng: test đích 22/22, full suite 249/249, typecheck sạch, build:next xanh.normalizeContent mirror toggle, publishIssues và persistable mở rộng. Kiểm chứng: test đích 16/16, full suite 247/247, typecheck sạch.profile: "default" cho 20 mẫu. Kiểm chứng: test đích 21/21, full suite 242/242, typecheck sạch, build:next xanh, catalog vẫn 20.git diff --check sạch.refs/ và 20 mẫu hiện có; thay thiết kế cover-only bằng kiến trúc Hybrid, chốt 30 concept/6 collection, section profile, bốn section mới và asset audit. Kiểm chứng: 30 family slug duy nhất, không placeholder, git diff --check sạch sau khi sửa./tinh-nang, số test cũ), các blocker Netlify/tên miền (đã chạy Cloudflare + domain thật), mục migration “TIẾP THEO” (đã làm); thêm production, git≠production, migration chưa xác minh, Turnstile đã gỡ, scraper, hiện tên Google, CLAUDE.md lỗi thời. Kiểm chứng: đối chiếu với git log/status, app/, supabase/migrations, package.json, wrangler.jsonc, docs.e0f3ebe1): gate xanh (test 224/224, tsc, diff-check), build với NEXT_PUBLIC_SITE_URL chính thức, smoke test trên workers.dev và domain chính (/, /blog, bài, sitemap 7 URL blog, 404 slug sai, ảnh /_next/image). Bản chứa trang thiết kế riêng nhưng form lỗi do thiếu migration.playwright.config.ts, e2e/create-invitation.spec.ts (14 test), e2e/support/mock-api.ts. 14/14 trên 7 project; WebKit desktop trên macOS tự abort khi gõ trong editor (NSTextInputContext), test dùng setText qua DOM cho nhánh đó.lib/music.ts, public/music/*, schema + MediaPanel; test 227/227 (file tồn tại, header MP3, ≤ 8 MB, schema từ chối /music/../x). Chưa kiểm tra trên trình duyệt vì Studio cần tạo thiệp thật.AccountUser.name, userDto, header và /account; test auth-routes cập nhật (đã vào bản deploy cùng ngày, chưa thử trên production).blogPosting JSON-LD, sitemap, route-inventory, footer. Kiểm chứng: test 224/224, next build sạch, curl (1 h1, title ≤ 60, canonical, JSON-LD, sitemap, 404), DevTools 1280 + 390 không tràn ngang, 0 ảnh hỏng, 0 lỗi console.scripts/scrape-invitation.mjs (--crawl, --suffix, --limit; tự bấm “Mở thiệp”; bỏ qua mẫu đã chụp); thử trên 3 trang, ra cover/mobile/desktop/page.html/tokens.json.app/thiet-ke-thiep-rieng/, DesignRequestForm, lib/design-request.ts, route + migration design_requests; 214 test, build OK, 390px không tràn ngang.StudioHome chuẩn hoá DD/MM/YYYY/YYYY-MM-DD thành ISO, chặn ngày không tồn tại; test hồi quy.next/font: mỗi loader là const cấp module, option phải literal, biến font đặt trên <html>.node --test chỉ nhận TypeScript “erasable”: không enum, không parameter properties; file trong lib/ mà test import phải dùng import tương đối có đuôi .ts (không @/).NEXT_PUBLIC_SITE_URL=https://taothiepcuoi.raystudio.com.vn npm run build rồi npx wrangler deploy. Build snapshot toàn bộ env vào .open-next/cloudflare/next-env.mjs (có service-role key, chạy server-side; kiểm tra không lọt biến lạ như VERCEL_*). rm -rf bị hook chặn: bản build tự dọn .open-next, không cần xoá tay. Netlify dùng npm run build:next.npm run build:next && npm run e2e -- --project=chrome (project: chrome, edge, safari, firefox, coccoc, mobile-safari, mobile-chrome, tablet-safari). WebKit cài bằng npx playwright install webkit (đã cài), Firefox chưa. Chạy từng project một, workers: 1. Test mock mọi /api/** và fail nếu có call chưa mock, vì build trỏ vào Supabase thật.X-Frame-Options: không nhúng iframe cùng origin để quét nhiều route trong DevTools (contentDocument rỗng); điều hướng từng route. Chụp màn hình trong Chrome DevTools MCP cần select_page với bringToFront trước, nếu không sẽ timeout; emulate mới đổi được viewport (resize cửa sổ không đổi innerWidth).Motion.tsx/ScrollReveal ẩn phần dưới màn hình tới khi cuộn: khi chụp so sánh phải cuộn chậm hết trang (cuộn quá nhanh bỏ sót reveal). Nội dung vẫn có trong view-source cho crawler.next start báo không hợp với output: standalone nhưng vẫn chạy cho mục đích test cục bộ.emulate viewport 390x844x2,mobile,touch.codegraph serve rò rỉ có thể gây ENFILE. Kiểm sysctl kern.num_files kern.maxfiles, hỏi chủ dự án trước khi kill.git commit (hook chặn): đưa lệnh cho chủ dự án.DELETE /api/invitations/:id đã có)./lien-he, RSS blog.