Commit graph

66 commits

Author SHA1 Message Date
Shekhar Vaidya
0557339e72 chore: remove .claude/ from git tracking, add to .gitignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 21:07:10 +05:30
Shekhar Vaidya
1c54c36d03 feat: expiry countdown, refresh links, CLI tabs, recently viewed, file size support
- Backend: ?force=true on /proxy bypasses cache for fresh link fetch
- Frontend: parse `se` param for live expiry countdown on download links
- Frontend: show Refresh button when link expires in <6h, force-fetches fresh URL
- Frontend: CliCommand component replaces Aria2Tip — wget/curl/aria2 tabs, persists selection in localStorage
- Frontend: RecentlyViewed component — localStorage, shows active countdown or expired state
- Frontend: FileSize shown alongside arch if returned by Microsoft CDN

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 21:06:17 +05:30
Shekhar Vaidya
e3f34016c6 chore: plan frontend UX improvements — expiry countdown, refresh, CLI tabs, recently viewed, file size
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 20:54:55 +05:30
Shekhar Vaidya
17315ad4e9 docs: add PROGRESS.md with full shipping history and production metrics
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 16:27:19 +05:30
Shekhar Vaidya
efe0c241ab chore: update CLAUDE.md — mark #12 and Beyond #12 items complete, defer rate limiter
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:34:21 +05:30
Shekhar Vaidya
825c825686 docs: document caching architecture, /metrics endpoint, and env vars in README
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:29:42 +05:30
Shekhar
ca4a89589b
Merge pull request #16 from starkSV/feat/metrics
feat: /metrics endpoint, cache eviction, and observability fixes
2026-05-18 23:24:07 +05:30
Shekhar Vaidya
90c498233b fix: route background stale refresh through singleflight; cleanup logging
- Background refresh on stale serve now goes through sfGroup.Do so
  concurrent stale hits collapse into one Microsoft call instead of
  hammering the API from multiple goroutines simultaneously.

- cleanupCaches: only logs when entries are actually evicted (was
  logging every 30min regardless of whether anything changed).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:12:59 +05:30
Shekhar Vaidya
a0a6341d5f feat: add /metrics endpoint, fix cache eviction and review issues
- /metrics: atomic counters for requests, cache hits, MS fetches, neg
  hits, stale serves, and cache sizes per endpoint. Auth via
  METRICS_SECRET env var (query param or Authorization: Bearer).

- Cache eviction: cleanupCaches() goroutine runs every 30min, removes
  expired SKU/neg entries and link entries past ExpiresAt + 4h stale
  window. Prevents unbounded map growth under sustained traffic.

- rand: replace global rand with package-level rand.Rand to avoid
  mutex contention at high QPS (jitter() uses local source).

- Singleflight keys: separate sfKey from negKey in both handlers for
  clarity — "sku:<id>" and "link:<id>:<sku>" vs neg cache keys.

- Background refresh on stale: when /proxy serves a stale entry after
  a failed refresh, fires a goroutine to retry and update the cache
  so the next request gets fresh data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:08:43 +05:30
