diff --git a/backend/main.go b/backend/main.go
index 1cbeb06..fca7b8c 100644
--- a/backend/main.go
+++ b/backend/main.go
@@ -940,7 +940,7 @@ func cleanupSessions() {
func enableCORS(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
origin := r.Header.Get("Origin")
- if origin == "https://msdl.tech-latest.com" || strings.HasPrefix(origin, "http://localhost:") {
+ if origin == "https://msdl.tech-latest.com" || strings.HasPrefix(origin, "http://localhost:") || strings.HasPrefix(origin, "http://100.") || strings.HasPrefix(origin, "http://192.168.") {
w.Header().Set("Access-Control-Allow-Origin", origin)
}
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
diff --git a/frontend/src/components/CliHandoff.tsx b/frontend/src/components/CliHandoff.tsx
new file mode 100644
index 0000000..1b21873
--- /dev/null
+++ b/frontend/src/components/CliHandoff.tsx
@@ -0,0 +1,142 @@
+import { useState } from 'react'
+import { motion, AnimatePresence } from 'motion/react'
+import { Terminal, ChevronRight, Copy, Check, ExternalLink } from 'lucide-react'
+import { toast } from 'sonner'
+
+interface Props {
+ productId: string
+ langName?: string
+ langDisplay?: string
+ defaultOpen?: boolean
+ highlight?: boolean
+}
+
+const RELEASES_URL = 'https://github.com/starkSV/windows-iso-downloader/releases/latest'
+
+function InstallSteps() {
+ return (
+
+ )
+}
+
+function RunStep({ command, langDisplay, onCopy, copied }: {
+ command: string
+ langDisplay?: string
+ onCopy: () => void
+ copied: boolean
+}) {
+ return (
+
+
2. Run
+
+
+ {langDisplay ?? 'will prompt for language'}
+
+
+
+
+ $
+ {command}
+
+
+
+
+ )
+}
+
+export default function CliHandoff({ productId, langName, langDisplay, defaultOpen = false, highlight = false }: Props) {
+ const [open, setOpen] = useState(defaultOpen)
+ const [copied, setCopied] = useState(false)
+
+ const command = langName
+ ? `msdl --id ${productId} --lang "${langName}"`
+ : `msdl --id ${productId}`
+
+ function handleCopy() {
+ navigator.clipboard.writeText(command)
+ setCopied(true)
+ toast.success('Command copied!')
+ setTimeout(() => setCopied(false), 2000)
+ }
+
+ if (highlight) {
+ return (
+
+
+
+
Use the MSDL CLI instead
+
+ Recommended
+
+
+
+ Our server is currently blocked by Microsoft. The CLI fetches the link directly from your machine — no server involved.
+
+
+
+
+ )
+ }
+
+ return (
+
+
+
+
+ {open && (
+
+
+
+ The MSDL CLI runs the lookup directly from your machine — no server in the middle.
+
+
+
+
+
+ )}
+
+
+ )
+}
diff --git a/frontend/src/pages/ProductDetailPage.tsx b/frontend/src/pages/ProductDetailPage.tsx
index 02ed985..c264f10 100644
--- a/frontend/src/pages/ProductDetailPage.tsx
+++ b/frontend/src/pages/ProductDetailPage.tsx
@@ -9,6 +9,7 @@ import SystemRequirements from '../components/SystemRequirements'
import CliCommand from '../components/CliCommand'
import RelatedReleases from '../components/RelatedReleases'
import OfficialFallback from '../components/OfficialFallback'
+import CliHandoff from '../components/CliHandoff'
import { addRecentEntry, updateRecentExpiry } from '../components/RecentlyViewed'
const API_BASE = import.meta.env.VITE_API_URL ?? 'http://localhost:3002'
@@ -526,10 +527,21 @@ export default function ProductDetailPage() {
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: 'auto' }}
exit={{ opacity: 0, height: 0 }}
- className="flex items-start gap-3 p-4 rounded-xl bg-red-500/8 border border-red-500/15 text-red-400 text-sm"
+ className="space-y-3"
>
-
- {error}
+
+ {selectedSku && (
+
+ )}
)}
@@ -637,12 +649,26 @@ export default function ProductDetailPage() {
{(!isNotFound && !hasCatalogError) && (
<>
- {/* Official fallback — shown when backend is WAF-blocked (stale) */}
- {meta.active && linkStatus === 'stale' && selectedSku && (
-
+ {/* Fallbacks — shown when stale or any error */}
+ {meta.active && (linkStatus === 'stale' || error !== null) && (
+ <>
+
+ {/* Collapsed CLI only when the highlighted card isn't already shown inside */}
+ {!(error !== null && languages.length > 0) && (
+ selectedSku ? (
+
+ ) : (
+
+ )
+ )}
+ >
)}
{/* System requirements */}