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.
This commit is contained in:
Shekhar Vaidya 2026-04-11 11:17:54 +05:30
parent 085f6b5a25
commit aac8f5d990
8 changed files with 257 additions and 107 deletions

View file

@ -53,7 +53,7 @@ func getReferer(productId string) string {
// Replicate Fido session tracking
func setupSession() (string, error) {
sessionID := uuid.New().String()
client := &http.Client{Timeout: 10 * time.Second}
client := &http.Client{Timeout: 3 * time.Second}
// Step 1: Register session
req1, _ := http.NewRequest("GET", fmt.Sprintf("https://vlscppe.microsoft.com/tags?org_id=%s&session_id=%s", ORG_ID, sessionID), nil)

View file

@ -1,18 +1,110 @@
{
"48": "Windows 8.1 Single Language (9600.17415)",
"52": "Windows 8.1 (9600.17415)",
"2378": "Windows 10 22H2 Home China (19045.2006)",
"2618": "Windows 10 22H2 v1 (19045.2965)",
"3113": "Windows 11 24H2 (26100.1742)",
"3114": "Windows 11 24H2 Home China (26100.1742)",
"3115": "Windows 11 24H2 Pro China (26100.1742)",
"3131": "Windows 11 Arm64 24H2 (26100.1742)",
"3132": "Windows 11 Arm64 24H2 Home China (26100.1742)",
"3133": "Windows 11 Arm64 24H2 Pro China (26100.1742)",
"3262": "Windows 11 25H2 (26200.6584)",
"3263": "Windows 11 25H2 Home China (26200.6584)",
"3264": "Windows 11 25H2 Pro China (26200.6584)",
"3265": "Windows 11 Arm64 25H2 (26200.6584)",
"3266": "Windows 11 Arm64 25H2 Home China (26200.6584)",
"3267": "Windows 11 Arm64 25H2 Pro China (26200.6584)"
"48": {
"name": "Windows 8.1 Single Language (9600.17415)",
"badge": "LEGACY",
"archs": ["x64", "x86"],
"related": ["52"]
},
"52": {
"name": "Windows 8.1 (9600.17415)",
"badge": "LEGACY",
"archs": ["x64", "x86"],
"related": ["48", "2618"]
},
"2378": {
"name": "Windows 10 22H2 Home China (19045.2006)",
"badge": "EOL SOON",
"archs": ["x64"],
"related": ["2618"]
},
"2618": {
"name": "Windows 10 22H2 v1 (19045.2965)",
"badge": "EOL SOON",
"archs": ["x64", "x86"],
"related": ["3113", "3262", "52"]
},
"3113": {
"name": "Windows 11 24H2 (26100.1742)",
"badge": "STABLE",
"archs": ["x64"],
"related": ["3262", "3131", "2618"]
},
"3114": {
"name": "Windows 11 24H2 Home China (26100.1742)",
"badge": "STABLE",
"archs": ["x64"],
"related": ["3113", "3115"]
},
"3115": {
"name": "Windows 11 24H2 Pro China (26100.1742)",
"badge": "STABLE",
"archs": ["x64"],
"related": ["3113", "3114"]
},
"3131": {
"name": "Windows 11 Arm64 24H2 (26100.1742)",
"badge": "STABLE",
"archs": ["ARM64"],
"related": ["3265", "3113"]
},
"3132": {
"name": "Windows 11 Arm64 24H2 Home China (26100.1742)",
"badge": "STABLE",
"archs": ["ARM64"],
"related": ["3131", "3133"]
},
"3133": {
"name": "Windows 11 Arm64 24H2 Pro China (26100.1742)",
"badge": "STABLE",
"archs": ["ARM64"],
"related": ["3131", "3132"]
},
"3262": {
"name": "Windows 11 25H2 (26200.6584)",
"badge": "LATEST",
"archs": ["x64"],
"related": ["3265", "3321", "3113"]
},
"3263": {
"name": "Windows 11 25H2 Home China (26200.6584)",
"badge": "LATEST",
"archs": ["x64"],
"related": ["3262", "3264"]
},
"3264": {
"name": "Windows 11 25H2 Pro China (26200.6584)",
"badge": "LATEST",
"archs": ["x64"],
"related": ["3262", "3263"]
},
"3265": {
"name": "Windows 11 Arm64 25H2 (26200.6584)",
"badge": "LATEST",
"archs": ["ARM64"],
"related": ["3262", "3321", "3131"]
},
"3266": {
"name": "Windows 11 Arm64 25H2 Home China (26200.6584)",
"badge": "LATEST",
"archs": ["ARM64"],
"related": ["3265", "3267"]
},
"3267": {
"name": "Windows 11 Arm64 25H2 Pro China (26200.6584)",
"badge": "LATEST",
"archs": ["ARM64"],
"related": ["3265", "3266"]
},
"3321": {
"name": "Windows 11 25H2 (Updated Oct)",
"badge": "LATEST",
"archs": ["x64"],
"related": ["3262", "3324", "3113"]
},
"3324": {
"name": "Windows 11 Arm64 25H2 (Updated Oct)",
"badge": "LATEST",
"archs": ["ARM64"],
"related": ["3321", "3262", "3265"]
}
}

View file

@ -12,9 +12,9 @@ import ScrollToTop from './components/ScrollToTop'
export default function App() {
return (
<div className="min-h-screen pb-20 sm:pb-24" style={{ overflowX: 'hidden', maxWidth: '100vw' }}>
<div className="min-h-screen pb-20 sm:pb-24 flex flex-col" style={{ overflowX: 'hidden', maxWidth: '100vw' }}>
<ScrollToTop />
<main>
<main className="flex-1">
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/products" element={<ProductsPage />} />

View file

@ -1,17 +1,27 @@
import { motion } from 'motion/react'
import { useState, useEffect } from 'react'
interface Stat {
value: string
label: string
}
const stats: Stat[] = [
{ value: '17', label: 'releases available' },
{ value: '38', label: 'languages' },
{ value: '0', label: 'intermediaries' },
]
export default function StatsBar() {
const [totalReleases, setTotalReleases] = useState('17')
useEffect(() => {
fetch('/data/products.json')
.then(r => r.json())
.then(data => setTotalReleases(Object.keys(data).length.toString()))
.catch(() => {})
}, [])
const stats: Stat[] = [
{ value: totalReleases, label: 'releases available' },
{ value: '38', label: 'languages' },
{ value: '0', label: 'intermediaries' },
]
return (
<motion.div
className="flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5 text-[11px] font-mono text-zinc-600"

View file

@ -1,4 +1,4 @@
import { useEffect } from 'react'
import { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import { motion } from 'motion/react'
import { ArrowRight } from 'lucide-react'
@ -58,6 +58,7 @@ const cardVariant = {
}
export default function HomePage() {
const [totalReleases, setTotalReleases] = useState(16)
useEffect(() => {
document.title = "Windows ISO Downloader | Official Microsoft Images"
@ -65,6 +66,11 @@ export default function HomePage() {
if (metaDesc) {
metaDesc.setAttribute('content', "Download official Microsoft Windows ISO files. Fast, free, no registration required.")
}
fetch('/data/products.json')
.then(r => r.json())
.then(data => setTotalReleases(Object.keys(data).length))
.catch(() => {})
}, [])
return (
@ -147,7 +153,7 @@ export default function HomePage() {
to="/products"
className="inline-flex items-center gap-2 px-5 py-2.5 rounded-xl border border-white/8 bg-white/4 text-sm text-zinc-400 hover:text-white hover:border-white/15 hover:bg-white/7 transition-all duration-200"
>
Browse all {featured.length > 0 ? '16' : ''} releases
Browse all {totalReleases} releases
<ArrowRight size={14} />
</Link>
</motion.div>

View file

@ -1,5 +1,5 @@
import { useState, useEffect } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import { useParams, useNavigate, Link } from 'react-router-dom'
import { motion, AnimatePresence } from 'motion/react'
import * as Select from '@radix-ui/react-select'
import { ArrowLeft, ChevronDown, Download, AlertTriangle, Check, ExternalLink } from 'lucide-react'
@ -11,61 +11,11 @@ import RelatedReleases from '../components/RelatedReleases'
const API_BASE = import.meta.env.VITE_API_URL ?? 'http://localhost:3002'
// Map product ID → metadata
const PRODUCT_META: Record<string, { badge: string; archs: string[] }> = {
'3262': { badge: 'LATEST', archs: ['x64'] },
'3265': { badge: 'LATEST', archs: ['ARM64'] },
'3321': { badge: 'LATEST', archs: ['x64'] },
'3324': { badge: 'LATEST', archs: ['ARM64'] },
'3113': { badge: 'STABLE', archs: ['x64'] },
'3131': { badge: 'STABLE', archs: ['ARM64'] },
'2618': { badge: 'EOL SOON', archs: ['x64', 'x86'] },
'2378': { badge: 'EOL SOON', archs: ['x64'] },
'52': { badge: 'LEGACY', archs: ['x64', 'x86'] },
'48': { badge: 'LEGACY', archs: ['x64', 'x86'] },
}
// Sibling release groups for "Also available"
const RELATED_GROUPS: Record<string, { id: string; label: string }[]> = {
'3262': [
{ id: '3265', label: 'Win 11 25H2 ARM64' },
{ id: '3321', label: 'Win 11 25H2 (updated)' },
{ id: '3113', label: 'Win 11 24H2' },
],
'3265': [
{ id: '3262', label: 'Win 11 25H2 x64' },
{ id: '3321', label: 'Win 11 25H2 (updated)' },
{ id: '3131', label: 'Win 11 24H2 ARM64' },
],
'3321': [
{ id: '3262', label: 'Win 11 25H2' },
{ id: '3324', label: 'Win 11 25H2 ARM64' },
{ id: '3113', label: 'Win 11 24H2' },
],
'3324': [
{ id: '3321', label: 'Win 11 25H2 x64' },
{ id: '3262', label: 'Win 11 25H2' },
{ id: '3265', label: 'Win 11 25H2 ARM64 (alt)' },
],
'3113': [
{ id: '3262', label: 'Win 11 25H2' },
{ id: '3131', label: 'Win 11 24H2 ARM64' },
{ id: '2618', label: 'Win 10 22H2' },
],
'3131': [
{ id: '3265', label: 'Win 11 25H2 ARM64' },
{ id: '3113', label: 'Win 11 24H2 x64' },
],
'2618': [
{ id: '3113', label: 'Win 11 24H2' },
{ id: '3262', label: 'Win 11 25H2' },
{ id: '52', label: 'Win 8.1' },
],
'52': [
{ id: '48', label: 'Win 8.1 Single Language' },
{ id: '2618', label: 'Win 10 22H2' },
],
interface ProductCatalogEntry {
name: string
badge: string
archs: string[]
related: string[]
}
function WinLogo({ className }: { className?: string }) {
@ -102,17 +52,45 @@ export default function ProductDetailPage() {
const [isFetching, setIsFetching] = useState(false)
const [error, setError] = useState<string | null>(null)
const [copiedUri, setCopiedUri] = useState<string | null>(null)
const meta = PRODUCT_META[productId!] ?? { badge: '', archs: ['x64'] }
const related = RELATED_GROUPS[productId!] ?? []
const [isNotFound, setIsNotFound] = useState(false)
const [isValidated, setIsValidated] = useState(false)
const [meta, setMeta] = useState<{ badge: string; archs: string[] }>({ badge: '', archs: [] })
const [related, setRelated] = useState<{ id: string; label: string }[]>([])
// Load product name + build string
useEffect(() => {
setBuildStr('')
setIsNotFound(false)
setIsValidated(false)
setProductName('')
setMeta({ badge: '', archs: [] })
setRelated([])
fetch('/data/products.json')
.then(r => r.json())
.then((data: Record<string, string>) => {
const name = data[productId!] ?? `Product ${productId}`
.then((data: Record<string, ProductCatalogEntry>) => {
const product = data[productId!]
if (!product || !product.name) {
setIsNotFound(true)
setProductName('Product Not Found')
document.title = 'Product Not Found | Windows ISO Downloader'
const descMeta = document.querySelector('meta[name="description"]')
if (descMeta) descMeta.setAttribute('content', 'The requested product could not be found.')
return
}
const name = product.name
setProductName(name)
setMeta({ badge: product.badge || '', archs: product.archs || [] })
setRelated((product.related || []).map(rId => ({
id: rId,
label: data[rId]?.name || `Product ${rId}`
})))
setIsValidated(true)
// Dynamic SEO injection
document.title = `${name} ISO Download | Windows ISO Downloader`
@ -125,12 +103,15 @@ export default function ProductDetailPage() {
const match = name.match(/\(([^)]+)\)/)
if (match) setBuildStr(match[1])
})
.catch(() => setProductName(`Product ${productId}`))
.catch(() => {
setIsNotFound(true)
setProductName('Error Loading Product')
})
}, [productId])
// Fetch languages on mount
useEffect(() => {
if (!productId) return
if (!productId || !isValidated) return
setIsLoadingLangs(true)
setError(null)
setDownloadLinks([])
@ -151,7 +132,7 @@ export default function ProductDetailPage() {
})
.catch(e => setError(e.message))
.finally(() => setIsLoadingLangs(false))
}, [productId])
}, [productId, isValidated])
async function handleGetLinks() {
if (!selectedSku || !productId) return
@ -230,11 +211,37 @@ export default function ProductDetailPage() {
{/* Main card */}
<div className="rounded-2xl border border-white/7 bg-[#111113] p-6 space-y-5">
{isLoadingLangs ? (
<div className="space-y-3">
<div className="h-3 w-20 bg-white/6 rounded animate-pulse" />
<div className="h-11 bg-white/6 rounded-xl animate-pulse" />
<div className="h-11 bg-white/5 rounded-xl animate-pulse" />
{isNotFound ? (
<div className="flex flex-col items-center justify-center py-6 text-center">
<AlertTriangle size={32} className="text-zinc-600 mb-4" />
<h2 className="text-lg font-semibold text-white mb-2">Product Not Found</h2>
<p className="text-zinc-500 text-sm max-w-xs px-4 leading-relaxed mb-6">
The product ID you requested ({productId}) does not exist or has been removed from the catalog.
</p>
<div className="flex items-center justify-center gap-3 w-full">
<Link to="/" className="flex-1 max-w-[140px] px-4 py-2.5 rounded-xl bg-white/5 border border-white/8 text-sm font-medium text-white hover:bg-white/10 transition-colors">
Home
</Link>
<Link to="/products" className="flex-1 max-w-[140px] px-4 py-2.5 rounded-xl bg-blue-500 text-sm font-medium text-white hover:bg-blue-600 transition-colors shadow-lg">
Browse all
</Link>
</div>
</div>
) : isLoadingLangs ? (
<div className="space-y-4">
<div className="flex items-center gap-2.5 text-xs text-zinc-400 font-medium tracking-wide">
<motion.span
animate={{ rotate: 360 }}
transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
className="inline-block w-4 h-4 border-2 border-zinc-500/30 border-t-zinc-500 rounded-full"
/>
Connecting to Microsoft CDN...
</div>
<div className="space-y-3">
<div className="h-3 w-20 bg-white/6 rounded animate-pulse" />
<div className="h-11 bg-white/6 rounded-xl animate-pulse" />
<div className="h-11 bg-white/5 rounded-xl animate-pulse" />
</div>
</div>
) : error && !languages.length ? (
<div className="flex items-start gap-3 p-4 rounded-xl bg-red-500/8 border border-red-500/15 text-red-400 text-sm">
@ -396,15 +403,19 @@ export default function ProductDetailPage() {
</AnimatePresence>
</div>
{/* System requirements */}
<SystemRequirements isWin11={isWin11(productId!)} />
{!isNotFound && (
<>
{/* System requirements */}
<SystemRequirements isWin11={isWin11(productId!)} />
{/* aria2 tip */}
<Aria2Tip downloadUrl={firstUri} />
{/* aria2 tip */}
<Aria2Tip downloadUrl={firstUri} />
{/* Related releases */}
{related.length > 0 && (
<RelatedReleases current={productId!} items={related} />
{/* Related releases */}
{related.length > 0 && (
<RelatedReleases current={productId!} items={related} />
)}
</>
)}
</motion.div>
</div>

View file

@ -22,8 +22,8 @@ export default function ProductsPage() {
fetch('/data/products.json')
.then(r => r.json())
.then((data: Record<string, string>) => {
setProducts(Object.entries(data).map(([id, name]) => ({ id, name })))
.then((data: Record<string, { name: string }>) => {
setProducts(Object.entries(data).map(([id, product]) => ({ id, name: product.name })))
})
.finally(() => setIsLoading(false))
}, [])

View file

@ -101,8 +101,39 @@ if __name__ == "__main__":
time.sleep(0.5)
if args.write:
import os
catalog = {}
if os.path.exists(args.write):
try:
with open(args.write, 'r', encoding='utf-8') as f:
catalog = json.load(f)
except Exception as e:
logging.error(f"Failed to read existing catalog: {e}")
# Merge new products, preserving existing extra metadata if present
for pid, name in products.items():
if pid in catalog:
# Update name but keep other fields like badge, archs, etc.
if isinstance(catalog[pid], dict):
catalog[pid]["name"] = name
else:
# Upgrade from old flat format
catalog[pid] = {
"name": name,
"badge": "",
"archs": [],
"related": []
}
else:
catalog[pid] = {
"name": name,
"badge": "",
"archs": [],
"related": []
}
with open(args.write, 'w', encoding='utf-8') as f:
json.dump(products, f, indent=4)
logging.info(f"\nSaved {len(products)} products to {args.write}")
json.dump(catalog, f, indent=4)
logging.info(f"\nSaved {len(catalog)} products to {args.write} (merged with existing)")
logging.info("Done.")