Shekhar
3329cd1b52
Merge pull request #15 from starkSV/feat/caching-layer
fix: bump Dockerfile to golang:1.25-alpine to match go.mod requirement
2026-05-18 22:52:10 +05:30
Shekhar Vaidya
2f14ca6f22 fix: bump Dockerfile to golang:1.25-alpine to match go.mod requirement 2026-05-18 22:51:25 +05:30
Shekhar
8f7bbdeed9
Merge pull request #14 from starkSV/feat/caching-layer
feat: two-layer in-memory caching for backend (closes #12)
2026-05-18 22:49:33 +05:30
Shekhar Vaidya
c6d8615cf1 feat: two-layer in-memory caching for backend (closes #12)
Reduces Microsoft API traffic from thousands/day to ~50-100/day,
eliminating the 715-123130 rate-limit block under real traffic.

1. Singleflight (golang.org/x/sync/singleflight) — wraps all Microsoft
   fetches so 500 concurrent cache misses collapse into 1 API hit.

2. SKU info cache — 7-day TTL keyed by product_id. Language lists are
   stable; no need to hit Microsoft on every product page load.

3. Download link cache — dynamic TTL keyed by product_id:sku_id. Expiry
   is derived from the signed URL's `se` query param minus 30min buffer,
   so we never serve an expired signed URL.

4. Negative response caching — 60s TTL for 429 / 715-123130 failures.
   Prevents thundering herd from retries worsening an existing block.
   Only stored when no stale data is available to fall back on.

5. Dynamic TTL — parses `se` (signed expiry) from Microsoft CDN URL:
   TTL = (se - now) - 30min. Falls back to 22h if unparseable.

6. Stale-on-failure — if a refresh fails (rate-limited or transient),
   the expired cache entry is served temporarily. Applies to both
   /proxy (download links) and /evallinks (eval ISOs).

7. Jitter — ±5min random offset on all TTLs prevents synchronised
   mass-expiry spikes when many entries are warmed at the same time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:41:58 +05:30
Shekhar
ddf96a873d
Merge pull request #13 from starkSV/feat/evalcenter-isos
feat: Enterprise & Server evaluation ISOs via Microsoft Eval Center
2026-05-18 22:21:20 +05:30
Shekhar Vaidya
590382b127 docs: update README for eval ISOs feature
- Add Server & Enterprise ISOs to "What it does" bullets
- Document /evallinks API endpoint with example response
- Add evaluation editions section to Supported Products table
- Fix Contributing guide to reflect current architecture (products.json,
  no PRODUCT_META/RELATED_GROUPS) and add steps for adding eval products

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:18:02 +05:30
Shekhar Vaidya
ddc657e0a7 fix(seo): audit and fix SEO across all pages
- ProductsPage: align <title> with og:title ("All Windows ISO Releases")
- Disclaimer + PrivacyPolicy: add noindex (legal/thin pages shouldn't rank)
- ProductDetailPage: improve auto-generated meta description wording;
  add SoftwareApplication JSON-LD to match EvalDetailPage
- HomePage: update JSON-LD description to include Windows Server

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:14:52 +05:30
Shekhar Vaidya
fe1191b07f fix(ui): mention Server & Enterprise in HowItWorks step 1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:10:37 +05:30
Shekhar Vaidya
4ad8cfbfcc feat: update ComparisonTable and FAQAccordion to reflect eval ISOs
Add "Server & Enterprise ISOs" row to the Why MSDL comparison table
and a new FAQ entry explaining eval editions, the 180-day trial, and
where to find them. Closes #eval-polish.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 22:08:55 +05:30
Shekhar Vaidya
b1458934c3 fix(ui): standardise page widths to two-tier system
Listing pages (home, products, eval): max-w-4xl
Content pages (product detail, eval detail, about, privacy, disclaimer): max-w-2xl

Previously four different widths were in use across the app.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-18 22:04:09 +05:30
Shekhar Vaidya
fdf4d7258d fix(seo): improve meta tags and JSON-LD for eval product pages
- Add unique seoDesc field to each eval product (≤155 chars)
- EvalDetailPage: use seoDesc for description, add Evaluation to
  title, add SoftwareApplication JSON-LD alongside breadcrumb
- EvalPage: add ItemList JSON-LD for the listing page

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-18 22:01:55 +05:30
Shekhar Vaidya
a78059187f feat: add Enterprise & Server eval ISOs via Microsoft evalcenter
Adds /eval listing page and /product/<slug> detail pages for Windows
Server 2025/2022/2019/2016 and Windows 11 Enterprise evaluation ISOs,
sourced from Microsoft evalcenter without any session flow.

Backend: new /evallinks endpoint fetches evalcenter page, extracts
fwlinks, follows all redirects in parallel, detects arch + locale.
24h cache per product with startup warming so first hit is instant.

Frontend: EvalPage listing at /eval, EvalDetailPage at /product/<slug>
matching consumer structure with downloads, aria2 template, system
requirements, and also-available section. Smart ProductRouter in
App.tsx dispatches slug vs numeric productId. Dock highlights Products
tab for /product/* and /eval routes. CTA banner on home page and
footer link added. sitemap.xml updated with 6 new URLs.

Closes #13

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-18 21:56:57 +05:30
Shekhar Vaidya
d6d782bc49 chore: add CLAUDE.md with project context and implementation backlog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 18:32:18 +05:30
Shekhar
38ea92d014
Merge pull request #11 from starkSV/feat/cf-worker-proxy
docs: update README, About, Privacy and Disclaimer for CF Worker
2026-05-18 12:58:47 +05:30
Shekhar Vaidya
58d66fe06d docs: update README, About, Privacy and Disclaimer for CF Worker
- README: add cloudflare-worker/ to project structure, update How It
  Works diagram to show CF Worker hop, add CF Worker setup instructions
  under Running Locally, and fix Deployment section (Worker is an
  outbound proxy, not the backend host)
- About: mention CF Worker distributes requests across Cloudflare edge
- Privacy: add Cloudflare as a third-party service, update date
- Disclaimer: update date

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:58:07 +05:30
Shekhar
ea83c22f9f
Merge pull request #10 from starkSV/feat/cf-worker-proxy
fix(backend): allow non-numeric SKU IDs for legacy Windows products
2026-05-18 12:46:27 +05:30
Shekhar Vaidya
106e2e2b31 fix(backend): allow non-numeric SKU IDs for legacy Windows products
Replaced strconv.Atoi on sku_id with a permissive allowlist regex
(alphanumeric, hyphens, underscores). Older products like Windows 8.1
(#48, #52) return non-integer SKU IDs from Microsoft API, causing the
Get Download Links button to fail with 'sku_id must be a numeric value'.

Closes #9
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:45:27 +05:30
Shekhar
2e2f9c5c48
Merge pull request #8 from starkSV/feat/cf-worker-proxy
fix(frontend): fix TypeScript error in Back button navigate call
2026-05-18 12:12:28 +05:30
Shekhar Vaidya
e7b0fea94b fix(frontend): fix TypeScript error in Back button navigate call
Split ternary into two separate navigate() calls to satisfy TypeScript
overload resolution — navigate(delta: number) and navigate(to: To)
are distinct overloads that cannot share a ternary return type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:11:35 +05:30
Shekhar
2e05348a97
Merge pull request #7 from starkSV/feat/cf-worker-proxy
feat: Cloudflare Worker proxy for Microsoft API + Back button fix + favicon
2026-05-18 12:07:42 +05:30
Shekhar Vaidya
8b036e94ba feat: route Microsoft API calls through Cloudflare Worker to avoid IP blocks
- Add cloudflare-worker/worker.js: edge proxy forwarding requests to allowed
  Microsoft hosts from Cloudflare distributed IPs. Set CF_WORKER_URL env var
  to activate; omit to keep direct-to-Microsoft behaviour (self-hosters unaffected).
- Wrap all outbound Microsoft URLs in proxyURL() in main.go so the Worker
  sits transparently in front of every session and download-link request.
- Fix Back button navigating to external referrer when user lands directly
  on a product URL (#5) — use window.history.state?.idx to detect whether
  there is prior in-app history before calling navigate(-1).

Closes #5, Closes #6

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 12:01:03 +05:30
Shekhar Vaidya
a8f9ba1da1 feat(frontend): add Google Search Console verification meta tag
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 20:51:28 +05:30
Shekhar
72dd3eedde
Merge pull request #4 from starkSV/feat/seo-improvements
feat(frontend): add per-page SEO, 404 page, OG tags, and sitemap updates
2026-05-12 20:40:23 +05:30
Shekhar Vaidya
86da27cb8c feat(frontend): add per-page SEO, 404 page, OG tags, and sitemap updates
- Replace react-helmet-async (React 19 incompatible) with native React 19
  document metadata hoisting across all pages
- Add per-page <title>, <meta name="description">, <link rel="canonical">,
  og:title, og:description, og:url to HomePage, ProductsPage, ProductDetailPage,
  AboutPage, DisclaimerPage, PrivacyPolicyPage
- Add JSON-LD SoftwareApplication schema to HomePage and BreadcrumbList to
  ProductDetailPage
- Add 404 NotFoundPage with noindex meta and canonical to home
- Add og:site_name, og:image, og:type, twitter:card/title/description/image
  to index.html as static fallback; remove duplicate static canonical
- Update sitemap.xml with product IDs 3321, 3324 and lastmod dates
- Add product screenshots to README and update description
- Add og-image.png placeholder

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 20:35:48 +05:30
Shekhar
d0a70496da
Merge pull request #3 from starkSV/fix-aria2-disable-ipv6
fix(frontend): add --disable-ipv6=true to generated aria2 command
2026-05-12 19:46:28 +05:30
Shekhar Vaidya
79e21bb487 fix(frontend): add --disable-ipv6=true to generated aria2 command
IPv6 failures (broken routing, disabled IPv6, VPN/Pi-hole setups) cause
aria2 to abort instead of falling back to IPv4. The flag is a safe
default on all network configurations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 19:37:17 +05:30
Shekhar
462b31a650
Merge pull request #2 from starkSV/improve-backend-url-encoding
refactor(backend): validate numeric IDs and use url.Values for upstream URLs
2026-05-12 19:09:32 +05:30
Shekhar Vaidya
37f947cb32 refactor(backend): validate numeric IDs and use url.Values for upstream URLs
- Reject non-numeric product_id and sku_id with HTTP 400 before any
  upstream request is made, preventing parameter injection into
  Microsoft API query strings.
- Replace all fmt.Sprintf URL construction with url.Values.Set +
  .Encode() across handleSkuInfo, handleProxy, and setupSession,
  ensuring values are always percent-encoded correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 19:00:09 +05:30
Shekhar
10ad222dde
Merge pull request #1 from starkSV/fix-inactive-product-requests-6753598370478744190
Fix inactive products triggering backend requests and improve validation
2026-05-12 18:30:02 +05:30
google-labs-jules[bot]
fc60a9f37b fix: prevent inactive products from triggering backend requests
- Update ProductDetailPage.tsx to only set isValidated(true) for active products.
- Add regex validation to ensure productId is numeric.
- Initialize meta.active to false.
- Add loading state for catalog fetch.
- Fix minor lint issue in ProductsPage.tsx.

Co-authored-by: starkSV <21262426+starkSV@users.noreply.github.com>
2026-05-12 09:47:48 +00:00
Shekhar Vaidya
79450e4b35 Prevent skuinfo API calls when product is marked inactive 2026-04-11 13:11:01 +05:30
Shekhar
7c651d3b4e docs: update issue draft for inactive product fetches 2026-04-11 13:09:46 +05:30
Shekhar Vaidya
2d688ae7e8 Implement inactive product state, restore backend tracker limits, and add dedicated catalog error UI panel 2026-04-11 13:01:56 +05:30
Shekhar
1910ce621a docs: clarify manual catalog maintenance note 2026-04-11 12:55:13 +05:30
Shekhar
6a36d9ee05 docs: refresh issue drafts for catalog branch 2026-04-11 12:47:45 +05:30
Shekhar Vaidya
aac8f5d990 Modernize UI, unify product catalog, and backend optimization
- Migrated products.json to structured metadata format.

- Refactored ProductDetailPage to eagerly reset state and validate product IDs against local catalog.

- Dynamic data fetching in HomePage and StatsBar for total release counts.

- Adjusted UI layout in App.tsx and UX states (404/Loading) for missing dependencies.

- Shortened backend tracking HTTP timeouts to prevent local Pi-Hole hangs.
2026-04-11 11:17:54 +05:30
Shekhar
085f6b5a25 docs: add prevention guidance to issue drafts 2026-04-11 10:44:57 +05:30
Shekhar Vaidya
1f9b3493c0 Create msdls_v3.py 2026-04-11 10:41:59 +05:30
Shekhar
64d9557dcd docs: add issue drafts from project review 2026-04-11 10:32:01 +05:30
Shekhar
f43a0e2dfa perf: replace heavy blur-3xl filter with css radial gradient to maximize mobile lighthouse score 2026-04-10 23:18:22 +05:30
Shekhar
4c0539517c fix: remove unused useNavigate hook causing TS6133 build error 2026-04-10 23:04:29 +05:30