diff --git a/.gitignore b/.gitignore index cdee5d4..f3d4698 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,9 @@ node_modules/ **/.claude/ test-results/ playwright-report/ -.husky/ +.husky/_/ .hoangsa/ + +# Temp screenshot/artifact files +_*.png +_*.js diff --git a/.hoangsa/sessions/chore/audit-full-codebase/AUDIT-REPORT.md b/.hoangsa/sessions/chore/audit-full-codebase/AUDIT-REPORT.md deleted file mode 100644 index 3c2b946..0000000 --- a/.hoangsa/sessions/chore/audit-full-codebase/AUDIT-REPORT.md +++ /dev/null @@ -1,141 +0,0 @@ -# AUDIT REPORT — weekend-go-web - -**Date:** 2026-04-14 -**Scope:** Full audit (9 dimensions, deep mode) -**Codebase:** 4 HTML pages + 2 JS + 2 CSS + Tailwind config (~2,259 LOC excluding compiled CSS) -**Stack:** HTML5 + TailwindCSS 3.4.19 (CLI) + Vanilla JS — static landing page for "Cuối Tuần Đi Đâu" app - ---- - -## Executive summary - -| Severity | Count | -|----------|-------| -| 🔴 Critical | 0 | -| 🟠 High | 9 | -| 🟡 Medium | 17 | -| 🟢 Low | 12 | -| **Total** | **38** | - -**Health rating:** 🟡 Solid foundation, several structural debts. No critical security issues. Codebase is small and approachable but lacks abstractions appropriate for a 4-page multi-page site (heavy duplication). No tests, no CI, no deploy config committed. - -**Three biggest themes:** -1. **HTML duplication** — Same nav/footer/CTA/SVG markup copy-pasted across 4 pages. Drift already started. Time bomb for brand updates. -2. **Build/deploy gap** — README says "no build step" but Tailwind CLI is required. No CI verifies builds. No deploy config in repo. No way to confirm `assets/css/styles.css` is fresh. -3. **Accessibility blind spots** — Carousel autoplays without `prefers-reduced-motion`. Malformed `

...

` HTML on legal pages. Skip-link missing. - -**What's already good:** -- Zero critical vulnerabilities. `npm audit` clean. -- `` + WebP fallback used throughout (good perf foundation). -- Hero LCP preloaded with `fetchpriority="high"`. -- All `` have meaningful Vietnamese alt text. -- Decorative SVG icons consistently `aria-hidden="true"` (20+ occurrences). -- `` consistent across all 4 pages. -- OG/Twitter meta on all pages. -- Single `

` per page. -- `defer` on all JS scripts. -- Carousel pauses on `visibilitychange`. -- `.editorconfig` present. - ---- - -## Roadmap — 5 themes ordered by ROI - -### 🎯 Theme 1 — Quick wins (cleanup, ≤ 30 min each) -**Impact:** Removes obvious bugs + fixes invalid HTML. Total: ~1 hour. - -| ID | Action | Effort | Severity | -|----|--------|--------|----------| -| A11Y-001 / ARCH-002 | Fix `

...

` mismatched closers in `terms.html`, `privacy.html`, `community-standards.html` (6 occurrences total) | 5 min | HIGH | -| SEC-001 | Add `node_modules/`, `.env*`, `.hoangsa/`, `.claude/` to `.gitignore` | 1 min | HIGH | -| CQ-005 / SEC-003 | Delete inline `` inline. Duplicates a rule already in `src/input.css`. -- Impact: forces `'unsafe-inline'` in any future `style-src` CSP. -- Suggested fix: remove the inline block — rule already exists in `assets/css/styles.css` via `src/input.css`. -- Effort: 1 min. - -### SEC-004 — Plaintext mailto exposes `hello@cuoituandidau.vn` to scrapers [LOW / informational] -- Location: index.html:1290, privacy.html:188,218, terms.html:172,202, community-standards.html:162,185,215 -- Evidence: email appears as plain text in HTML. -- Impact: spam harvesting. Acceptable for a contact address; note only. -- Suggested fix: optional — use a contact form, Cloudflare email obfuscation, or split/encode the address in the rendered text while keeping `href="mailto:"`. -- Effort: n/a unless spam becomes a problem. - -### SEC-005 — Third-party hosts loaded at runtime [LOW / informational] -- Location: all four HTML files, `` in `` -- Evidence: only two external origins: `fonts.googleapis.com` (Google Fonts CSS) and `fonts.gstatic.com` (font files). No analytics, no trackers, no tag managers, no CDNs for JS. -- Impact: minimal. Both are well-known Google hosts; privacy policy should mention Google Fonts data collection (IP logging) for GDPR-style compliance. Consider self-hosting Inter if privacy is a concern (Germany has ruled runtime Google Fonts = GDPR violation). -- Suggested fix: either self-host Inter woff2 files (saves one preconnect + decouples from Google), or reference Google Fonts usage in privacy.html. -- Effort: 30 min to self-host. - -### PERF-001 — Raw PNG duplicates waste ~4.76 MB of repo storage [MEDIUM] -- Location: `assets/images/ai-review.png`, `plan-list.png`, `share-review.png`, `weekend-plan.png` -- Evidence: these `.png` files are not referenced anywhere in HTML; only their `.webp` variants are used (index.html:946,966,936,956). No `` fallback wrapper is used for these carousel images. -- Impact: bloated clone/deploy. At 836 KB–1.47 MB each they were originally intended as `` fallbacks but the `` tags reference `.webp` directly with no `` fallback. -- Suggested fix: either (a) delete the unused PNGs, or (b) wrap each carousel `` in `` for Safari <14 / legacy fallback. Given target audience (mobile-first Vietnam, modern browsers) option (a) is fine. -- Effort: 5 min (delete) or 15 min (wrap). - -### PERF-002 — og:image / twitter:image on legal pages point at 544 KB PNG [MEDIUM] -- Location: privacy.html:16,22; terms.html:16,22; community-standards.html:16,22 -- Evidence: `og:image` and `twitter:image` = `https://cuoituandidau.vn/assets/images/hero-banner-desktop.png` (544 KB). index.html correctly uses the `.webp` variant (30.9 KB). -- Impact: social crawlers (Facebook, LinkedIn, iMessage, Slack) fetch 544 KB per share of a legal page. Slow preview generation, wasted bandwidth. Note: some platforms historically don't accept webp for og:image; PNG is safer but a smaller, resized (1200×630) dedicated OG image would be ideal. -- Suggested fix: create a 1200×630 JPEG or PNG around 80–150 KB dedicated for OG (e.g. `og-cover.jpg`) and reference it from all pages including index.html. -- Effort: 30 min (design + export + swap meta). - -### PERF-003 — Google Fonts stylesheet is render-blocking [MEDIUM] -- Location: index.html:63-66; privacy.html:27-28; terms.html:27-28; community-standards.html:27-28 -- Evidence: `` is synchronous. Even with `display=swap`, the CSS request blocks render. Legal pages do a `` but don't use the `onload` swap trick, so the preload is redundant. -- Impact: one extra round-trip (~100–300 ms) to fonts.googleapis.com before first paint. Not catastrophic but measurable in FCP. -- Suggested fix: self-host Inter (preferred — also solves SEC-005 and eliminates two DNS lookups) or convert to the async pattern: `` with a `