From b4b3762ef099609bfcc27669639c661dc413bcaa Mon Sep 17 00:00:00 2001 From: Jamie Pine Date: Sun, 25 Jan 2026 21:06:41 -0800 Subject: [PATCH] Update global styles and enhance landing page layout - Added overflow-x hidden to prevent horizontal scrolling on html and body elements. - Centered the heading and paragraph text on the landing page for improved aesthetics. - Introduced a mobile-friendly centered screenshot above download buttons. - Updated comments for clarity regarding screenshot positioning on different devices. --- landing/src/app/api/releases/route.ts | 18 ++++++ landing/src/app/globals.css | 4 ++ landing/src/app/page.tsx | 51 +++++++++++++--- landing/src/lib/constants.ts | 20 +++--- landing/src/lib/releases.ts | 88 +++++++++++++++++++++++++++ 5 files changed, 164 insertions(+), 17 deletions(-) create mode 100644 landing/src/app/api/releases/route.ts create mode 100644 landing/src/lib/releases.ts diff --git a/landing/src/app/api/releases/route.ts b/landing/src/app/api/releases/route.ts new file mode 100644 index 00000000..5b62672c --- /dev/null +++ b/landing/src/app/api/releases/route.ts @@ -0,0 +1,18 @@ +import { NextResponse } from 'next/server'; +import { getLatestRelease } from '@/lib/releases'; + +export const dynamic = 'force-dynamic'; +export const revalidate = 600; // Revalidate every 10 minutes + +export async function GET() { + try { + const releaseInfo = await getLatestRelease(); + return NextResponse.json(releaseInfo); + } catch (error) { + console.error('Error fetching release info:', error); + return NextResponse.json( + { error: 'Failed to fetch release information' }, + { status: 500 } + ); + } +} diff --git a/landing/src/app/globals.css b/landing/src/app/globals.css index f9e6fc44..da5b7b99 100644 --- a/landing/src/app/globals.css +++ b/landing/src/app/globals.css @@ -54,8 +54,12 @@ * { @apply border-border; } + html { + overflow-x: hidden; + } body { @apply bg-background text-foreground antialiased; + overflow-x: hidden; background-image: radial-gradient(at 0% 0%, rgba(255, 255, 255, 0.03) 0px, transparent 50%), radial-gradient(at 100% 100%, rgba(255, 255, 255, 0.02) 0px, transparent 50%); diff --git a/landing/src/app/page.tsx b/landing/src/app/page.tsx index 084fa1bb..17285225 100644 --- a/landing/src/app/page.tsx +++ b/landing/src/app/page.tsx @@ -2,13 +2,36 @@ import { Cloud, Code, Cpu, Github, Shield, Zap } from 'lucide-react'; import Image from 'next/image'; +import { useEffect, useState } from 'react'; import { AppleIcon, LinuxIcon, WindowsIcon } from '@/components/PlatformIcons'; import { Button } from '@/components/ui/button'; import { Section, SectionTitle } from '@/components/ui/section'; import { DOWNLOAD_LINKS, GITHUB_REPO } from '@/lib/constants'; +import type { DownloadLinks } from '@/lib/releases'; import { FeatureCard } from '../components/ui/feature-card'; export default function Home() { + const [downloadLinks, setDownloadLinks] = useState(DOWNLOAD_LINKS); + + useEffect(() => { + // Fetch latest release info + fetch('/api/releases') + .then((res) => { + if (!res.ok) { + throw new Error('Failed to fetch releases'); + } + return res.json(); + }) + .then((data) => { + if (data.downloadLinks) { + setDownloadLinks(data.downloadLinks); + } + }) + .catch((error) => { + console.error('Failed to fetch release info:', error); + // Keep fallback links (releases page) on error + }); + }, []); const features = [ { title: 'Near-Perfect Voice Cloning', @@ -64,20 +87,34 @@ export default function Home() { priority /> -

+

Voicebox

-

+

Open source voice cloning powered by Qwen3-TTS. Create natural-sounding speech from text with near-perfect voice replication.

+ {/* Mobile: centered screenshot above download buttons */} +
+
+ Voicebox Application Screenshot +
+
+ {/* Download buttons under left content */}
- {/* Right side - Large screenshot positioned off-screen */} + {/* Desktop: Large screenshot positioned off-screen */}
{ + // Return cached data if still valid + const now = Date.now(); + if (cachedReleaseInfo && now - cacheTimestamp < CACHE_DURATION) { + return cachedReleaseInfo; + } + + try { + const response = await fetch(`${GITHUB_API_BASE}/repos/${GITHUB_REPO}/releases/latest`, { + next: { revalidate: 600 }, // Revalidate every 10 minutes + headers: { + Accept: 'application/vnd.github.v3+json', + }, + }); + + if (!response.ok) { + throw new Error(`GitHub API error: ${response.status}`); + } + + const release = await response.json(); + const version = release.tag_name; + const assets = release.assets || []; + + // Extract download links based on file patterns + const downloadLinks: Partial = {}; + + for (const asset of assets) { + const name = asset.name.toLowerCase(); + const url = asset.browser_download_url; + + if (name.includes('aarch64') || name.includes('arm64')) { + downloadLinks.macArm = url; + } else if (name.includes('x64') && name.includes('.dmg')) { + downloadLinks.macIntel = url; + } else if (name.includes('.msi')) { + downloadLinks.windows = url; + } else if (name.includes('.appimage') || name.includes('.deb')) { + downloadLinks.linux = url; + } + } + + // Fallback: construct URLs if not found in assets + const baseUrl = `https://github.com/${GITHUB_REPO}/releases/download/${version}`; + + const releaseInfo: ReleaseInfo = { + version, + downloadLinks: { + macArm: downloadLinks.macArm || `${baseUrl}/voicebox_${version.replace('v', '')}_aarch64.dmg`, + macIntel: downloadLinks.macIntel || `${baseUrl}/voicebox_${version.replace('v', '')}_x64.dmg`, + windows: downloadLinks.windows || `${baseUrl}/voicebox_${version.replace('v', '')}_x64_en-US.msi`, + linux: downloadLinks.linux || `${baseUrl}/voicebox_x86_64-unknown-linux-gnu.AppImage`, + }, + }; + + // Update cache + cachedReleaseInfo = releaseInfo; + cacheTimestamp = now; + + return releaseInfo; + } catch (error) { + console.error('Failed to fetch latest release:', error); + throw error; + } +}