* feat(web): overhaul SEO structure and landing pages Add distro-specific install pages and an engine comparison hub to capture high-intent organic queries. Centralize metadata and structured data handling to improve crawl consistency, internal linking, and rich-result eligibility. * feat(web): add subpage navigation and visual polish Make SEO landing pages easier to discover and navigate by adding persistent subpage header/footer links to home and key routes. Refresh install and comparison pages with colorful icon-driven sections while expanding homepage footer links for stronger internal linking. * fix(ci): make web version sync robust to schema location CI assumed softwareVersion lived in layout.tsx, but SEO refactors moved SoftwareApplication JSON-LD to page.tsx. Update workflow sync steps to patch whichever file currently contains softwareVersion so website build and release jobs keep working. * chore(web): remove SEO audit artifact Drop the internal SEO audit markdown from the PR so only production website and workflow changes are included.
1295 lines
55 KiB
TypeScript
1295 lines
55 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect, useCallback } from "react";
|
|
import { motion } from "framer-motion";
|
|
import Link from "next/link";
|
|
import { LiveDemo } from "@/components/live-demo";
|
|
import {
|
|
Terminal,
|
|
Lock,
|
|
Zap,
|
|
Laptop,
|
|
Keyboard,
|
|
Settings,
|
|
Code,
|
|
Github,
|
|
Star,
|
|
Download,
|
|
ChevronRight,
|
|
CheckCircle2,
|
|
Menu,
|
|
X,
|
|
Copy,
|
|
Check,
|
|
Play,
|
|
Shield,
|
|
Globe,
|
|
Cpu,
|
|
Volume2,
|
|
Sparkles,
|
|
Heart,
|
|
} from "lucide-react";
|
|
import { ThemeToggle } from "@/components/theme-toggle";
|
|
import { VocalinuxLogo } from "@/components/optimized-image";
|
|
import { CodeBlock } from "@/components/code-block";
|
|
import { useInView } from "react-intersection-observer";
|
|
|
|
// The one-liner install command (split into three lines for display)
|
|
// Downloads install.sh from the specific release tag to ensure version consistency
|
|
const getInstallCommands = (latestRelease: string) => ({
|
|
interactiveInstallCommand: `curl -fsSL raw.githubusercontent.com/jatinkrmalik/vocalinux/${latestRelease}/install.sh -o /tmp/vl.sh && bash /tmp/vl.sh --interactive`,
|
|
|
|
oneClickInstallCommand: `curl -fsSL raw.githubusercontent.com/jatinkrmalik/vocalinux/${latestRelease}/install.sh -o /tmp/vl.sh && bash /tmp/vl.sh`,
|
|
|
|
oneClickInstallWhisper: `curl -fsSL raw.githubusercontent.com/jatinkrmalik/vocalinux/${latestRelease}/install.sh -o /tmp/vl.sh && bash /tmp/vl.sh --engine=whisper`,
|
|
|
|
oneClickInstallVosk: `curl -fsSL raw.githubusercontent.com/jatinkrmalik/vocalinux/${latestRelease}/install.sh -o /tmp/vl.sh && bash /tmp/vl.sh --engine=vosk`,
|
|
|
|
uninstallCommand: `curl -fsSL https://raw.githubusercontent.com/jatinkrmalik/vocalinux/${latestRelease}/uninstall.sh -o /tmp/vul.sh && bash /tmp/vul.sh`,
|
|
});
|
|
|
|
const homeJsonLd = [
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "SoftwareApplication",
|
|
"@id": "https://vocalinux.com/#softwareapplication",
|
|
name: "Vocalinux",
|
|
applicationCategory: "UtilitiesApplication",
|
|
operatingSystem: "Linux",
|
|
isAccessibleForFree: true,
|
|
license: "https://github.com/jatinkrmalik/vocalinux/blob/main/LICENSE",
|
|
offers: {
|
|
"@type": "Offer",
|
|
price: "0",
|
|
priceCurrency: "USD",
|
|
},
|
|
description:
|
|
"Offline voice dictation and speech-to-text for Linux with whisper.cpp and VOSK.",
|
|
"softwareVersion": "0.6.1-beta",
|
|
author: {
|
|
"@type": "Person",
|
|
name: "Jatin K Malik",
|
|
url: "https://github.com/jatinkrmalik",
|
|
},
|
|
url: "https://vocalinux.com/",
|
|
downloadUrl: "https://github.com/jatinkrmalik/vocalinux",
|
|
screenshot: "https://vocalinux.com/og-image.png",
|
|
featureList: [
|
|
"100% offline speech recognition",
|
|
"Works with X11 and Wayland",
|
|
"Double-tap Ctrl activation",
|
|
"whisper.cpp, Whisper, and VOSK support",
|
|
"Linux desktop integration",
|
|
],
|
|
},
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "FAQPage",
|
|
mainEntity: [
|
|
{
|
|
"@type": "Question",
|
|
name: "Is Vocalinux really 100% offline?",
|
|
acceptedAnswer: {
|
|
"@type": "Answer",
|
|
text: "Yes. All speech recognition runs locally on your Linux machine. Voice data does not leave your computer.",
|
|
},
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
name: "Which Linux distributions are supported?",
|
|
acceptedAnswer: {
|
|
"@type": "Answer",
|
|
text: "Vocalinux supports Ubuntu, Fedora, Debian, Arch, Linux Mint, Pop!_OS, and other modern Linux distributions across X11 and Wayland.",
|
|
},
|
|
},
|
|
{
|
|
"@type": "Question",
|
|
name: "How do I switch between speech engines?",
|
|
acceptedAnswer: {
|
|
"@type": "Answer",
|
|
text: "Use the settings GUI or the CLI flags: vocalinux --engine whisper_cpp, vocalinux --engine whisper, or vocalinux --engine vosk.",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"@context": "https://schema.org",
|
|
"@type": "HowTo",
|
|
name: "Install Vocalinux on Linux",
|
|
description: "Install offline voice dictation on Linux in a few minutes.",
|
|
totalTime: "PT10M",
|
|
step: [
|
|
{
|
|
"@type": "HowToStep",
|
|
name: "Run the install command",
|
|
text: "Copy the install command from vocalinux.com and run it in terminal.",
|
|
url: "https://vocalinux.com/#install",
|
|
},
|
|
{
|
|
"@type": "HowToStep",
|
|
name: "Complete the guided setup",
|
|
text: "Pick your speech engine and model size in the interactive installer.",
|
|
url: "https://vocalinux.com/#install",
|
|
},
|
|
{
|
|
"@type": "HowToStep",
|
|
name: "Start dictating",
|
|
text: "Launch vocalinux and double-tap Ctrl to begin voice dictation.",
|
|
url: "https://vocalinux.com/#install",
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
const FeatureCard = ({
|
|
icon,
|
|
title,
|
|
description,
|
|
}: {
|
|
icon: React.ReactNode;
|
|
title: string;
|
|
description: string;
|
|
}) => {
|
|
const [ref, inView] = useInView({
|
|
triggerOnce: true,
|
|
threshold: 0.1,
|
|
});
|
|
return (
|
|
<motion.div
|
|
ref={ref}
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={inView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
|
transition={{ duration: 0.5 }}
|
|
className="bg-white dark:bg-zinc-800 p-6 rounded-xl shadow-md hover:shadow-xl transition-all h-full border border-zinc-100 dark:border-zinc-700"
|
|
>
|
|
<div className="flex items-center gap-4 mb-4">
|
|
<div className="bg-primary/10 p-3 rounded-lg">{icon}</div>
|
|
<h3 className="text-lg sm:text-xl font-semibold">{title}</h3>
|
|
</div>
|
|
<p className="text-sm sm:text-base text-muted-foreground">{description}</p>
|
|
</motion.div>
|
|
);
|
|
};
|
|
|
|
const CopyButton = ({ text, className = "" }: { text: string; className?: string }) => {
|
|
const [copied, setCopied] = useState(false);
|
|
|
|
const handleCopy = useCallback(() => {
|
|
navigator.clipboard.writeText(text);
|
|
setCopied(true);
|
|
setTimeout(() => setCopied(false), 2000);
|
|
}, [text]);
|
|
|
|
return (
|
|
<button
|
|
onClick={handleCopy}
|
|
className={`flex items-center gap-2 bg-zinc-700 hover:bg-zinc-600 text-white px-3 py-1.5 rounded text-sm transition-all ${className}`}
|
|
aria-label={copied ? "Copied to clipboard" : "Copy to clipboard"}
|
|
>
|
|
{copied ? (
|
|
<>
|
|
<Check className="h-4 w-4" />
|
|
Copied!
|
|
</>
|
|
) : (
|
|
<>
|
|
<Copy className="h-4 w-4" />
|
|
Copy
|
|
</>
|
|
)}
|
|
</button>
|
|
);
|
|
};
|
|
|
|
const FadeInSection = ({
|
|
children,
|
|
delay = 0,
|
|
}: {
|
|
children: React.ReactNode;
|
|
delay?: number;
|
|
}) => {
|
|
const [ref, inView] = useInView({
|
|
triggerOnce: true,
|
|
threshold: 0.1,
|
|
rootMargin: "0px 0px -50px 0px",
|
|
});
|
|
return (
|
|
<motion.div
|
|
ref={ref}
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={inView ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }}
|
|
transition={{ duration: 0.5, delay }}
|
|
className="w-full"
|
|
>
|
|
{children}
|
|
</motion.div>
|
|
);
|
|
};
|
|
|
|
export default function HomePage() {
|
|
const [stars, setStars] = useState<number | null>(null);
|
|
const [latestRelease, setLatestRelease] = useState<string>("main"); // Default to main for safety
|
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
|
|
|
useEffect(() => {
|
|
// Fetch actual GitHub stars and latest release
|
|
fetch("https://api.github.com/repos/jatinkrmalik/vocalinux")
|
|
.then((res) => res.json())
|
|
.then((data) => {
|
|
if (data.stargazers_count) {
|
|
setStars(data.stargazers_count);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
// Fallback if API fails
|
|
setStars(null);
|
|
});
|
|
|
|
// Fetch latest release tag for stable install commands
|
|
fetch("https://api.github.com/repos/jatinkrmalik/vocalinux/releases/latest")
|
|
.then((res) => res.json())
|
|
.then((data) => {
|
|
if (data.tag_name) {
|
|
setLatestRelease(data.tag_name);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
// Fallback to main if API fails
|
|
setLatestRelease("main");
|
|
});
|
|
}, []);
|
|
|
|
const navLinks = [
|
|
{ href: "#demo", label: "Demo" },
|
|
{ href: "#features", label: "Features" },
|
|
{ href: "#install", label: "Install" },
|
|
{ href: "#guides", label: "Guides" },
|
|
{ href: "#faq", label: "FAQ" },
|
|
];
|
|
|
|
// Get install commands based on the latest release
|
|
const installCommands = getInstallCommands(latestRelease);
|
|
const { interactiveInstallCommand, oneClickInstallCommand, oneClickInstallWhisper, oneClickInstallVosk, uninstallCommand } = installCommands;
|
|
|
|
return (
|
|
<main className="min-h-screen bg-gradient-to-b from-zinc-50 to-white dark:from-zinc-900 dark:to-zinc-950">
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(homeJsonLd) }}
|
|
/>
|
|
|
|
{/* Header */}
|
|
<header className="fixed top-0 left-0 right-0 z-50 bg-background/80 backdrop-blur-md border-b border-border">
|
|
<nav className="max-w-7xl mx-auto px-4 sm:px-6 py-3 flex items-center justify-between">
|
|
<Link href="/" className="flex items-center gap-2 group">
|
|
<VocalinuxLogo
|
|
width={32}
|
|
height={32}
|
|
className="h-7 w-7 sm:h-8 sm:w-8 transition-transform group-hover:scale-110"
|
|
priority
|
|
/>
|
|
<span className="font-bold text-lg sm:text-xl">Vocalinux</span>
|
|
<span className="hidden sm:inline-block text-xs bg-gradient-to-r from-primary/20 to-green-500/20 text-primary border border-primary/30 px-2.5 py-1 rounded-full font-semibold shadow-sm shadow-primary/20">
|
|
v0.6.1 Beta
|
|
</span>
|
|
</Link>
|
|
|
|
{/* Desktop navigation */}
|
|
<div className="hidden md:flex items-center gap-6">
|
|
{navLinks.map((link) => (
|
|
<a
|
|
key={link.href}
|
|
href={link.href}
|
|
className="text-muted-foreground hover:text-foreground transition-colors text-sm font-medium"
|
|
>
|
|
{link.label}
|
|
</a>
|
|
))}
|
|
<a
|
|
href="https://github.com/jatinkrmalik/vocalinux"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-2 text-muted-foreground hover:text-foreground transition-colors"
|
|
>
|
|
<Github className="h-5 w-5" />
|
|
{stars !== null && (
|
|
<span className="text-xs bg-zinc-100 dark:bg-zinc-800 px-2 py-0.5 rounded-full">
|
|
{stars.toLocaleString()}
|
|
</span>
|
|
)}
|
|
</a>
|
|
<ThemeToggle />
|
|
</div>
|
|
|
|
{/* Mobile navigation toggle */}
|
|
<div className="flex md:hidden items-center gap-3">
|
|
<ThemeToggle />
|
|
<button
|
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
|
className="p-2 text-foreground focus:outline-none"
|
|
aria-label="Toggle menu"
|
|
>
|
|
{mobileMenuOpen ? <X className="h-6 w-6" /> : <Menu className="h-6 w-6" />}
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
|
|
{/* Mobile menu */}
|
|
<motion.div
|
|
initial={{ height: 0, opacity: 0 }}
|
|
animate={{
|
|
height: mobileMenuOpen ? "auto" : 0,
|
|
opacity: mobileMenuOpen ? 1 : 0,
|
|
}}
|
|
transition={{ duration: 0.3 }}
|
|
className="md:hidden overflow-hidden bg-background border-b border-border"
|
|
>
|
|
<div className="px-4 py-3 space-y-2">
|
|
{navLinks.map((link) => (
|
|
<a
|
|
key={link.href}
|
|
href={link.href}
|
|
className="block py-2 text-foreground hover:text-primary transition-colors"
|
|
onClick={() => setMobileMenuOpen(false)}
|
|
>
|
|
{link.label}
|
|
</a>
|
|
))}
|
|
<a
|
|
href="https://github.com/jatinkrmalik/vocalinux"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-2 py-2 text-foreground hover:text-primary transition-colors"
|
|
onClick={() => setMobileMenuOpen(false)}
|
|
>
|
|
<Github className="h-5 w-5" />
|
|
GitHub
|
|
</a>
|
|
</div>
|
|
</motion.div>
|
|
</header>
|
|
|
|
{/* Hero Section */}
|
|
<section className="relative pt-28 sm:pt-36 pb-16 sm:pb-24 px-4 sm:px-6 overflow-hidden">
|
|
<div className="absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-purple-500/5 dark:from-primary/10 dark:to-purple-500/10" />
|
|
|
|
{/* Animated background elements */}
|
|
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
|
<motion.div
|
|
animate={{ rotate: 360 }}
|
|
transition={{ duration: 50, repeat: Infinity, ease: "linear" }}
|
|
className="absolute -top-1/2 -right-1/2 w-full h-full bg-gradient-to-br from-primary/5 to-transparent rounded-full blur-3xl"
|
|
/>
|
|
</div>
|
|
|
|
<div className="max-w-7xl mx-auto relative">
|
|
<div className="text-center max-w-4xl mx-auto">
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6 }}
|
|
>
|
|
{/* Badge */}
|
|
<div className="inline-flex items-center gap-2 bg-primary/10 px-4 py-2 rounded-full mb-6">
|
|
<Sparkles className="h-4 w-4 text-primary" />
|
|
<span className="text-sm font-medium text-primary">
|
|
Beta Release — Try it now!
|
|
</span>
|
|
</div>
|
|
|
|
<h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-bold tracking-tight mb-6">
|
|
Voice Dictation for Linux,{" "}
|
|
<span className="text-transparent bg-clip-text bg-gradient-to-r from-primary to-purple-600">
|
|
Finally Done Right
|
|
</span>
|
|
</h1>
|
|
|
|
<p className="text-lg sm:text-xl md:text-2xl text-muted-foreground mb-2 max-w-3xl mx-auto">
|
|
100% offline voice dictation for Linux.
|
|
</p>
|
|
<p className="text-lg sm:text-xl md:text-2xl text-muted-foreground mb-8 max-w-3xl mx-auto">
|
|
Just double-tap Ctrl and speak.
|
|
</p>
|
|
|
|
{/* CTA Buttons */}
|
|
<div className="flex flex-col sm:flex-row gap-4 justify-center mb-12">
|
|
<a
|
|
href="#install"
|
|
className="inline-flex items-center justify-center gap-2 bg-primary text-white dark:text-zinc-900 hover:bg-primary/90 px-8 py-4 rounded-xl text-lg font-semibold transition-all hover:scale-105 shadow-lg shadow-primary/25"
|
|
>
|
|
<Download className="h-5 w-5" />
|
|
Install Now — It's Free
|
|
</a>
|
|
<a
|
|
href="#demo"
|
|
className="inline-flex items-center justify-center gap-2 bg-secondary text-secondary-foreground hover:bg-secondary/80 px-8 py-4 rounded-xl text-lg font-semibold transition-all"
|
|
>
|
|
<Play className="h-5 w-5" />
|
|
Watch Demo
|
|
</a>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* One-Click Install Box - Redesigned */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 30 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.2 }}
|
|
className="w-full max-w-6xl mx-auto px-4"
|
|
>
|
|
<div className="bg-gradient-to-br from-zinc-900 to-zinc-950 rounded-2xl p-6 sm:p-8 shadow-2xl border border-zinc-800/50 backdrop-blur">
|
|
{/* Header */}
|
|
<div className="flex items-center gap-3 mb-5">
|
|
<div className="flex items-center justify-center h-10 w-10 rounded-full bg-green-500/20 flex-shrink-0">
|
|
<Terminal className="h-5 w-5 text-green-400" />
|
|
</div>
|
|
<div className="text-left">
|
|
<h2 className="text-lg font-semibold text-white text-left">Quick Install (Interactive)</h2>
|
|
<p className="text-xs text-zinc-400 text-left">Guided installation with hardware detection</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Command box */}
|
|
<div className="bg-zinc-950/80 rounded-xl border border-zinc-800 overflow-hidden">
|
|
<div className="flex items-center justify-between px-4 py-2.5 border-b border-zinc-800 bg-zinc-900/50">
|
|
<div className="flex items-center gap-2">
|
|
<div className="h-2.5 w-2.5 rounded-full bg-red-500/70" />
|
|
<div className="h-2.5 w-2.5 rounded-full bg-yellow-500/70" />
|
|
<div className="h-2.5 w-2.5 rounded-full bg-green-500/70" />
|
|
</div>
|
|
<CopyButton text={interactiveInstallCommand} />
|
|
</div>
|
|
<div className="p-4 sm:p-5">
|
|
<pre className="font-mono text-sm sm:text-base text-green-400 text-left whitespace-pre-wrap">
|
|
<span className="text-zinc-500 select-none">$ </span>{interactiveInstallCommand}
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Bottom info */}
|
|
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mt-5 pt-5 border-t border-zinc-800/50">
|
|
<p className="text-sm text-zinc-400">
|
|
<span className="text-zinc-500">Compatible:</span> Ubuntu, Fedora, Debian, Arch & more
|
|
</p>
|
|
<div className="flex items-center gap-4 text-xs text-zinc-500">
|
|
<span className="flex items-center gap-1.5">
|
|
<CheckCircle2 className="h-3.5 w-3.5 text-green-500" />
|
|
No sudo required
|
|
</span>
|
|
<span className="flex items-center gap-1.5">
|
|
<Zap className="h-3.5 w-3.5 text-green-500" />
|
|
~1-2 min
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Tech stack info */}
|
|
<div className="flex flex-wrap justify-center items-center gap-4 sm:gap-6 mt-4 pt-4 border-t border-zinc-800/30 text-xs text-zinc-400">
|
|
<span className="flex items-center gap-1.5">
|
|
<Zap className="h-3.5 w-3.5 text-yellow-500" />
|
|
<strong className="text-zinc-300">whisper.cpp</strong> powered
|
|
</span>
|
|
<span className="flex items-center gap-1.5">
|
|
<Globe className="h-3.5 w-3.5 text-blue-500" />
|
|
AMD, Intel & NVIDIA GPUs
|
|
</span>
|
|
<span className="flex items-center gap-1.5">
|
|
<Code className="h-3.5 w-3.5 text-purple-500" />
|
|
Free & open-source
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Trust indicators */}
|
|
<motion.div
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
transition={{ duration: 0.6, delay: 0.4 }}
|
|
className="flex flex-wrap justify-center items-center gap-6 sm:gap-10 mt-12 text-sm text-muted-foreground"
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<Shield className="h-5 w-5 text-green-500" />
|
|
<span>100% Offline</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Lock className="h-5 w-5 text-blue-500" />
|
|
<span>Privacy First</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Code className="h-5 w-5 text-purple-500" />
|
|
<span>Open Source (GPL-3.0)</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Globe className="h-5 w-5 text-orange-500" />
|
|
<span>X11 & Wayland</span>
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Demo Section - Live Interactive Demo */}
|
|
<section id="demo" className="py-16 sm:py-24 px-4 sm:px-6 bg-zinc-50 dark:bg-zinc-900/50">
|
|
<div className="max-w-6xl mx-auto">
|
|
<FadeInSection>
|
|
<div className="text-center mb-12">
|
|
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold mb-4">
|
|
Try Linux Speech-to-Text in Your Browser
|
|
</h2>
|
|
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
|
Experience voice-to-text right here in your browser. Click the microphone and start speaking!
|
|
</p>
|
|
</div>
|
|
</FadeInSection>
|
|
|
|
<FadeInSection delay={0.1}>
|
|
<LiveDemo />
|
|
</FadeInSection>
|
|
|
|
{/* Key demo points */}
|
|
<FadeInSection delay={0.2}>
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-12">
|
|
{[
|
|
{
|
|
icon: <Keyboard className="h-6 w-6 text-primary" />,
|
|
title: "Double-tap Ctrl",
|
|
description: "In the real app, just double-tap Ctrl to start dictating anywhere",
|
|
},
|
|
{
|
|
icon: <Zap className="h-6 w-6 text-primary" />,
|
|
title: "Real-time Transcription",
|
|
description: "See your words appear as you speak with minimal latency",
|
|
},
|
|
{
|
|
icon: <Volume2 className="h-6 w-6 text-primary" />,
|
|
title: "Audio Feedback",
|
|
description: "Subtle sounds let you know when recording starts and stops",
|
|
},
|
|
].map((item, i) => (
|
|
<div
|
|
key={i}
|
|
className="flex items-start gap-4 p-4 rounded-xl bg-white dark:bg-zinc-800 border border-zinc-200 dark:border-zinc-700"
|
|
>
|
|
<div className="bg-primary/10 p-2 rounded-lg">{item.icon}</div>
|
|
<div>
|
|
<h3 className="font-semibold mb-1">{item.title}</h3>
|
|
<p className="text-sm text-muted-foreground">{item.description}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</FadeInSection>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Features Section */}
|
|
<section id="features" className="py-16 sm:py-24 px-4 sm:px-6">
|
|
<div className="max-w-7xl mx-auto">
|
|
<FadeInSection>
|
|
<div className="text-center mb-16">
|
|
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold mb-4">
|
|
Offline Voice Dictation Features for Linux
|
|
</h2>
|
|
<p className="text-lg text-muted-foreground max-w-3xl mx-auto">
|
|
Finally, Linux users get the voice dictation experience they deserve —
|
|
no compromises on privacy, no cloud dependencies, just pure productivity.
|
|
</p>
|
|
</div>
|
|
</FadeInSection>
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
<FeatureCard
|
|
icon={<Shield className="h-6 w-6 text-primary" />}
|
|
title="100% Offline & Private"
|
|
description="All processing happens on your machine. Your voice data never leaves your computer — complete privacy guaranteed."
|
|
/>
|
|
<FeatureCard
|
|
icon={<Laptop className="h-6 w-6 text-primary" />}
|
|
title="Universal App Support"
|
|
description="Works everywhere — terminals, browsers, IDEs, office apps, and any text input field on your Linux system."
|
|
/>
|
|
<FeatureCard
|
|
icon={<Zap className="h-6 w-6 text-primary" />}
|
|
title="Blazing Fast"
|
|
description="whisper.cpp brings C++ optimized inference with Vulkan GPU support. Works with AMD, Intel, and NVIDIA GPUs!"
|
|
/>
|
|
<FeatureCard
|
|
icon={<Keyboard className="h-6 w-6 text-primary" />}
|
|
title="Simple Activation"
|
|
description="Double-tap Ctrl to start, double-tap again to stop. No complex keyboard shortcuts to memorize."
|
|
/>
|
|
<FeatureCard
|
|
icon={<Globe className="h-6 w-6 text-primary" />}
|
|
title="X11 & Wayland Support"
|
|
description="Works seamlessly with both display servers. Modern Wayland and traditional X11 — we've got you covered."
|
|
/>
|
|
<FeatureCard
|
|
icon={<Settings className="h-6 w-6 text-primary" />}
|
|
title="Fully Configurable"
|
|
description="Adjust model size, language, activation method, and more. GUI settings panel or config file — your choice."
|
|
/>
|
|
</div>
|
|
|
|
{/* Comparison highlight */}
|
|
<FadeInSection delay={0.2}>
|
|
<div className="mt-16 bg-gradient-to-r from-primary/10 via-purple-500/10 to-primary/10 rounded-2xl p-8 sm:p-12">
|
|
<div className="grid md:grid-cols-2 gap-8 items-center">
|
|
<div>
|
|
<h3 className="text-2xl sm:text-3xl font-bold mb-4">
|
|
The Linux Voice Gap, Solved
|
|
</h3>
|
|
<p className="text-muted-foreground mb-6">
|
|
While macOS and Windows have had built-in voice dictation for years,
|
|
Linux users have been left behind — until now.
|
|
</p>
|
|
<ul className="space-y-3">
|
|
{[
|
|
"No more cloud services that compromise privacy",
|
|
"No more janky solutions that only work in specific apps",
|
|
"No more complicated setup processes",
|
|
"Just install and start dictating",
|
|
].map((item, i) => (
|
|
<li key={i} className="flex items-start gap-3">
|
|
<CheckCircle2 className="h-5 w-5 text-green-500 flex-shrink-0 mt-0.5" />
|
|
<span>{item}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
<div className="flex justify-center">
|
|
<div className="relative">
|
|
<div className="bg-white dark:bg-zinc-800 rounded-2xl p-8 shadow-xl">
|
|
<div className="flex items-center gap-4 mb-6">
|
|
<VocalinuxLogo width={64} height={64} className="h-16 w-16" />
|
|
<div>
|
|
<div className="text-2xl font-bold">Vocalinux</div>
|
|
<div className="text-sm text-muted-foreground">
|
|
Voice dictation, finally
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4 text-center">
|
|
<div className="p-3 bg-zinc-50 dark:bg-zinc-900 rounded-lg">
|
|
<div className="text-2xl font-bold text-primary">0</div>
|
|
<div className="text-xs text-muted-foreground">Cloud calls</div>
|
|
</div>
|
|
<div className="p-3 bg-zinc-50 dark:bg-zinc-900 rounded-lg">
|
|
<div className="text-2xl font-bold text-primary">∞</div>
|
|
<div className="text-xs text-muted-foreground">Privacy</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</FadeInSection>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Installation Section */}
|
|
<section id="install" className="py-16 sm:py-24 px-4 sm:px-6 bg-zinc-50 dark:bg-zinc-900/50">
|
|
<div className="max-w-4xl mx-auto">
|
|
<FadeInSection>
|
|
<div className="text-center mb-12">
|
|
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold mb-4">
|
|
How to Install Voice Dictation on Linux
|
|
</h2>
|
|
<p className="text-lg text-muted-foreground">
|
|
One command. That's all it takes.
|
|
</p>
|
|
</div>
|
|
</FadeInSection>
|
|
|
|
<FadeInSection delay={0.1}>
|
|
<div className="bg-white dark:bg-zinc-800 rounded-2xl shadow-xl overflow-hidden border border-zinc-200 dark:border-zinc-700 min-w-0">
|
|
<div className="p-6 sm:p-8">
|
|
{/* Default: whisper.cpp install */}
|
|
<div className="mb-8">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="bg-green-500/10 p-2 rounded-lg">
|
|
<Zap className="h-5 w-5 text-green-500" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className="text-xl font-semibold">Recommended: whisper.cpp (Default)</h3>
|
|
<p className="text-sm text-muted-foreground">
|
|
Fastest installation (~1-2 min), Vulkan GPU support for AMD/Intel/NVIDIA
|
|
</p>
|
|
</div>
|
|
<CopyButton text={oneClickInstallCommand} />
|
|
</div>
|
|
<div className="overflow-x-auto">
|
|
<CodeBlock
|
|
language="bash"
|
|
className="rounded-lg text-sm sm:text-base"
|
|
customStyle={{ margin: 0, maxWidth: '100%', overflowX: 'auto' }}
|
|
wrapLongLines={false}
|
|
>
|
|
{oneClickInstallCommand}
|
|
</CodeBlock>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Alternative install - Whisper (OpenAI) */}
|
|
<div className="border-t border-zinc-200 dark:border-zinc-700 pt-6">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="bg-cyan-500/10 p-2 rounded-lg">
|
|
<Cpu className="h-5 w-5 text-cyan-500" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className="text-lg font-semibold">OpenAI Whisper (PyTorch)</h3>
|
|
<p className="text-sm text-muted-foreground">
|
|
PyTorch-based engine, NVIDIA GPU only (~5-10 min, ~2.3GB download)
|
|
</p>
|
|
</div>
|
|
<CopyButton text={oneClickInstallWhisper} />
|
|
</div>
|
|
<div className="overflow-x-auto">
|
|
<CodeBlock
|
|
language="bash"
|
|
className="rounded-lg text-sm"
|
|
customStyle={{ margin: 0, maxWidth: '100%', overflowX: 'auto' }}
|
|
wrapLongLines={false}
|
|
>
|
|
{oneClickInstallWhisper}
|
|
</CodeBlock>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Alternative install - VOSK only */}
|
|
<div className="border-t border-zinc-200 dark:border-zinc-700 pt-6">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="bg-orange-500/10 p-2 rounded-lg">
|
|
<Zap className="h-5 w-5 text-orange-500" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h3 className="text-lg font-semibold">VOSK Only (Lightweight)</h3>
|
|
<p className="text-sm text-muted-foreground">
|
|
For low-RAM systems (4GB or less) - minimal footprint (~40MB)
|
|
</p>
|
|
</div>
|
|
<CopyButton text={oneClickInstallVosk} />
|
|
</div>
|
|
<div className="overflow-x-auto">
|
|
<CodeBlock
|
|
language="bash"
|
|
className="rounded-lg text-sm"
|
|
customStyle={{ margin: 0, maxWidth: '100%', overflowX: 'auto' }}
|
|
wrapLongLines={false}
|
|
>
|
|
{oneClickInstallVosk}
|
|
</CodeBlock>
|
|
</div>
|
|
</div>
|
|
|
|
{/* What the installer does */}
|
|
<div className="mt-8 p-4 bg-zinc-50 dark:bg-zinc-900 rounded-lg">
|
|
<h4 className="font-semibold mb-3">What the installer does:</h4>
|
|
<ul className="grid sm:grid-cols-2 gap-2 text-sm text-muted-foreground">
|
|
{[
|
|
"Installs system dependencies",
|
|
"Creates isolated virtual environment",
|
|
"Downloads speech recognition models",
|
|
"Sets up desktop integration",
|
|
"Adds vocalinux to your PATH",
|
|
"Creates application launcher",
|
|
].map((item, i) => (
|
|
<li key={i} className="flex items-center gap-2">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
{item}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
|
|
{/* After install */}
|
|
<div className="mt-6 p-4 bg-primary/5 rounded-lg border border-primary/20">
|
|
<h4 className="font-semibold mb-2 flex items-center gap-2">
|
|
<Play className="h-4 w-4 text-primary" />
|
|
After Installation
|
|
</h4>
|
|
<p className="text-sm text-muted-foreground mb-3">
|
|
Launch Vocalinux from your terminal or application menu:
|
|
</p>
|
|
<code className="block bg-zinc-900 text-green-400 px-4 py-2 rounded text-sm">
|
|
vocalinux
|
|
</code>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</FadeInSection>
|
|
|
|
{/* System requirements */}
|
|
<FadeInSection delay={0.2}>
|
|
<div className="mt-8 grid sm:grid-cols-2 gap-6">
|
|
<div className="bg-white dark:bg-zinc-800 p-6 rounded-xl border border-zinc-200 dark:border-zinc-700 min-w-0">
|
|
<h4 className="font-semibold mb-4 flex items-center gap-2">
|
|
<Cpu className="h-5 w-5 text-primary" />
|
|
System Requirements
|
|
</h4>
|
|
<ul className="space-y-2 text-sm text-muted-foreground">
|
|
<li>• Ubuntu 22.04+ (or equivalent)</li>
|
|
<li>• Python 3.8 or newer</li>
|
|
<li>• 4GB RAM (8GB for large models)</li>
|
|
<li>• Microphone</li>
|
|
<li>• X11 or Wayland display server</li>
|
|
</ul>
|
|
</div>
|
|
<div className="bg-white dark:bg-zinc-800 p-6 rounded-xl border border-zinc-200 dark:border-zinc-700 min-w-0">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="bg-red-500/10 p-2 rounded-lg">
|
|
<Terminal className="h-5 w-5 text-red-500" />
|
|
</div>
|
|
<div className="flex-1">
|
|
<h4 className="font-semibold">Uninstall</h4>
|
|
<p className="text-sm text-muted-foreground">
|
|
Clean removal in one command
|
|
</p>
|
|
</div>
|
|
<CopyButton text={uninstallCommand} />
|
|
</div>
|
|
<div className="overflow-x-auto">
|
|
<CodeBlock
|
|
language="bash"
|
|
className="rounded-lg text-sm"
|
|
customStyle={{ margin: 0, maxWidth: '100%', overflowX: 'auto' }}
|
|
wrapLongLines={false}
|
|
>
|
|
{uninstallCommand}
|
|
</CodeBlock>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</FadeInSection>
|
|
</div>
|
|
</section>
|
|
|
|
{/* SEO Guide Hub Section */}
|
|
<section id="guides" className="py-16 sm:py-24 px-4 sm:px-6">
|
|
<div className="max-w-6xl mx-auto">
|
|
<FadeInSection>
|
|
<div className="text-center mb-12">
|
|
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold mb-4">
|
|
Linux Voice Dictation Guides by Distribution
|
|
</h2>
|
|
<p className="text-lg text-muted-foreground max-w-3xl mx-auto">
|
|
Follow distro-specific setup instructions for Ubuntu, Fedora, and Arch Linux.
|
|
These pages are written for real desktop workflows and include post-install checks.
|
|
</p>
|
|
</div>
|
|
</FadeInSection>
|
|
|
|
<div className="grid gap-6 md:grid-cols-3">
|
|
{[
|
|
{
|
|
href: "/install/ubuntu/",
|
|
title: "Ubuntu Voice Typing Guide",
|
|
description:
|
|
"Install offline speech-to-text on Ubuntu 22.04+ for GNOME, KDE, X11, and Wayland.",
|
|
},
|
|
{
|
|
href: "/install/fedora/",
|
|
title: "Fedora Speech-to-Text Guide",
|
|
description:
|
|
"Set up Vocalinux on Fedora Workstation with distro-specific notes for a stable dictation flow.",
|
|
},
|
|
{
|
|
href: "/install/arch/",
|
|
title: "Arch Linux Dictation Guide",
|
|
description:
|
|
"Lean setup for Arch, Manjaro, and EndeavourOS with hardware and injection sanity checks.",
|
|
},
|
|
].map((guide) => (
|
|
<Link
|
|
key={guide.href}
|
|
href={guide.href}
|
|
className="group rounded-2xl border border-zinc-200 bg-white p-6 shadow-sm transition-all hover:-translate-y-1 hover:shadow-lg dark:border-zinc-700 dark:bg-zinc-800"
|
|
>
|
|
<h3 className="mb-3 text-xl font-semibold">{guide.title}</h3>
|
|
<p className="mb-4 text-sm text-muted-foreground">{guide.description}</p>
|
|
<span className="inline-flex items-center gap-1 text-sm font-semibold text-primary group-hover:underline">
|
|
Read guide <ChevronRight className="h-4 w-4" />
|
|
</span>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
|
|
<FadeInSection delay={0.15}>
|
|
<div className="mt-8 rounded-2xl border border-primary/20 bg-primary/5 p-6 sm:p-8">
|
|
<h3 className="text-2xl font-bold mb-3">Need help choosing an engine?</h3>
|
|
<p className="text-muted-foreground mb-4">
|
|
Compare whisper.cpp, Whisper, and VOSK for speed, hardware support, and model size.
|
|
</p>
|
|
<Link
|
|
href="/compare/"
|
|
className="inline-flex items-center gap-2 text-sm font-semibold text-primary hover:underline"
|
|
>
|
|
View speech engine comparison <ChevronRight className="h-4 w-4" />
|
|
</Link>
|
|
</div>
|
|
</FadeInSection>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Speech Engines Section */}
|
|
<section className="py-16 sm:py-24 px-4 sm:px-6 bg-zinc-50 dark:bg-zinc-900/50">
|
|
<div className="max-w-5xl mx-auto">
|
|
<FadeInSection>
|
|
<div className="text-center mb-12">
|
|
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold mb-4">
|
|
Choose Your Linux Speech Recognition Engine
|
|
</h2>
|
|
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
|
Vocalinux supports multiple speech recognition engines. Pick the one that suits your needs.
|
|
</p>
|
|
</div>
|
|
</FadeInSection>
|
|
|
|
<div className="grid md:grid-cols-3 gap-8">
|
|
<FadeInSection delay={0.1}>
|
|
<div className="bg-white dark:bg-zinc-800 rounded-xl p-6 border-2 border-primary h-full relative overflow-hidden">
|
|
<div className="absolute top-4 right-4">
|
|
<span className="bg-primary text-primary-foreground text-xs font-semibold px-2 py-1 rounded">
|
|
DEFAULT
|
|
</span>
|
|
</div>
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="bg-primary/10 p-3 rounded-lg">
|
|
<Zap className="h-6 w-6 text-primary" />
|
|
</div>
|
|
<h3 className="text-xl font-bold">whisper.cpp</h3>
|
|
</div>
|
|
<p className="text-muted-foreground mb-6">
|
|
High-performance C++ port of Whisper with Vulkan GPU support. Our new default!
|
|
</p>
|
|
<ul className="space-y-2 mb-6">
|
|
{[
|
|
"10x faster installation (~1-2 min)",
|
|
"Universal GPU support (AMD/Intel/NVIDIA)",
|
|
"C++ optimized, true multi-threading",
|
|
"Tiny model only ~39MB",
|
|
].map((item, i) => (
|
|
<li key={i} className="flex items-center gap-2 text-sm">
|
|
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
{item}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<div className="text-sm text-muted-foreground">
|
|
<strong>Model sizes:</strong> Tiny (39MB) • Base (74MB) • Small (244MB) • Medium (769MB) • Large (1.5GB)
|
|
</div>
|
|
</div>
|
|
</FadeInSection>
|
|
|
|
<FadeInSection delay={0.2}>
|
|
<div className="bg-white dark:bg-zinc-800 rounded-xl p-6 border border-zinc-200 dark:border-zinc-700 h-full">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="bg-purple-500/10 p-3 rounded-lg">
|
|
<Sparkles className="h-6 w-6 text-purple-500" />
|
|
</div>
|
|
<h3 className="text-xl font-bold">Whisper (OpenAI)</h3>
|
|
</div>
|
|
<p className="text-muted-foreground mb-6">
|
|
OpenAI's original PyTorch-based Whisper model. NVIDIA GPU only.
|
|
</p>
|
|
<ul className="space-y-2 mb-6">
|
|
{[
|
|
"PyTorch-based implementation",
|
|
"NVIDIA GPU support (CUDA)",
|
|
"Same accuracy as whisper.cpp",
|
|
"Larger download (~2.3GB)",
|
|
].map((item, i) => (
|
|
<li key={i} className="flex items-center gap-2 text-sm">
|
|
<CheckCircle2 className="h-4 w-4 text-purple-500" />
|
|
{item}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<div className="text-sm text-muted-foreground">
|
|
<strong>Install time:</strong> ~5-10 minutes with PyTorch
|
|
</div>
|
|
</div>
|
|
</FadeInSection>
|
|
|
|
<FadeInSection delay={0.3}>
|
|
<div className="bg-white dark:bg-zinc-800 rounded-xl p-6 border border-zinc-200 dark:border-zinc-700 h-full">
|
|
<div className="flex items-center gap-3 mb-4">
|
|
<div className="bg-blue-500/10 p-3 rounded-lg">
|
|
<Cpu className="h-6 w-6 text-blue-500" />
|
|
</div>
|
|
<h3 className="text-xl font-bold">VOSK</h3>
|
|
</div>
|
|
<p className="text-muted-foreground mb-6">
|
|
Lightweight, fast speech recognition engine perfect for lower-powered systems.
|
|
</p>
|
|
<ul className="space-y-2 mb-6">
|
|
{[
|
|
"Very lightweight and fast",
|
|
"Low memory footprint",
|
|
"Great for real-time streaming",
|
|
"CPU only, minimal resources",
|
|
].map((item, i) => (
|
|
<li key={i} className="flex items-center gap-2 text-sm">
|
|
<CheckCircle2 className="h-4 w-4 text-blue-500" />
|
|
{item}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<div className="text-sm text-muted-foreground">
|
|
<strong>Footprint:</strong> ~40MB model, minimal CPU/RAM usage
|
|
</div>
|
|
</div>
|
|
</FadeInSection>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* FAQ Section */}
|
|
<section id="faq" className="py-16 sm:py-24 px-4 sm:px-6">
|
|
<div className="max-w-3xl mx-auto">
|
|
<FadeInSection>
|
|
<div className="text-center mb-12">
|
|
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold mb-4">
|
|
Frequently Asked Questions
|
|
</h2>
|
|
</div>
|
|
</FadeInSection>
|
|
|
|
<div className="space-y-4">
|
|
{[
|
|
{
|
|
question: "Is Vocalinux really 100% offline?",
|
|
answer:
|
|
"Yes! All speech recognition processing happens locally on your machine. Your voice data never leaves your computer. No internet connection is required after installation (models are downloaded during setup).",
|
|
},
|
|
{
|
|
question: "Which Linux distributions are supported?",
|
|
answer:
|
|
"Vocalinux works on most modern Linux distributions including Ubuntu 22.04+, Fedora, Debian, Arch Linux, Linux Mint, Pop!_OS, and more. It supports both X11 and Wayland display servers.",
|
|
},
|
|
{
|
|
question: "How do I switch between speech engines?",
|
|
answer:
|
|
'You can switch engines via the settings GUI or command line. Use "vocalinux --engine whisper_cpp" (default, recommended), "vocalinux --engine whisper" (OpenAI), or "vocalinux --engine vosk" (lightweight). whisper.cpp offers the best balance of speed and accuracy.',
|
|
},
|
|
{
|
|
question: "What are the system requirements?",
|
|
answer:
|
|
"Minimum: 4GB RAM, dual-core CPU, Python 3.8+. For Whisper large models: 8GB+ RAM recommended. The tiny/base Whisper models and VOSK work great on modest hardware.",
|
|
},
|
|
{
|
|
question: "Can I use it in languages other than English?",
|
|
answer:
|
|
"Yes! Whisper supports 99+ languages with varying accuracy levels. VOSK has models for 20+ languages. Download additional language models as needed.",
|
|
},
|
|
{
|
|
question: "How do I customize the activation shortcut?",
|
|
answer:
|
|
"The default is double-tap Ctrl. You can customize this via the GUI settings dialog or by editing ~/.config/vocalinux/config.yaml. Any key combination is supported.",
|
|
},
|
|
{
|
|
question: "Is Vocalinux free?",
|
|
answer:
|
|
"Yes, Vocalinux is completely free and open-source, licensed under GPL-3.0. No premium tiers, no subscriptions, no tracking — just free software.",
|
|
},
|
|
].map((item, i) => (
|
|
<FadeInSection key={i} delay={i * 0.05}>
|
|
<details className="group bg-white dark:bg-zinc-800 rounded-xl border border-zinc-200 dark:border-zinc-700">
|
|
<summary className="flex items-center justify-between p-6 cursor-pointer list-none">
|
|
<h3 className="font-semibold pr-4">{item.question}</h3>
|
|
<ChevronRight className="h-5 w-5 text-muted-foreground transition-transform group-open:rotate-90" />
|
|
</summary>
|
|
<div className="px-6 pb-6 text-muted-foreground">
|
|
{item.answer}
|
|
</div>
|
|
</details>
|
|
</FadeInSection>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
{/* CTA Section */}
|
|
<section className="py-16 sm:py-24 px-4 sm:px-6 bg-gradient-to-br from-primary/10 via-purple-500/10 to-primary/10">
|
|
<div className="max-w-4xl mx-auto text-center">
|
|
<FadeInSection>
|
|
<h2 className="text-3xl sm:text-4xl md:text-5xl font-bold mb-6">
|
|
Ready to Ditch Your Keyboard?
|
|
</h2>
|
|
<p className="text-lg text-muted-foreground mb-8 max-w-2xl mx-auto">
|
|
Join the growing community of Linux users who have discovered the power of voice dictation.
|
|
It's free, it's private, and it just works.
|
|
</p>
|
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
|
<a
|
|
href="#install"
|
|
className="inline-flex items-center justify-center gap-2 bg-primary text-white dark:text-zinc-900 hover:bg-primary/90 px-8 py-4 rounded-xl text-lg font-semibold transition-all hover:scale-105 shadow-lg shadow-primary/25"
|
|
>
|
|
<Download className="h-5 w-5" />
|
|
Install Vocalinux
|
|
</a>
|
|
<a
|
|
href="https://github.com/jatinkrmalik/vocalinux"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="inline-flex items-center justify-center gap-2 bg-zinc-900 text-white hover:bg-zinc-800 px-8 py-4 rounded-xl text-lg font-semibold transition-all"
|
|
>
|
|
<Star className="h-5 w-5" />
|
|
Star on GitHub
|
|
</a>
|
|
</div>
|
|
</FadeInSection>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Footer */}
|
|
<footer className="py-12 px-4 sm:px-6 bg-zinc-900 text-white">
|
|
<div className="max-w-7xl mx-auto">
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-8 mb-12">
|
|
<div className="md:col-span-2">
|
|
<Link href="/" className="flex items-center gap-2 mb-4">
|
|
<VocalinuxLogo width={32} height={32} className="h-8 w-8" />
|
|
<span className="text-xl font-bold">Vocalinux</span>
|
|
</Link>
|
|
<p className="text-zinc-400 mb-4 max-w-md">
|
|
Free, open-source voice dictation for Linux. 100% offline and privacy-focused.
|
|
</p>
|
|
<div className="flex items-center gap-4">
|
|
<a
|
|
href="https://github.com/jatinkrmalik/vocalinux"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-zinc-400 hover:text-white transition-colors"
|
|
aria-label="GitHub"
|
|
>
|
|
<Github className="h-6 w-6" />
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<h3 className="font-semibold mb-4">Quick Links</h3>
|
|
<ul className="space-y-2 text-sm">
|
|
<li>
|
|
<a href="#features" className="text-zinc-400 hover:text-white transition-colors">
|
|
Features
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="#install" className="text-zinc-400 hover:text-white transition-colors">
|
|
Installation
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="#faq" className="text-zinc-400 hover:text-white transition-colors">
|
|
FAQ
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<Link href="/install/" className="text-zinc-400 hover:text-white transition-colors">
|
|
Linux Install Guides
|
|
</Link>
|
|
</li>
|
|
<li>
|
|
<Link href="/install/ubuntu/" className="text-zinc-400 hover:text-white transition-colors">
|
|
Ubuntu Guide
|
|
</Link>
|
|
</li>
|
|
<li>
|
|
<Link href="/install/fedora/" className="text-zinc-400 hover:text-white transition-colors">
|
|
Fedora Guide
|
|
</Link>
|
|
</li>
|
|
<li>
|
|
<Link href="/install/arch/" className="text-zinc-400 hover:text-white transition-colors">
|
|
Arch Guide
|
|
</Link>
|
|
</li>
|
|
<li>
|
|
<Link href="/compare/" className="text-zinc-400 hover:text-white transition-colors">
|
|
Engine Comparison
|
|
</Link>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div>
|
|
<h3 className="font-semibold mb-4">Resources</h3>
|
|
<ul className="space-y-2 text-sm">
|
|
<li>
|
|
<a
|
|
href="https://github.com/jatinkrmalik/vocalinux"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-zinc-400 hover:text-white transition-colors"
|
|
>
|
|
GitHub Repository
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
href="https://github.com/jatinkrmalik/vocalinux/issues"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-zinc-400 hover:text-white transition-colors"
|
|
>
|
|
Report Issues
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
href="https://github.com/jatinkrmalik/vocalinux/discussions"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-zinc-400 hover:text-white transition-colors"
|
|
>
|
|
Discussions
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<Link href="/install/" className="text-zinc-400 hover:text-white transition-colors">
|
|
Setup by Distribution
|
|
</Link>
|
|
</li>
|
|
<li>
|
|
<Link href="/compare/" className="text-zinc-400 hover:text-white transition-colors">
|
|
whisper.cpp vs Whisper vs VOSK
|
|
</Link>
|
|
</li>
|
|
<li>
|
|
<a
|
|
href="https://github.com/jatinkrmalik/vocalinux/blob/main/CONTRIBUTING.md"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-zinc-400 hover:text-white transition-colors"
|
|
>
|
|
Contributing
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pt-8 border-t border-zinc-800 flex flex-col sm:flex-row justify-between items-center gap-4">
|
|
<p className="text-zinc-400 text-sm">
|
|
© {new Date().getFullYear()} Vocalinux. Open-source under GPL-3.0 License.
|
|
</p>
|
|
<p className="text-zinc-400 text-sm flex items-center gap-1">
|
|
Made with <Heart className="h-4 w-4 text-red-500" /> by{" "}
|
|
<a
|
|
href="https://x.com/intent/user?screen_name=jatinkrmalik"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-zinc-400 hover:text-white transition-colors"
|
|
>
|
|
Jatin K Malik
|
|
</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
</main>
|
|
);
|
|
}
|