| name | winning-web-speed-hackathon |
| description | Optimizes deliberately slow web applications for maximum Lighthouse scores in Web Speed Hackathon (CyberAgent). Use when participating in WSH or performing aggressive frontend performance optimization on React/Node.js apps with SQLite backends. Covers bundle reduction, image optimization, Core Web Vitals, server tuning, and known competition traps. |
Winning Web Speed Hackathon
Systematic workflow to maximize Lighthouse scores in CyberAgent's Web Speed Hackathon. The competition provides a deliberately de-tuned React + Node.js app; your job is to optimize it while passing VRT and regulation checks.
Use this skill when participating in Web Speed Hackathon, or aggressively optimizing a React/Node.js web app for Lighthouse Performance scores.
Scoring Model (WSH 2026)
Total: 1150 points (9 pages × 100 pts + 5 user flows × 50 pts)
Page display scoring weights (per page, 100 pts):
- CLS x25 | FCP x10 | LCP x25 | SI x10 | TBT x30
User flow scoring (per flow, 50 pts): INP x25 + TBT x25
Condition: Page display score < 300 pts → user flow scores = 0 pts.
LCP and TBT dominate. Prioritize accordingly.
Scoring Tool (in-repo)
This repo includes an official scoring tool at scoring-tool/. Run it locally:
cd scoring-tool && pnpm install
pnpm start http://wsh.localhost:1355
pnpm start http://wsh.localhost:1355 --targetName "ホームを開く"
Available target names:
- 通常テスト (9): ホームを開く, 投稿詳細ページを開く, 写真つき投稿詳細ページを開く, 動画つき投稿詳細ページを開く, 音声つき投稿詳細ページを開く, 検索ページを開く, DM一覧ページを開く, DM詳細ページを開く, 利用規約ページを開く
- ユーザーフロー (5): ユーザーフロー: ユーザー登録 → サインアウト → サインイン, ユーザーフロー: DM送信, ユーザーフロー: 検索 → 結果表示, ユーザーフロー: Crok AIチャット, ユーザーフロー: 投稿
Phase 0: Reconnaissance (First 30 min)
- Clone and run the app locally. Confirm it builds and serves.
- Run scoring tool locally on all scored pages. Record baseline scores:
cd scoring-tool && pnpm start http://wsh.localhost:1355
- Analyze the bundle:
npx webpack-bundle-analyzer dist/stats.json
- Check Chrome DevTools:
- Network tab: Identify largest transfers, uncompressed assets, no-cache headers
- Coverage tab (Ctrl+Shift+P → "Coverage"): Find unused JS/CSS percentage
- Performance tab: Record page load, identify long tasks and layout shifts
- Scan for known traps — see WSH-KNOWN-TRAPS.md
- Read the regulation/checklist carefully. Know what you cannot break.
- Prioritize fixes by estimated score impact. Work top-down.
Phase 1: Build & Bundle (Highest Impact)
These fixes often yield 50-200+ point gains.
- Fix build mode: Ensure
NODE_ENV=production and bundler mode: 'production'
- Remove source maps: Delete
devtool: 'inline-source-map' or similar
- Kill bloated dependencies: Check for and remove/replace:
@iconify/json, @ffmpeg/ffmpeg, zengin-code, moment-timezone → dayjs
lodash → native JS or lodash-es (tree-shakeable)
canvaskit-wasm, Three.js → simple HTML/CSS/<img>
- Full icon sets → only used icons
- Enable tree shaking: Remove
@babel/plugin-transform-modules-commonjs
- Code split routes:
React.lazy() + <Suspense> per route
- Target modern browsers: Set browserslist to
last 1 Chrome version
- Minify everything: Ensure terser/esbuild minification is active
- Consider Preact: Drop-in replacement, ~3KB vs ~40KB for React
Details: BUNDLE-OPTIMIZATION.md
Phase 2: Images & Fonts (High Impact)
- Convert images to AVIF (best) or WebP. Use Sharp or ImageMagick.
- Resize to actual display dimensions (not 4000px originals)
- Convert animated GIFs to WebM/MP4
<video> elements
- Add
loading="lazy" to below-fold images, fetchpriority="high" to LCP image
- Add explicit
width/height to all <img> (prevents CLS)
- Subset fonts to used characters only (pyftsubset/glyphhanger)
- Add
font-display: swap and preload critical fonts
Details: IMAGE-AND-FONT-OPTIMIZATION.md
Phase 3: Network & Server (Medium-High Impact)
- Enable compression: gzip/Brotli middleware (e.g.,
@fastify/compress)
- Set Cache-Control:
max-age=31536000, immutable for hashed static assets
- Remove artificial delays: Search for
setTimeout, sleep, delay, jitter in server code
- Fix N+1 queries: Add JOINs or batch loading. Add DB indexes.
- Add resource hints:
<link rel="preconnect">, <link rel="preload"> for critical assets
- Remove
no-store cache headers on static resources
- Parallelize API calls:
Promise.all() instead of sequential fetches
Details: NETWORK-AND-SERVER.md
Phase 4: CSS & Rendering (Medium Impact)
- Remove runtime CSS-in-JS: Replace UnoCSS runtime / styled-components with static CSS
- Extract critical CSS: Inline above-fold CSS in
<head>
- Remove unused CSS: PurgeCSS or manual removal
- Fix CLS sources: Add
aspect-ratio, explicit dimensions, font fallback metrics
- Defer non-critical CSS: Load below-fold styles asynchronously
- Add
defer to all non-critical <script> tags
Details: RENDERING-AND-CSS.md
Phase 5: Runtime & Interaction (For INP/TBT)
- Fix ReDoS: Check regex patterns for catastrophic backtracking (email/password validators)
- Break long tasks: Use
scheduler.yield() or setTimeout(0) to yield to main thread
- Optimize React renders:
React.memo, useMemo for expensive computations
- Virtualize long lists:
react-window or @tanstack/virtual
- Replace heavy hover handlers: Use
onMouseEnter/onMouseLeave instead of onMouseOver
- Remove unnecessary animations: framer-motion, CSS transitions on layout properties
Phase 6: SSR & Advanced (If Time Permits)
- Implement SSR: Stream HTML with
renderToPipeableStream for instant FCP/LCP
- Move to Vite: If stuck with Webpack dev mode, migrate for better DX and build
- Deploy static assets to CDN: Cloudflare Pages or similar
- Service Worker: Cache static assets for repeat visits (if required by rules)
Validation Loop
After every major change:
1. Build → verify no errors
cd application && pnpm run build
2. Start the server via portless
portless proxy start 2>/dev/null || true
cd application && portless wsh pnpm run start &
3. Run scoring tool on affected pages
cd scoring-tool && pnpm start http://wsh.localhost:1355 --targetName "ホームを開く"
# Or run all targets:
cd scoring-tool && pnpm start http://wsh.localhost:1355
4. Run VRT (e2e tests)
cd application/e2e && E2E_BASE_URL=http://wsh.localhost:1355 pnpm exec playwright test
# Single test file:
cd application/e2e && E2E_BASE_URL=http://wsh.localhost:1355 pnpm exec playwright test src/home.test.ts
5. Compare scores to previous baseline
6. Commit working state before next optimization
VRT config: maxDiffPixelRatio: 0.03 (3% pixel diff tolerance), Desktop Chrome 1920x1080.
Never skip VRT. Regulation violations = disqualification.
Time Management (31-hour competition)
| Hours | Focus | Expected Impact |
|---|
| 0-0.5 | Recon & analysis | Baseline established |
| 0.5-4 | Build/bundle fixes | +100-300 pts |
| 4-8 | Image/font optimization | +50-150 pts |
| 8-14 | Server/network/API | +30-100 pts |
| 14-20 | CSS/rendering/CLS | +20-80 pts |
| 20-26 | Runtime/INP/TBT polish | +10-50 pts |
| 26-30 | SSR/advanced if needed | +20-100 pts |
| 30-31 | Final VRT check & deploy | Safety margin |
Reference Files