diff --git a/bun.lock b/bun.lock index b507da48..d6b63ee8 100644 --- a/bun.lock +++ b/bun.lock @@ -17,7 +17,7 @@ }, "app": { "name": "@voicebox/app", - "version": "0.1.13", + "version": "0.2.0", "dependencies": { "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", @@ -72,13 +72,15 @@ }, "landing": { "name": "@voicebox/landing", - "version": "0.1.13", + "version": "0.2.0", "dependencies": { + "@fontsource/space-grotesk": "^5.2.10", "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.4", "autoprefixer": "^10.4.17", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "framer-motion": "^12.36.0", "lucide-react": "^0.316.0", "next": "^16.1.3", "postcss": "^8.4.33", @@ -87,6 +89,7 @@ "tailwind-merge": "^3.4.0", "tailwindcss": "^3.4.1", "tailwindcss-animate": "^1.0.7", + "wavesurfer.js": "^7.12.2", }, "devDependencies": { "@types/node": "^20.11.5", @@ -97,7 +100,7 @@ }, "tauri": { "name": "@voicebox/tauri", - "version": "0.1.13", + "version": "0.2.0", "dependencies": { "@tauri-apps/api": "^2.0.0", "@tauri-apps/plugin-dialog": "^2.0.0", @@ -120,7 +123,7 @@ }, "web": { "name": "@voicebox/web", - "version": "0.1.13", + "version": "0.2.0", "dependencies": { "@tanstack/react-query": "^5.0.0", "react": "^18.3.0", @@ -274,6 +277,8 @@ "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="], + "@fontsource/space-grotesk": ["@fontsource/space-grotesk@5.2.10", "", {}, "sha512-XNXEbT74OIITPqw2H6HXwPDp85fy43uxfBwFR5PU+9sLnjuLj12KlhVM9nZVN6q6dlKjkuN8JisW/OBxwxgUew=="], + "@hookform/resolvers": ["@hookform/resolvers@3.10.0", "", { "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag=="], "@humanwhocodes/config-array": ["@humanwhocodes/config-array@0.13.0", "", { "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" } }, "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw=="], @@ -1152,12 +1157,16 @@ "@typescript-eslint/typescript-estree/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + "@voicebox/landing/framer-motion": ["framer-motion@12.36.0", "", { "dependencies": { "motion-dom": "^12.36.0", "motion-utils": "^12.36.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-4PqYHAT7gev0ke0wos+PyrcFxI0HScjm3asgU8nSYa8YzJFuwgIvdj3/s3ZaxLq0bUSboIn19A2WS/MHwLCvfw=="], + "@voicebox/landing/lucide-react": ["lucide-react@0.316.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0" } }, "sha512-dTmYX1H4IXsRfVcj/KUxworV6814ApTl7iXaS21AimK2RUEl4j4AfOmqD3VR8phe5V91m4vEJ8tCK4uT1jE5nA=="], "@voicebox/landing/tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="], "@voicebox/landing/tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="], + "@voicebox/landing/wavesurfer.js": ["wavesurfer.js@7.12.2", "", {}, "sha512-akVYISAHCw2gNw/7n8Pk/zH1Zz91WJyL/2MaNQCLD1XV3A226gKlWoDHWp9UdWqQ3zXnWttDf9ewZQQ3cxbOmQ=="], + "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], @@ -1169,5 +1178,9 @@ "tinyglobby/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "@voicebox/landing/framer-motion/motion-dom": ["motion-dom@12.36.0", "", { "dependencies": { "motion-utils": "^12.36.0" } }, "sha512-Ep1pq8P88rGJ75om8lTCA13zqd7ywPGwCqwuWwin6BKc0hMLkVfcS6qKlRqEo2+t0DwoUcgGJfXwaiFn4AOcQA=="], + + "@voicebox/landing/framer-motion/motion-utils": ["motion-utils@12.36.0", "", {}, "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg=="], } } diff --git a/landing/package.json b/landing/package.json index 60acdd13..88464f93 100644 --- a/landing/package.json +++ b/landing/package.json @@ -9,11 +9,13 @@ "lint": "next lint" }, "dependencies": { + "@fontsource/space-grotesk": "^5.2.10", "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.4", "autoprefixer": "^10.4.17", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "framer-motion": "^12.36.0", "lucide-react": "^0.316.0", "next": "^16.1.3", "postcss": "^8.4.33", @@ -21,7 +23,8 @@ "react-dom": "^18.2.0", "tailwind-merge": "^3.4.0", "tailwindcss": "^3.4.1", - "tailwindcss-animate": "^1.0.7" + "tailwindcss-animate": "^1.0.7", + "wavesurfer.js": "^7.12.2" }, "devDependencies": { "@types/node": "^20.11.5", diff --git a/landing/public/audio/fireship.webm b/landing/public/audio/fireship.webm new file mode 100644 index 00000000..0561ea18 Binary files /dev/null and b/landing/public/audio/fireship.webm differ diff --git a/landing/public/audio/jarvis.webm b/landing/public/audio/jarvis.webm new file mode 100644 index 00000000..4eefdbe8 Binary files /dev/null and b/landing/public/audio/jarvis.webm differ diff --git a/landing/public/audio/linus.webm b/landing/public/audio/linus.webm new file mode 100644 index 00000000..63b7ad03 Binary files /dev/null and b/landing/public/audio/linus.webm differ diff --git a/landing/public/audio/morganfreeman.webm b/landing/public/audio/morganfreeman.webm new file mode 100644 index 00000000..eb5cddd4 Binary files /dev/null and b/landing/public/audio/morganfreeman.webm differ diff --git a/landing/public/audio/samaltman.webm b/landing/public/audio/samaltman.webm new file mode 100644 index 00000000..7400bece Binary files /dev/null and b/landing/public/audio/samaltman.webm differ diff --git a/landing/public/audio/samjackson.webm b/landing/public/audio/samjackson.webm new file mode 100644 index 00000000..02f43a96 Binary files /dev/null and b/landing/public/audio/samjackson.webm differ diff --git a/landing/public/voicebox-logo-app.webp b/landing/public/voicebox-logo-app.webp new file mode 100644 index 00000000..9fedd439 Binary files /dev/null and b/landing/public/voicebox-logo-app.webp differ diff --git a/landing/src/app/globals.css b/landing/src/app/globals.css index da5b7b99..709d74b7 100644 --- a/landing/src/app/globals.css +++ b/landing/src/app/globals.css @@ -16,7 +16,7 @@ --secondary-foreground: 0 0% 0%; --muted: 0 0% 96%; --muted-foreground: 0 0% 45%; - --accent: 0 0% 96%; + --accent: 43 50% 50%; --accent-foreground: 0 0% 0%; --destructive: 0 0% 0%; --destructive-foreground: 0 0% 100%; @@ -27,26 +27,52 @@ } .dark { - --background: 0 0% 3%; - --foreground: 0 0% 98%; - --card: 0 0% 8% / 0.6; - --card-foreground: 0 0% 98%; - --popover: 0 0% 8% / 0.8; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 0 0% 8%; - --secondary: 0 0% 12% / 0.5; - --secondary-foreground: 0 0% 98%; - --muted: 0 0% 12% / 0.4; - --muted-foreground: 0 0% 65%; - --accent: 0 0% 15% / 0.5; - --accent-foreground: 0 0% 98%; + /* Surfaces -- slightly warm-tinted darks */ + --background: 30 4% 4%; + --foreground: 30 10% 94%; + --card: 30 4% 7%; + --card-foreground: 30 10% 94%; + --popover: 30 4% 7%; + --popover-foreground: 30 10% 94%; + --primary: 30 10% 94%; + --primary-foreground: 30 4% 7%; + --secondary: 30 4% 10%; + --secondary-foreground: 30 10% 94%; + --muted: 30 3% 12%; + --muted-foreground: 30 5% 55%; + --accent: 43 50% 45%; + --accent-foreground: 30 10% 94%; --destructive: 0 62% 50%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 15% / 0.5; - --input: 0 0% 15% / 0.5; - --ring: 0 0% 98% / 0.2; - --radius: 1rem; + --destructive-foreground: 30 10% 94%; + --border: 30 4% 13%; + --input: 30 4% 13%; + --ring: 30 10% 94% / 0.2; + --radius: 0.75rem; + + /* App-specific surface tokens */ + --app: 30 4% 4%; + --app-box: 30 4% 7%; + --app-dark-box: 30 4% 5%; + --app-darker-box: 30 4% 3%; + --app-light-box: 30 4% 14%; + --app-line: 30 4% 13%; + --app-button: 30 4% 11%; + --app-hover: 30 4% 15%; + --app-selected: 30 4% 17%; + + /* Text hierarchy */ + --ink: 30 10% 94%; + --ink-dull: 30 5% 55%; + --ink-faint: 30 3% 38%; + + /* Accent shades */ + --accent-faint: 43 45% 55%; + --accent-deep: 43 55% 35%; + --accent-glow: 43 60% 50%; + + /* Sidebar */ + --sidebar: 30 4% 3%; + --sidebar-line: 30 4% 10%; } } @@ -60,9 +86,9 @@ 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%); + font-family: + ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Helvetica Neue", Arial, sans-serif; } } @@ -71,3 +97,41 @@ text-wrap: balance; } } + +/* Staggered fade-in animation for hero elements */ +@keyframes fadeUp { + from { + opacity: 0; + transform: translateY(16px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.fade-in { + opacity: 0; + animation: fadeUp 0.6s ease-out forwards; +} + +/* Noise texture overlay for hero glow */ +.hero-glow::after { + content: ""; + position: absolute; + inset: 0; + z-index: 5; + pointer-events: none; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.8' numOctaves='5' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); + opacity: 0.3; + mix-blend-mode: overlay; +} + +/* Scrollbar hiding */ +::-webkit-scrollbar { + display: none; +} + +* { + scrollbar-width: none; +} diff --git a/landing/src/app/layout.tsx b/landing/src/app/layout.tsx index f29ef15e..a5ba9383 100644 --- a/landing/src/app/layout.tsx +++ b/landing/src/app/layout.tsx @@ -1,17 +1,19 @@ import type { Metadata } from 'next'; -import { Inter } from 'next/font/google'; import './globals.css'; -import { Banner } from '@/components/Banner'; -import { Footer } from '@/components/Footer'; -import { Header } from '@/components/Header'; - -const inter = Inter({ subsets: ['latin'], variable: '--font-sans' }); export const metadata: Metadata = { - title: 'Voicebox - Open Source Voice Cloning Desktop App Powered by Qwen3-TTS', + title: 'Voicebox - Open Source Voice Cloning Desktop App', description: 'Near-perfect voice cloning powered by Qwen3-TTS. Desktop app for Mac, Windows, and Linux. Multi-sample support, smart caching, local or remote inference.', - keywords: ['voice cloning', 'TTS', 'Qwen3', 'desktop app', 'AI voice'], + keywords: [ + 'voice cloning', + 'TTS', + 'Qwen3', + 'desktop app', + 'AI voice', + 'open source', + 'text to speech', + ], icons: { icon: [ { url: '/favicon.png', type: 'image/png' }, @@ -20,8 +22,8 @@ export const metadata: Metadata = { apple: [{ url: '/apple-touch-icon.png', sizes: '180x180', type: 'image/png' }], }, openGraph: { - title: 'voicebox', - description: 'Professional voice cloning with Qwen3-TTS', + title: 'Voicebox', + description: 'Open source voice cloning. Local-first. Free forever.', type: 'website', url: 'https://voicebox.sh', }, @@ -30,15 +32,8 @@ export const metadata: Metadata = { export default function RootLayout({ children }: { children: React.ReactNode }) { return ( - -
- -
-
- {children} -
-
+ +
{children}
); diff --git a/landing/src/app/page.tsx b/landing/src/app/page.tsx index 4ba9d8c4..cc5728e3 100644 --- a/landing/src/app/page.tsx +++ b/landing/src/app/page.tsx @@ -1,304 +1,227 @@ 'use client'; -import { Cloud, Code, Cpu, Github, Shield, Zap } from 'lucide-react'; +import { Github } from 'lucide-react'; import Image from 'next/image'; import { useEffect, useState } from 'react'; +import { ControlUI } from '@/components/ControlUI'; +import { Features } from '@/components/Features'; +import { Footer } from '@/components/Footer'; +import { Navbar } from '@/components/Navbar'; import { AppleIcon, LinuxIcon, WindowsIcon } from '@/components/PlatformIcons'; -import { Button } from '@/components/ui/button'; -import { Section } 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'); - } + if (!res.ok) throw new Error('Failed to fetch releases'); return res.json(); }) .then((data) => { - if (data.downloadLinks) { - setDownloadLinks(data.downloadLinks); - } + 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', - description: - "Powered by Alibaba's Qwen3-TTS model for exceptional voice quality and accuracy.", - icon: , - }, - { - title: 'Stories Editor', - description: - 'Create multi-voice narratives with a timeline-based editor. Arrange tracks, trim clips, and mix conversations.', - icon: , - }, - { - title: 'Multi-Sample Support', - description: - 'Combine multiple voice samples for higher quality and more natural-sounding results.', - icon: , - }, - - { - title: 'Local or Remote', - description: - 'Run GPU inference locally or connect to a remote machine. One-click server setup.', - icon: , - }, - { - title: 'Audio Transcription', - description: - 'Powered by Whisper for accurate speech-to-text. Extract reference text from voice samples automatically.', - icon: , - }, - { - title: 'Cross-Platform', - description: 'Available for macOS, Windows, and Linux. No Python installation required.', - icon: , - }, - ]; return ( -
- {/* Hero Section */} -
-
-
- {/* Left side - Content */} -
-
- Voicebox Logo -
-

- 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 */} - -
- - {/* Desktop: Large screenshot positioned off-screen */} -
-
- Voicebox Application Screenshot -
-
-
+ {/* ── Hero Section ─────────────────────────────────────────────── */} +
+ {/* Background glow */} +
+
+
-
- {/* Screenshots Section */} -
-
-
-
- Voicebox Screenshot 2 -
-
- Voicebox Screenshot 1 -
-
- Voicebox Screenshot 3 -
-
-
-
- - {/* Description Section */} -
-
-

- What is Voicebox? -

-
-

- Voicebox is a local-first voice cloning studio with DAW-like features - for professional voice synthesis. Think of it as a{' '} - local, free and open-source alternative to ElevenLabs — download - models, clone voices, and generate speech entirely on your machine. -

-

- Unlike cloud services that lock your voice data behind subscriptions, Voicebox gives - you complete privacy, professional tools, and native performance. Download a voice - model, clone any voice from a few seconds of audio, and compose multi-voice projects - with studio-grade editing tools. -

-

- Optimized for performance with Metal acceleration on Mac and{' '} - CUDA acceleration on Windows/Linux for fast, local inference. -

-

No Python install required.

-
-
-
- - {/* Demo Video Section */} -
-
-

- See it in action... -

-
-
- {/** biome-ignore lint/a11y/useMediaCaption: not generating captions for this, ya damn linter */} - -
-
-
-
- - {/* Features Section */} -
-
- {features.map((feature) => ( - + {/* Logo */} +
+ Voicebox - ))} +
+ + {/* Headline */} +
+

+ Your voice, your machine. +

+
+ + {/* Subtitle */} +

+ Open source voice cloning studio powered by Qwen3-TTS. Clone any voice, generate natural + speech, and compose multi-voice projects — all running locally. +

+ + {/* CTAs */} + + + {/* Version */} +

+ Free and open source · macOS, Windows, Linux +

-
-
+ + {/* ── ControlUI mockup ─────────────────────────────────────── */} +
+ +
+
+ + {/* ── Features ─────────────────────────────────────────────── */} + + + {/* ── About / Manifesto ────────────────────────────────────── */} +
+
+

+ Why Voicebox exists +

+
+

+ Cloud voice cloning services lock your voice data behind subscriptions, rate limits, + and terms of service that can change at any time. Your voice — and the voices you + clone — should belong to you. +

+

+ Voicebox is a local-first voice cloning studio. Download a model, clone any voice from + a few seconds of audio, and generate speech entirely on your machine. +

+

+ Optimized with Metal acceleration on Mac and CUDA on Windows/Linux. No Python install + required. No cloud. No subscriptions. Free and open-source, forever. +

+
+
+
+ + {/* ── Download Section ─────────────────────────────────────── */} +
+
+
+

+ Download Voicebox +

+

+ Available for macOS, Windows, and Linux. No dependencies required. +

+
+ +
+ {/* macOS ARM */} + + +
+
macOS
+
Apple Silicon (ARM)
+
+
+ + {/* macOS Intel */} + + +
+
macOS
+
Intel (x64)
+
+
+ + {/* Windows */} + + +
+
Windows
+
64-bit (MSI)
+
+
+ + {/* Linux */} +
+ +
+
Linux
+
Coming soon
+
+
+
+ + {/* GitHub link */} + +
+
+ + {/* ── Footer ───────────────────────────────────────────────── */} +