Cloudflare's deploy log has been flagging the SPA fallback rule (/* /index.html 200) as a false-positive infinite loop and ignoring it on every deploy. Investigated live: direct navigation to /about, a dynamic route, and a genuinely invalid path all return 200 with the correct content already, since Cloudflare Pages' own default fallback serves index.html for any unmatched path. The rule was dead weight -- removing it to stop the recurring warning noise. Closes the tracked issue in CLAUDE.md. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
3.2 KiB
3.2 KiB
MSDL — Claude Context
Project
Open-source Windows ISO downloader. React + Go. Live at msdl.tech-latest.com.
Frontend on Cloudflare Pages, backend on Hetzner via Coolify.
Outbound Microsoft API calls route through a Cloudflare Worker (cloudflare-worker/worker.js)
controlled by CF_WORKER_URL + CF_WORKER_SECRET env vars on the backend.
Conventions
- Small config/one-liner fixes → commit directly to main
- Any meaningful feature or multi-file change → feature branch → PR → merge
- GitHub issues are for bugs and community contributions only — planned features tracked here and in PROGRESS.md
- Commit messages follow conventional commits:
feat:,fix:,docs:,chore: - Always test locally before committing or pushing — research feasibility before implementing (e.g. file size was planned but Microsoft CDN doesn't return it; caught after commit)
Backlog (implement when ready, in priority order)
#12 — Two-layer in-memory caching ✅ DONE (feat/caching-layer, merged)
All 7 items shipped: singleflight, SKU cache (7d TTL), link cache (dynamic TTL from se param),
negative cache (60s), dynamic TTL, stale-on-failure, jitter. Verified in production.
Beyond #12 — Observability & resilience
- Cache hit/miss logging — logged on every request (fetched vs cached, cached until timestamp).
/metricsendpoint (auth-protected) — exposes cache hit rate, miss count, stale serves. Auth viaMETRICS_SECRETenv var. (feat/metrics, merged)- README architecture section — caching layer,
/metrics, env vars documented. - Per-IP / per-product rate limiter — deferred; revisit after 1 month of production traffic data.
Frontend UX improvements ✅ DONE (feat/ux-improvements, merged — v1.2.0)
- Expiry countdown — parses
separam from signed URL where available; falls back to "24 hours" for consumer links (Microsoft doesn't includesein consumer CDN URLs). - Refresh links —
?force=trueon/proxybypasses cache, fetches fresh from Microsoft. Button shown when under 6h remaining. - CLI command tabs — wget / curl / aria2 tabs, persists selection in localStorage. Replaces old aria2-only tip. Applied to both consumer and eval pages.
- Recently viewed — localStorage only. Shows on homepage. Consumer + eval pages both tracked. Expired state shown when link expiry known.
File size— not feasible. Microsoft CDN does not return file size in the API response.
Known bugs / open issues
_redirectsCloudflare Pages — investigated 2026-07-21. The rule was indeed ignored (Cloudflare's deploy log flags it as a false-positive infinite loop), but this turned out to be a non-issue: Cloudflare Pages' own default fallback already servesindex.htmlfor any unmatched path, so the explicit rule was redundant. Verified live: direct navigation to/about, a dynamic route (/product/3262), and a genuinely invalid path all return HTTP 200 with the correct content (including React Router's own 404 page for the invalid one). Removedfrontend/public/_redirectsentirely to stop the recurring deploy warning.