refactor(web): decompose 832-LOC landing into 10 section components
app/_components/landing-page.tsx: 832 LOC -> 33-LOC composition shell. Each section becomes a focused, named component under components/landing/sections/: - hero.tsx: terminal headline + install command + primary CTA - ultrawork.tsx: ultrawork mode pitch - sisyphus.tsx: Sisyphus orchestrator showcase - prometheus-atlas.tsx: planner + executor pair (was amber+indigo, now violet — single secondary accent) - hephaestus.tsx: code surgeon (was orange, now cyan) - team-mode.tsx: parallel team coordination (was fuchsia/purple/cyan gradient, now solid cyan headline + violet skills accent) - sub-agents.tsx: explore/librarian/oracle/multimodal etc. - architecture.tsx: 4-tier diagram - reviews.tsx: testimonials (Star kept text-cyan-500 / fill-cyan-500, on-brand) - cta.tsx: final call-to-action components/landing/constants.ts (new): - SUB_AGENT_KEYS, AGENT_STYLES, PRINCIPLE_KEYS, PRINCIPLE_ICONS, REVIEW_KEYS, CATEGORY_ROUTING, SKILL_INJECTIONS - Single source of truth for agent/principle/review metadata used across sections components/icons/github-icon.tsx (new): - Extracted inline SVG into a typed component with default aria-hidden and overridable size/className Color consolidation: 9-color rainbow per-section -> cyan (primary) + violet (secondary, agent identity) + neutral grays + status colors only. 'Evolution not revolution': dark + cyan brand soul intact.
This commit is contained in:
@@ -1,44 +1,15 @@
|
|||||||
import type { Metadata } from "next"
|
import type { Metadata } from "next"
|
||||||
import type { JSX, SVGProps } from "react"
|
import type { JSX } from "react"
|
||||||
import { getTranslations } from "next-intl/server"
|
import { ArchitectureSection } from "@/components/landing/sections/architecture"
|
||||||
import {
|
import { CtaSection } from "@/components/landing/sections/cta"
|
||||||
Layers,
|
import { HephaestusSection } from "@/components/landing/sections/hephaestus"
|
||||||
Star,
|
import { HeroSection } from "@/components/landing/sections/hero"
|
||||||
Check,
|
import { PrometheusAtlasSection } from "@/components/landing/sections/prometheus-atlas"
|
||||||
Zap,
|
import { ReviewsSection } from "@/components/landing/sections/reviews"
|
||||||
Search,
|
import { SisyphusSection } from "@/components/landing/sections/sisyphus"
|
||||||
Code2,
|
import { SubAgentsSection } from "@/components/landing/sections/sub-agents"
|
||||||
Brain,
|
import { TeamModeSection } from "@/components/landing/sections/team-mode"
|
||||||
Eye,
|
import { UltraworkSection } from "@/components/landing/sections/ultrawork"
|
||||||
MessageSquare,
|
|
||||||
Shield,
|
|
||||||
Lightbulb,
|
|
||||||
Route,
|
|
||||||
HardDrive,
|
|
||||||
ArrowRight,
|
|
||||||
Target,
|
|
||||||
Users,
|
|
||||||
Network,
|
|
||||||
Terminal,
|
|
||||||
Wrench,
|
|
||||||
Sparkles,
|
|
||||||
Sword,
|
|
||||||
} from "lucide-react"
|
|
||||||
import { HeroStats } from "@/components/landing/hero-stats"
|
|
||||||
import { InstallCommand } from "@/components/landing/install-command"
|
|
||||||
import { TerminalTypewriter } from "@/components/landing/motion-wrappers"
|
|
||||||
import { Badge } from "@/components/ui/badge"
|
|
||||||
import { Button } from "@/components/ui/button"
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
|
||||||
import { Link } from "@/i18n/routing"
|
|
||||||
import { formatStats, getStats } from "@/lib/stats"
|
|
||||||
|
|
||||||
const FALLBACK_STATS = {
|
|
||||||
stars: "40k+",
|
|
||||||
totalDownloads: "1M+",
|
|
||||||
monthlyDownloads: "580k+",
|
|
||||||
weeklyDownloads: "90k+",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const landingMetadata: Metadata = {
|
export const landingMetadata: Metadata = {
|
||||||
title: "Oh My OpenAgent — The Best Agent Harness",
|
title: "Oh My OpenAgent — The Best Agent Harness",
|
||||||
@@ -47,786 +18,19 @@ export const landingMetadata: Metadata = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function LandingPage(): Promise<JSX.Element> {
|
export async function LandingPage(): Promise<JSX.Element> {
|
||||||
const t = await getTranslations("landing")
|
|
||||||
|
|
||||||
let formattedStats = FALLBACK_STATS
|
|
||||||
try {
|
|
||||||
const stats = await getStats()
|
|
||||||
formattedStats = formatStats(stats)
|
|
||||||
} catch {
|
|
||||||
formattedStats = FALLBACK_STATS
|
|
||||||
}
|
|
||||||
|
|
||||||
const subAgentKeys = ["oracle", "librarian", "explore", "metis", "momus"] as const
|
|
||||||
type SubAgentKey = (typeof subAgentKeys)[number]
|
|
||||||
|
|
||||||
const agentStyles: Record<
|
|
||||||
SubAgentKey,
|
|
||||||
{ color: string; border: string; bg: string; icon: typeof Brain }
|
|
||||||
> = {
|
|
||||||
oracle: {
|
|
||||||
color: "text-purple-400",
|
|
||||||
border: "border-zinc-800",
|
|
||||||
bg: "bg-purple-400/5",
|
|
||||||
icon: Eye,
|
|
||||||
},
|
|
||||||
librarian: {
|
|
||||||
color: "text-green-400",
|
|
||||||
border: "border-zinc-800",
|
|
||||||
bg: "bg-green-400/5",
|
|
||||||
icon: Search,
|
|
||||||
},
|
|
||||||
explore: {
|
|
||||||
color: "text-blue-400",
|
|
||||||
border: "border-zinc-800",
|
|
||||||
bg: "bg-blue-400/5",
|
|
||||||
icon: Code2,
|
|
||||||
},
|
|
||||||
metis: {
|
|
||||||
color: "text-pink-400",
|
|
||||||
border: "border-zinc-800",
|
|
||||||
bg: "bg-pink-400/5",
|
|
||||||
icon: MessageSquare,
|
|
||||||
},
|
|
||||||
momus: { color: "text-red-400", border: "border-zinc-800", bg: "bg-red-400/5", icon: Check },
|
|
||||||
}
|
|
||||||
|
|
||||||
const reviewKeys = ["review1", "review2", "review3", "review4", "review5", "review6"] as const
|
|
||||||
|
|
||||||
const principleKeys = [
|
|
||||||
"specialization",
|
|
||||||
"trustVerify",
|
|
||||||
"wisdom",
|
|
||||||
"modelOptimization",
|
|
||||||
"categories",
|
|
||||||
"continuity",
|
|
||||||
] as const
|
|
||||||
type PrincipleKey = (typeof principleKeys)[number]
|
|
||||||
|
|
||||||
const principleIcons: Record<PrincipleKey, typeof Brain> = {
|
|
||||||
specialization: Target,
|
|
||||||
trustVerify: Shield,
|
|
||||||
wisdom: Lightbulb,
|
|
||||||
modelOptimization: Zap,
|
|
||||||
categories: Route,
|
|
||||||
continuity: HardDrive,
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-h-screen flex-col overflow-x-hidden">
|
<div className="flex min-h-screen flex-col overflow-x-hidden">
|
||||||
<link rel="preload" as="image" href="/images/hero.webp" fetchPriority="low" />
|
<link rel="preload" as="image" href="/images/hero.webp" fetchPriority="low" />
|
||||||
<section className="relative flex min-h-[90vh] items-center justify-center overflow-hidden pt-16">
|
<HeroSection />
|
||||||
<div
|
<UltraworkSection />
|
||||||
aria-hidden="true"
|
<SisyphusSection />
|
||||||
className="hero-bg absolute inset-0 z-0 bg-cover bg-center"
|
<PrometheusAtlasSection />
|
||||||
style={{ backgroundImage: "url(/images/hero.webp)" }}
|
<HephaestusSection />
|
||||||
/>
|
<TeamModeSection />
|
||||||
<div className="absolute inset-0 z-0 bg-gradient-to-b from-black/80 via-black/90 to-[#0a0a0a]" />
|
<SubAgentsSection />
|
||||||
|
<ArchitectureSection />
|
||||||
<div className="relative z-10 container mx-auto flex flex-col items-center gap-8 px-4 text-center md:px-6">
|
<ReviewsSection />
|
||||||
<div className="space-y-4">
|
<CtaSection />
|
||||||
<h1 className="text-5xl font-bold tracking-tighter text-white md:text-7xl">
|
|
||||||
{t("hero.title")}
|
|
||||||
<span className="text-cyan-400">{t("hero.titleHighlight")}</span>
|
|
||||||
</h1>
|
|
||||||
<p className="mx-auto max-w-3xl text-xl font-light text-zinc-400 md:text-2xl">
|
|
||||||
{t("hero.subtitle", {
|
|
||||||
stars: formattedStats.stars,
|
|
||||||
downloads: formattedStats.totalDownloads,
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<HeroStats
|
|
||||||
initialStats={{
|
|
||||||
stars: formattedStats.stars,
|
|
||||||
totalDownloads: formattedStats.totalDownloads,
|
|
||||||
monthlyDownloads: formattedStats.monthlyDownloads,
|
|
||||||
weeklyDownloads: formattedStats.weeklyDownloads,
|
|
||||||
}}
|
|
||||||
labels={{
|
|
||||||
githubStars: t("hero.githubStars", { count: "{count}" }),
|
|
||||||
specializedAgents: t("hero.specializedAgents", { count: "11" }),
|
|
||||||
totalDownloads: t("hero.totalDownloads", { count: "{count}" }),
|
|
||||||
monthlyDownloads: t("hero.monthlyDownloads", { count: "{count}" }),
|
|
||||||
lifecycleHooks: t("hero.lifecycleHooks", { count: "54+" }),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="w-full max-w-md">
|
|
||||||
<InstallCommand command={t("hero.installCommand")} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-4 sm:flex-row">
|
|
||||||
<Link href="https://github.com/code-yeongyu/oh-my-openagent" target="_blank">
|
|
||||||
<Button
|
|
||||||
size="lg"
|
|
||||||
className="h-12 bg-cyan-500 px-8 text-lg font-bold text-black shadow-sm hover:bg-cyan-600"
|
|
||||||
>
|
|
||||||
{t("hero.getStarted")}
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
<Link href="https://github.com/code-yeongyu/oh-my-openagent" target="_blank">
|
|
||||||
<Button
|
|
||||||
size="lg"
|
|
||||||
variant="outline"
|
|
||||||
className="h-12 border-zinc-700 px-8 text-lg text-white hover:bg-zinc-800"
|
|
||||||
>
|
|
||||||
<GithubIcon className="mr-2 h-5 w-5" />
|
|
||||||
{t("hero.viewOnGitHub")}
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="features" className="overflow-hidden border-t border-white/5 bg-[#0a0a0a] py-24">
|
|
||||||
<div className="container mx-auto px-4 md:px-6">
|
|
||||||
<div className="flex flex-col items-center gap-16 lg:flex-row">
|
|
||||||
<div className="flex-1 space-y-8">
|
|
||||||
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-4 py-1.5 text-cyan-400">
|
|
||||||
{t("ulw.badge")}
|
|
||||||
</Badge>
|
|
||||||
<h2 className="bg-gradient-to-r from-cyan-400 to-purple-600 bg-clip-text text-4xl font-black tracking-tighter text-transparent md:text-5xl">
|
|
||||||
{t("ulw.title")}
|
|
||||||
</h2>
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h3 className="text-3xl font-bold text-white">{t("ulw.headline")}</h3>
|
|
||||||
<p className="text-xl leading-relaxed text-zinc-400">{t("ulw.description")}</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-wrap gap-3">
|
|
||||||
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-4 py-2 text-sm text-cyan-400">
|
|
||||||
{t("ulw.autoPlanning")}
|
|
||||||
</Badge>
|
|
||||||
<Badge className="border-purple-500/20 bg-purple-500/10 px-4 py-2 text-sm text-purple-400">
|
|
||||||
{t("ulw.deepResearch")}
|
|
||||||
</Badge>
|
|
||||||
<Badge className="border-green-500/20 bg-green-500/10 px-4 py-2 text-sm text-green-400">
|
|
||||||
{t("ulw.selfCorrection")}
|
|
||||||
</Badge>
|
|
||||||
<Badge className="border-amber-500/20 bg-amber-500/10 px-4 py-2 text-sm text-amber-400">
|
|
||||||
{t("ulw.parallelAgents")}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
<p className="text-lg text-zinc-400/90 italic">{t("ulw.tagline")}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="w-full max-w-xl flex-1">
|
|
||||||
<div className="overflow-hidden rounded-xl border border-zinc-800 bg-black shadow-xl">
|
|
||||||
<div className="flex items-center gap-2 border-b border-zinc-800 bg-zinc-900/50 px-4 py-3">
|
|
||||||
<div className="h-3 w-3 rounded-full border border-red-500/50 bg-red-500/20" />
|
|
||||||
<div className="h-3 w-3 rounded-full border border-yellow-500/50 bg-yellow-500/20" />
|
|
||||||
<div className="h-3 w-3 rounded-full border border-green-500/50 bg-green-500/20" />
|
|
||||||
<div className="ml-2 font-mono text-xs text-zinc-400">
|
|
||||||
{t("ulw.terminalTitle")}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="space-y-4 overflow-x-auto p-6 font-mono text-sm">
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<span className="text-green-500">➜</span>
|
|
||||||
<span className="text-cyan-500">~</span>
|
|
||||||
<TerminalTypewriter text={t("ulw.terminalInput")} />
|
|
||||||
</div>
|
|
||||||
<div className="space-y-2 border-l-2 border-zinc-800 pl-4">
|
|
||||||
<div className="text-cyan-400">{t("ulw.steps.scanning")}</div>
|
|
||||||
<div className="text-zinc-400">{t("ulw.steps.context")}</div>
|
|
||||||
<div className="text-purple-400">{t("ulw.steps.planning")}</div>
|
|
||||||
<div className="text-amber-400">{t("ulw.steps.delegating")}</div>
|
|
||||||
<div className="text-blue-400">{t("ulw.steps.verifying")}</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2 pt-4">
|
|
||||||
<span className="text-green-500">✓</span>
|
|
||||||
<span className="font-bold text-green-400">{t("ulw.steps.complete")}</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<span className="text-green-500">➜</span>
|
|
||||||
<span className="text-cyan-500">~</span>
|
|
||||||
<span className="animate-pulse text-white">_</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="agents" className="relative overflow-hidden bg-black py-24">
|
|
||||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,_var(--tw-gradient-stops))] from-cyan-900/20 via-black to-black opacity-50" />
|
|
||||||
<div className="relative z-10 container mx-auto px-4 md:px-6">
|
|
||||||
<div className="mx-auto max-w-4xl">
|
|
||||||
<div className="mb-6 flex items-center gap-3">
|
|
||||||
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-4 py-1.5 text-cyan-400">
|
|
||||||
{t("sisyphus.badge")}
|
|
||||||
</Badge>
|
|
||||||
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
|
||||||
{t("sisyphus.model")}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 className="mb-4 text-4xl font-bold text-white md:text-5xl">
|
|
||||||
<span className="text-cyan-400">{t("sisyphus.title")}</span>
|
|
||||||
</h2>
|
|
||||||
<h3 className="mb-6 text-2xl font-bold text-zinc-300 md:text-3xl">
|
|
||||||
{t("sisyphus.headline")}
|
|
||||||
</h3>
|
|
||||||
<p className="mb-12 max-w-3xl text-xl leading-relaxed text-zinc-400">
|
|
||||||
{t("sisyphus.description")}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="mb-12 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
|
|
||||||
{(["intent", "explore", "delegate", "verify"] as const).map((phase, i) => (
|
|
||||||
<div key={phase}>
|
|
||||||
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<div className="mb-1 font-mono text-xs text-cyan-400">PHASE {i + 1}</div>
|
|
||||||
<CardTitle className="text-lg text-white">
|
|
||||||
{t(`sisyphus.phases.${phase}.title`)}
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<p className="text-sm text-zinc-400">
|
|
||||||
{t(`sisyphus.phases.${phase}.description`)}
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div className="rounded-xl border border-cyan-400/20 bg-cyan-400/5 p-6 md:p-8">
|
|
||||||
<div className="flex items-start gap-4">
|
|
||||||
<div className="rounded-lg bg-cyan-400/10 p-3">
|
|
||||||
<HardDrive className="h-6 w-6 text-cyan-400" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4 className="mb-2 text-xl font-bold text-cyan-400">
|
|
||||||
{t("sisyphus.boulderTitle")}
|
|
||||||
</h4>
|
|
||||||
<p className="leading-relaxed text-zinc-300">
|
|
||||||
{t("sisyphus.boulderDescription")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="border-y border-white/5 bg-[#0a0a0a] py-24">
|
|
||||||
<div className="container mx-auto px-4 md:px-6">
|
|
||||||
<div className="mb-16 text-center">
|
|
||||||
<Badge className="mb-6 border-amber-500/20 bg-amber-500/10 px-4 py-1.5 text-amber-400">
|
|
||||||
{t("prometheusAtlas.badge")}
|
|
||||||
</Badge>
|
|
||||||
<h2 className="mb-4 text-4xl font-bold text-white md:text-5xl">
|
|
||||||
{t("prometheusAtlas.title")}
|
|
||||||
</h2>
|
|
||||||
<p className="mx-auto max-w-2xl text-xl text-zinc-400">
|
|
||||||
{t("prometheusAtlas.headline")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-12 grid grid-cols-1 gap-8 lg:grid-cols-2">
|
|
||||||
<div>
|
|
||||||
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="rounded-lg bg-amber-400/10 p-2">
|
|
||||||
<Brain className="h-6 w-6 text-amber-400" />
|
|
||||||
</div>
|
|
||||||
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
|
||||||
{t("prometheusAtlas.prometheus.model")}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
<CardTitle className="mt-4 text-2xl text-amber-400">
|
|
||||||
{t("prometheusAtlas.prometheus.name")}
|
|
||||||
</CardTitle>
|
|
||||||
<CardDescription className="font-medium text-zinc-400">
|
|
||||||
{t("prometheusAtlas.prometheus.role")}
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="space-y-4">
|
|
||||||
<p className="leading-relaxed text-zinc-300">
|
|
||||||
{t("prometheusAtlas.prometheus.description")}
|
|
||||||
</p>
|
|
||||||
<ul className="space-y-2">
|
|
||||||
{([0, 1, 2, 3] as const).map((i) => (
|
|
||||||
<li key={i} className="flex items-center gap-2 text-sm text-zinc-400">
|
|
||||||
<ArrowRight className="h-3 w-3 shrink-0 text-amber-400" />
|
|
||||||
{t(`prometheusAtlas.prometheus.features.${i}`)}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="rounded-lg bg-indigo-400/10 p-2">
|
|
||||||
<Layers className="h-6 w-6 text-indigo-400" />
|
|
||||||
</div>
|
|
||||||
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
|
||||||
{t("prometheusAtlas.atlas.model")}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
<CardTitle className="mt-4 text-2xl text-indigo-400">
|
|
||||||
{t("prometheusAtlas.atlas.name")}
|
|
||||||
</CardTitle>
|
|
||||||
<CardDescription className="font-medium text-zinc-400">
|
|
||||||
{t("prometheusAtlas.atlas.role")}
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="space-y-4">
|
|
||||||
<p className="leading-relaxed text-zinc-300">
|
|
||||||
{t("prometheusAtlas.atlas.description")}
|
|
||||||
</p>
|
|
||||||
<ul className="space-y-2">
|
|
||||||
{([0, 1, 2, 3] as const).map((i) => (
|
|
||||||
<li key={i} className="flex items-center gap-2 text-sm text-zinc-400">
|
|
||||||
<ArrowRight className="h-3 w-3 shrink-0 text-indigo-400" />
|
|
||||||
{t(`prometheusAtlas.atlas.features.${i}`)}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<div className="overflow-x-auto rounded-xl border border-zinc-800 bg-zinc-900/20 p-6 md:p-8">
|
|
||||||
<div className="flex min-w-[600px] flex-col items-start justify-between gap-4 md:min-w-0 md:flex-row md:items-center md:gap-0">
|
|
||||||
{([1, 2, 3, 4, 5] as const).map((step, i) => (
|
|
||||||
<div key={step} className="flex flex-1 items-center gap-4">
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-full border border-zinc-700 bg-zinc-800 font-mono text-xs text-zinc-400">
|
|
||||||
{step}
|
|
||||||
</div>
|
|
||||||
<span className="text-sm whitespace-nowrap text-zinc-300">
|
|
||||||
{t(`prometheusAtlas.workflow.step${step}`)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{i < 4 && (
|
|
||||||
<ArrowRight className="ml-auto hidden h-4 w-4 shrink-0 text-zinc-600 md:block" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<p className="mt-6 border-t border-zinc-800 pt-6 text-center text-zinc-400 italic">
|
|
||||||
{t("prometheusAtlas.whyItWorks")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="relative overflow-hidden bg-black py-24">
|
|
||||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_bottom,_var(--tw-gradient-stops))] from-orange-900/10 via-black to-black opacity-70" />
|
|
||||||
<div className="relative z-10 container mx-auto px-4 md:px-6">
|
|
||||||
<div className="mx-auto max-w-4xl">
|
|
||||||
<div className="mb-6 flex items-center gap-3">
|
|
||||||
<Badge className="border-orange-500/20 bg-orange-500/10 px-4 py-1.5 text-orange-400">
|
|
||||||
{t("hephaestus.badge")}
|
|
||||||
</Badge>
|
|
||||||
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
|
||||||
{t("hephaestus.model")}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 className="mb-4 text-4xl font-bold md:text-5xl">
|
|
||||||
<span className="text-orange-400">{t("hephaestus.title")}</span>
|
|
||||||
</h2>
|
|
||||||
<h3 className="mb-6 text-2xl font-bold text-zinc-300 md:text-3xl">
|
|
||||||
{t("hephaestus.headline")}
|
|
||||||
</h3>
|
|
||||||
<p className="mb-12 max-w-3xl text-xl leading-relaxed text-zinc-400">
|
|
||||||
{t("hephaestus.description")}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="mb-8 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-5">
|
|
||||||
{(["explore", "plan", "decide", "execute", "verify"] as const).map((step, i) => (
|
|
||||||
<div key={step}>
|
|
||||||
<div className="rounded-lg border border-orange-400/20 bg-orange-400/5 p-4 text-center">
|
|
||||||
<div className="mb-2 font-mono text-xs text-orange-400">0{i + 1}</div>
|
|
||||||
<p className="text-sm leading-snug break-keep text-zinc-300">
|
|
||||||
{t(`hephaestus.loop.${step}`)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p className="text-center text-lg text-zinc-400/90 italic">{t("hephaestus.tagline")}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section
|
|
||||||
id="team-mode"
|
|
||||||
className="relative overflow-hidden border-t border-white/5 bg-[#0a0a0a] py-24"
|
|
||||||
>
|
|
||||||
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-fuchsia-900/20 via-black to-black opacity-70" />
|
|
||||||
<div className="relative z-10 container mx-auto px-4 md:px-6">
|
|
||||||
<div className="mx-auto max-w-5xl">
|
|
||||||
<div className="mb-6 flex flex-wrap items-center gap-3">
|
|
||||||
<Badge className="border-fuchsia-500/30 bg-fuchsia-500/10 px-4 py-1.5 font-mono text-fuchsia-300">
|
|
||||||
{t("teamMode.badge")}
|
|
||||||
</Badge>
|
|
||||||
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
|
||||||
opt-in
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 className="mb-4 text-4xl font-bold tracking-tight md:text-5xl">
|
|
||||||
<span className="bg-gradient-to-r from-fuchsia-400 via-purple-400 to-cyan-400 bg-clip-text text-transparent">
|
|
||||||
{t("teamMode.title")}
|
|
||||||
</span>
|
|
||||||
</h2>
|
|
||||||
<h3 className="mb-6 text-2xl font-bold text-zinc-200 md:text-3xl">
|
|
||||||
{t("teamMode.headline")}
|
|
||||||
</h3>
|
|
||||||
<p className="mb-12 max-w-3xl text-xl leading-relaxed text-zinc-400">
|
|
||||||
{t("teamMode.description")}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="mb-16 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
||||||
{(
|
|
||||||
[
|
|
||||||
{ key: "lead", icon: Network },
|
|
||||||
{ key: "parallel", icon: Users },
|
|
||||||
{ key: "tmux", icon: Terminal },
|
|
||||||
{ key: "tools", icon: Wrench },
|
|
||||||
] as const
|
|
||||||
).map(({ key, icon: Icon }) => (
|
|
||||||
<div key={key}>
|
|
||||||
<Card className="h-full border-zinc-800 bg-zinc-900/30 transition-colors hover:border-fuchsia-500/30">
|
|
||||||
<CardHeader className="pb-3">
|
|
||||||
<div className="w-fit rounded-lg bg-fuchsia-500/10 p-2 text-fuchsia-300">
|
|
||||||
<Icon className="h-5 w-5" />
|
|
||||||
</div>
|
|
||||||
<CardTitle className="mt-3 text-lg text-fuchsia-200">
|
|
||||||
{t(`teamMode.features.${key}.title`)}
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<p className="text-sm leading-relaxed text-zinc-400">
|
|
||||||
{t(`teamMode.features.${key}.description`)}
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-10 flex items-center gap-3">
|
|
||||||
<Sparkles className="h-4 w-4 text-fuchsia-400" />
|
|
||||||
<span className="font-mono text-sm tracking-widest text-fuchsia-300/80 uppercase">
|
|
||||||
{t("teamMode.poweredBy")}
|
|
||||||
</span>
|
|
||||||
<div className="h-px flex-1 bg-gradient-to-r from-fuchsia-500/30 to-transparent" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-12 grid grid-cols-1 gap-6 lg:grid-cols-2">
|
|
||||||
{(
|
|
||||||
[
|
|
||||||
{ key: "hyperplan", icon: Sword, accent: "purple" as const },
|
|
||||||
{ key: "securityResearch", icon: Shield, accent: "rose" as const },
|
|
||||||
] as const
|
|
||||||
).map(({ key, icon: Icon, accent }) => (
|
|
||||||
<div key={key}>
|
|
||||||
<Card
|
|
||||||
className={`h-full border-zinc-800 bg-zinc-900/30 ${
|
|
||||||
accent === "purple"
|
|
||||||
? "hover:border-purple-500/40"
|
|
||||||
: "hover:border-rose-500/40"
|
|
||||||
} transition-colors`}
|
|
||||||
>
|
|
||||||
<CardHeader>
|
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<div
|
|
||||||
className={`rounded-lg p-2 ${
|
|
||||||
accent === "purple"
|
|
||||||
? "bg-purple-500/10 text-purple-300"
|
|
||||||
: "bg-rose-500/10 text-rose-300"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<Icon className="h-5 w-5" />
|
|
||||||
</div>
|
|
||||||
<CardTitle
|
|
||||||
className={`font-mono text-lg ${
|
|
||||||
accent === "purple" ? "text-purple-300" : "text-rose-300"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{t(`teamMode.skills.${key}.name`)}
|
|
||||||
</CardTitle>
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<p className="leading-relaxed text-zinc-300">
|
|
||||||
{t(`teamMode.skills.${key}.description`)}
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col items-start gap-4 rounded-xl border border-zinc-800 bg-black/40 p-6 sm:flex-row sm:items-center sm:justify-between">
|
|
||||||
<code className="font-mono text-sm break-all text-fuchsia-200/90">
|
|
||||||
{t("teamMode.optIn")}
|
|
||||||
</code>
|
|
||||||
<p className="text-sm text-zinc-400 italic sm:text-right">{t("teamMode.tagline")}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="border-t border-white/5 bg-[#0a0a0a] py-24">
|
|
||||||
<div className="container mx-auto px-4 md:px-6">
|
|
||||||
<div className="mb-16 text-center">
|
|
||||||
<h2 className="mb-4 text-4xl font-bold text-white md:text-5xl">{t("agents.title")}</h2>
|
|
||||||
<p className="text-xl text-zinc-400">{t("agents.subtitle")}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-5">
|
|
||||||
{subAgentKeys.map((key) => {
|
|
||||||
const style = agentStyles[key]
|
|
||||||
const Icon = style.icon
|
|
||||||
return (
|
|
||||||
<div key={key}>
|
|
||||||
<Card
|
|
||||||
className={`h-full border-zinc-800 bg-zinc-900/30 ${style.border} ${style.bg}`}
|
|
||||||
>
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<div className="flex items-start justify-between">
|
|
||||||
<div className={`rounded-lg bg-black/50 p-2 ${style.color}`}>
|
|
||||||
<Icon className="h-5 w-5" />
|
|
||||||
</div>
|
|
||||||
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
|
||||||
{t(`agents.${key}.model`)}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
<CardTitle className={`mt-3 text-lg ${style.color}`}>
|
|
||||||
{t(`agents.${key}.name`)}
|
|
||||||
</CardTitle>
|
|
||||||
<CardDescription className="text-sm font-medium text-zinc-400">
|
|
||||||
{t(`agents.${key}.role`)}
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<p className="text-sm leading-relaxed text-zinc-300">
|
|
||||||
{t(`agents.${key}.description`)}
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
|
|
||||||
<div className="col-span-1 mt-4 md:col-span-2 lg:col-span-5">
|
|
||||||
<Card className="h-full overflow-hidden border-zinc-800 bg-zinc-900/30">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="mb-2 flex items-center gap-3">
|
|
||||||
<Badge className="border-teal-500/20 bg-teal-500/10 px-3 py-1 text-teal-400">
|
|
||||||
{t("agents.dynamicSystem.role")}
|
|
||||||
</Badge>
|
|
||||||
</div>
|
|
||||||
<CardTitle className="text-2xl text-teal-400">
|
|
||||||
{t("agents.dynamicSystem.name")}
|
|
||||||
</CardTitle>
|
|
||||||
<CardDescription className="max-w-3xl text-base text-zinc-400">
|
|
||||||
{t("agents.dynamicSystem.description")}
|
|
||||||
</CardDescription>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<div className="mt-4 grid grid-cols-1 gap-8 md:grid-cols-2">
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h3 className="text-sm font-bold tracking-wider text-zinc-300 uppercase">
|
|
||||||
Category Routing
|
|
||||||
</h3>
|
|
||||||
<div className="space-y-2">
|
|
||||||
{[
|
|
||||||
{ cat: "visual-engineering", model: "Gemini 3.1 Pro" },
|
|
||||||
{ cat: "ultrabrain", model: "GPT 5.5 xHigh" },
|
|
||||||
{ cat: "artistry", model: "Gemini 3.1 Pro" },
|
|
||||||
{ cat: "quick", model: "GPT 5.4 Mini" },
|
|
||||||
{ cat: "deep", model: "GPT 5.5 Medium" },
|
|
||||||
{ cat: "writing", model: "Kimi K2.5" },
|
|
||||||
{ cat: "git", model: "Claude Haiku 4.5" },
|
|
||||||
].map((item) => (
|
|
||||||
<div
|
|
||||||
key={item.cat}
|
|
||||||
className="flex items-center justify-between rounded border border-zinc-800/50 bg-black/40 p-2"
|
|
||||||
>
|
|
||||||
<span className="font-mono text-sm text-teal-400">{item.cat}</span>
|
|
||||||
<ArrowRight className="h-3 w-3 text-zinc-600" />
|
|
||||||
<span className="text-sm text-zinc-300">{item.model}</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-4">
|
|
||||||
<h3 className="text-sm font-bold tracking-wider text-zinc-300 uppercase">
|
|
||||||
Skill Injection
|
|
||||||
</h3>
|
|
||||||
<div className="grid grid-cols-2 gap-3">
|
|
||||||
{["playwright", "git-master", "frontend-ui-ux", "team-mode"].map(
|
|
||||||
(skill) => (
|
|
||||||
<div
|
|
||||||
key={skill}
|
|
||||||
className="flex items-center gap-2 rounded border border-zinc-700/50 bg-zinc-800/30 p-3"
|
|
||||||
>
|
|
||||||
<Zap className="h-4 w-4 text-yellow-400" />
|
|
||||||
<span className="font-mono text-sm text-zinc-200">{skill}</span>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="mt-6 rounded-lg border border-teal-500/10 bg-teal-500/5 p-4">
|
|
||||||
<p className="text-sm text-teal-300 italic">
|
|
||||||
"The right model + right expertise, every time."
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="bg-black py-24">
|
|
||||||
<div className="container mx-auto px-4 md:px-6">
|
|
||||||
<div className="mb-16 text-center">
|
|
||||||
<h2 className="mb-4 text-4xl font-bold text-white md:text-5xl">
|
|
||||||
{t("architecture.title")}
|
|
||||||
</h2>
|
|
||||||
<p className="text-xl text-zinc-400">{t("architecture.subtitle")}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mx-auto grid max-w-5xl grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
||||||
{principleKeys.map((key) => {
|
|
||||||
const Icon = principleIcons[key]
|
|
||||||
return (
|
|
||||||
<div key={key}>
|
|
||||||
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="w-fit rounded-lg bg-zinc-800 p-2">
|
|
||||||
<Icon className="h-5 w-5 text-zinc-300" />
|
|
||||||
</div>
|
|
||||||
<CardTitle className="mt-3 text-lg text-white">
|
|
||||||
{t(`architecture.principles.${key}.title`)}
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<p className="text-sm leading-relaxed text-zinc-400">
|
|
||||||
{t(`architecture.principles.${key}.description`)}
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="border-t border-white/5 bg-[#0a0a0a] py-24">
|
|
||||||
<div className="container mx-auto px-4 md:px-6">
|
|
||||||
<div>
|
|
||||||
<h2 className="mb-16 text-center text-4xl font-bold text-white md:text-5xl">
|
|
||||||
{t("reviews.title")}
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
||||||
{reviewKeys.map((key) => (
|
|
||||||
<div key={key}>
|
|
||||||
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
|
||||||
<CardContent className="pt-6">
|
|
||||||
<div className="mb-4 text-cyan-500">
|
|
||||||
<Star className="h-5 w-5 fill-cyan-500" />
|
|
||||||
</div>
|
|
||||||
<p className="mb-6 leading-relaxed text-zinc-300 italic">
|
|
||||||
“{t(`reviews.${key}.text`)}”
|
|
||||||
</p>
|
|
||||||
<p className="text-sm font-medium text-zinc-400">
|
|
||||||
— {t(`reviews.${key}.author`)}
|
|
||||||
</p>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className="bg-black py-24">
|
|
||||||
<div className="container mx-auto px-4 md:px-6">
|
|
||||||
<div>
|
|
||||||
<div className="relative overflow-hidden rounded-3xl border border-zinc-800 bg-zinc-900/30 p-8 text-center md:p-16">
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-cyan-500/10 via-purple-500/10 to-cyan-500/10 opacity-50" />
|
|
||||||
<div className="relative z-10 mx-auto max-w-3xl space-y-8">
|
|
||||||
<h2 className="text-4xl font-bold text-white md:text-5xl">{t("cta.title")}</h2>
|
|
||||||
<p className="text-lg text-zinc-400">{t("cta.subtitle")}</p>
|
|
||||||
<div className="flex justify-center">
|
|
||||||
<div className="inline-flex items-center gap-2 rounded-full border border-zinc-800 bg-black px-6 py-3 font-mono text-sm text-zinc-300">
|
|
||||||
<span className="text-cyan-500">$</span>
|
|
||||||
{t("cta.installCommand")}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col justify-center gap-4 sm:flex-row">
|
|
||||||
<Link href="https://github.com/code-yeongyu/oh-my-openagent" target="_blank">
|
|
||||||
<Button
|
|
||||||
size="lg"
|
|
||||||
className="h-12 bg-cyan-500 px-8 font-bold text-black hover:bg-cyan-600"
|
|
||||||
>
|
|
||||||
{t("cta.installNow")}
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
<Link href="/docs">
|
|
||||||
<Button
|
|
||||||
size="lg"
|
|
||||||
variant="outline"
|
|
||||||
className="h-12 border-zinc-700 px-8 text-white hover:bg-zinc-800"
|
|
||||||
>
|
|
||||||
{t("cta.readTheDocs")}
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function GithubIcon(props: SVGProps<SVGSVGElement>) {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
{...props}
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
role="img"
|
|
||||||
>
|
|
||||||
<title>GitHub</title>
|
|
||||||
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4" />
|
|
||||||
<path d="M9 18c-4.51 2-5-2-7-2" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import type { SVGProps, JSX } from "react"
|
||||||
|
|
||||||
|
export function GithubIcon(props: SVGProps<SVGSVGElement>): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
{...props}
|
||||||
|
aria-hidden={props["aria-hidden"] ?? true}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
role="img"
|
||||||
|
>
|
||||||
|
<title>GitHub</title>
|
||||||
|
<path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4" />
|
||||||
|
<path d="M9 18c-4.51 2-5-2-7-2" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import type { Brain } from "lucide-react"
|
||||||
|
import {
|
||||||
|
Check,
|
||||||
|
Eye,
|
||||||
|
Search,
|
||||||
|
Code2,
|
||||||
|
MessageSquare,
|
||||||
|
Target,
|
||||||
|
Shield,
|
||||||
|
Lightbulb,
|
||||||
|
Zap,
|
||||||
|
Route,
|
||||||
|
HardDrive,
|
||||||
|
} from "lucide-react"
|
||||||
|
|
||||||
|
export const SUB_AGENT_KEYS = ["oracle", "librarian", "explore", "metis", "momus"] as const
|
||||||
|
export type SubAgentKey = (typeof SUB_AGENT_KEYS)[number]
|
||||||
|
|
||||||
|
type AgentStyle = {
|
||||||
|
readonly color: string
|
||||||
|
readonly border: string
|
||||||
|
readonly bg: string
|
||||||
|
readonly icon: typeof Brain
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consolidated: single secondary accent (violet) for all sub-agents.
|
||||||
|
// The visual differentiation comes from the icon, not a rainbow of colors.
|
||||||
|
export const AGENT_STYLES: Readonly<Record<SubAgentKey, AgentStyle>> = {
|
||||||
|
oracle: { color: "text-violet-300", border: "border-zinc-800", bg: "bg-violet-400/5", icon: Eye },
|
||||||
|
librarian: {
|
||||||
|
color: "text-violet-300",
|
||||||
|
border: "border-zinc-800",
|
||||||
|
bg: "bg-violet-400/5",
|
||||||
|
icon: Search,
|
||||||
|
},
|
||||||
|
explore: {
|
||||||
|
color: "text-violet-300",
|
||||||
|
border: "border-zinc-800",
|
||||||
|
bg: "bg-violet-400/5",
|
||||||
|
icon: Code2,
|
||||||
|
},
|
||||||
|
metis: {
|
||||||
|
color: "text-violet-300",
|
||||||
|
border: "border-zinc-800",
|
||||||
|
bg: "bg-violet-400/5",
|
||||||
|
icon: MessageSquare,
|
||||||
|
},
|
||||||
|
momus: {
|
||||||
|
color: "text-violet-300",
|
||||||
|
border: "border-zinc-800",
|
||||||
|
bg: "bg-violet-400/5",
|
||||||
|
icon: Check,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PRINCIPLE_KEYS = [
|
||||||
|
"specialization",
|
||||||
|
"trustVerify",
|
||||||
|
"wisdom",
|
||||||
|
"modelOptimization",
|
||||||
|
"categories",
|
||||||
|
"continuity",
|
||||||
|
] as const
|
||||||
|
export type PrincipleKey = (typeof PRINCIPLE_KEYS)[number]
|
||||||
|
|
||||||
|
export const PRINCIPLE_ICONS: Readonly<Record<PrincipleKey, typeof Brain>> = {
|
||||||
|
specialization: Target,
|
||||||
|
trustVerify: Shield,
|
||||||
|
wisdom: Lightbulb,
|
||||||
|
modelOptimization: Zap,
|
||||||
|
categories: Route,
|
||||||
|
continuity: HardDrive,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const REVIEW_KEYS = [
|
||||||
|
"review1",
|
||||||
|
"review2",
|
||||||
|
"review3",
|
||||||
|
"review4",
|
||||||
|
"review5",
|
||||||
|
"review6",
|
||||||
|
] as const
|
||||||
|
export type ReviewKey = (typeof REVIEW_KEYS)[number]
|
||||||
|
|
||||||
|
export const CATEGORY_ROUTING = [
|
||||||
|
{ cat: "visual-engineering", model: "Gemini 3.1 Pro" },
|
||||||
|
{ cat: "ultrabrain", model: "GPT 5.5 xHigh" },
|
||||||
|
{ cat: "artistry", model: "Gemini 3.1 Pro" },
|
||||||
|
{ cat: "quick", model: "GPT 5.4 Mini" },
|
||||||
|
{ cat: "deep", model: "GPT 5.5 Medium" },
|
||||||
|
{ cat: "writing", model: "Kimi K2.5" },
|
||||||
|
{ cat: "git", model: "Claude Haiku 4.5" },
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export const SKILL_INJECTIONS = ["playwright", "git-master", "frontend-ui-ux", "team-mode"] as const
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
|
import { PRINCIPLE_KEYS, PRINCIPLE_ICONS } from "@/components/landing/constants"
|
||||||
|
|
||||||
|
export async function ArchitectureSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="bg-black py-24" data-section="architecture">
|
||||||
|
<div className="reveal-on-enter container mx-auto px-4 md:px-6">
|
||||||
|
<div className="mb-16 text-center">
|
||||||
|
<h2 className="mb-4 text-4xl font-bold text-white md:text-5xl">
|
||||||
|
{t("architecture.title")}
|
||||||
|
</h2>
|
||||||
|
<p className="text-xl text-zinc-400">{t("architecture.subtitle")}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mx-auto grid max-w-5xl grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{PRINCIPLE_KEYS.map((key) => {
|
||||||
|
const Icon = PRINCIPLE_ICONS[key]
|
||||||
|
return (
|
||||||
|
<div key={key}>
|
||||||
|
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="w-fit rounded-lg bg-zinc-800 p-2">
|
||||||
|
<Icon className="h-5 w-5 text-zinc-300" />
|
||||||
|
</div>
|
||||||
|
<CardTitle className="mt-3 text-lg text-white">
|
||||||
|
{t(`architecture.principles.${key}.title`)}
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-sm leading-relaxed text-zinc-400">
|
||||||
|
{t(`architecture.principles.${key}.description`)}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Link } from "@/i18n/routing"
|
||||||
|
|
||||||
|
export async function CtaSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="bg-black py-24" data-section="cta">
|
||||||
|
<div className="reveal-on-enter container mx-auto px-4 md:px-6">
|
||||||
|
<div>
|
||||||
|
<div className="relative overflow-hidden rounded-3xl border border-zinc-800 bg-zinc-900/30 p-8 text-center md:p-16">
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,_rgba(0,212,255,0.08)_0%,_transparent_70%)]" />
|
||||||
|
<div className="relative z-10 mx-auto max-w-3xl space-y-8">
|
||||||
|
<h2 className="text-4xl font-bold text-white md:text-5xl">{t("cta.title")}</h2>
|
||||||
|
<p className="text-lg text-zinc-400">{t("cta.subtitle")}</p>
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<div className="inline-flex items-center gap-2 rounded-full border border-zinc-800 bg-black px-6 py-3 font-mono text-sm text-zinc-300">
|
||||||
|
<span className="text-cyan-500">$</span>
|
||||||
|
{t("cta.installCommand")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col justify-center gap-4 sm:flex-row">
|
||||||
|
<Link
|
||||||
|
href="https://github.com/code-yeongyu/oh-my-openagent"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
className="h-12 bg-cyan-500 px-8 font-bold text-black hover:bg-cyan-600"
|
||||||
|
>
|
||||||
|
{t("cta.installNow")}
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
<Link href="/docs">
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
variant="outline"
|
||||||
|
className="h-12 border-zinc-700 px-8 text-white hover:bg-zinc-800"
|
||||||
|
>
|
||||||
|
{t("cta.readTheDocs")}
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
|
||||||
|
export async function HephaestusSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="relative overflow-hidden bg-black py-24" data-section="hephaestus">
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_bottom,_var(--tw-gradient-stops))] from-cyan-900/10 via-black to-black opacity-70" />
|
||||||
|
<div className="reveal-on-enter relative z-10 container mx-auto px-4 md:px-6">
|
||||||
|
<div className="mx-auto max-w-4xl">
|
||||||
|
<div className="mb-6 flex items-center gap-3">
|
||||||
|
<Badge className="border-cyan-400/20 bg-cyan-400/5 px-4 py-1.5 text-cyan-400">
|
||||||
|
{t("hephaestus.badge")}
|
||||||
|
</Badge>
|
||||||
|
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
||||||
|
{t("hephaestus.model")}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="mb-4 text-4xl font-bold md:text-5xl">
|
||||||
|
<span className="text-cyan-400">{t("hephaestus.title")}</span>
|
||||||
|
</h2>
|
||||||
|
<h3 className="mb-6 text-2xl font-bold text-zinc-300 md:text-3xl">
|
||||||
|
{t("hephaestus.headline")}
|
||||||
|
</h3>
|
||||||
|
<p className="mb-12 max-w-3xl text-xl leading-relaxed text-zinc-400">
|
||||||
|
{t("hephaestus.description")}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mb-8 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-5">
|
||||||
|
{(["explore", "plan", "decide", "execute", "verify"] as const).map((step, i) => (
|
||||||
|
<div key={step}>
|
||||||
|
<div className="rounded-lg border border-cyan-400/20 bg-cyan-400/5 p-4 text-center">
|
||||||
|
<div className="mb-2 font-mono text-xs text-cyan-400">0{i + 1}</div>
|
||||||
|
<p className="text-sm leading-snug break-keep text-zinc-300">
|
||||||
|
{t(`hephaestus.loop.${step}`)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-center text-lg text-zinc-400/90 italic">{t("hephaestus.tagline")}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { getStats, formatStats } from "@/lib/stats"
|
||||||
|
import { HeroStats } from "@/components/landing/hero-stats"
|
||||||
|
import { InstallCommand } from "@/components/landing/install-command"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Link } from "@/i18n/routing"
|
||||||
|
import { GithubIcon } from "@/components/icons/github-icon"
|
||||||
|
|
||||||
|
const FALLBACK_STATS = {
|
||||||
|
stars: "40k+",
|
||||||
|
totalDownloads: "1M+",
|
||||||
|
monthlyDownloads: "580k+",
|
||||||
|
weeklyDownloads: "90k+",
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function HeroSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
let formattedStats = FALLBACK_STATS
|
||||||
|
try {
|
||||||
|
const stats = await getStats()
|
||||||
|
formattedStats = formatStats(stats)
|
||||||
|
} catch {
|
||||||
|
formattedStats = FALLBACK_STATS
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
data-section="hero"
|
||||||
|
className="relative flex min-h-[100dvh] items-center justify-center overflow-hidden pt-16"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
className="hero-bg absolute inset-0 z-0 bg-cover bg-center"
|
||||||
|
style={{ backgroundImage: "url(/images/hero.webp)" }}
|
||||||
|
/>
|
||||||
|
<div className="absolute inset-0 z-0 bg-gradient-to-b from-black/80 via-black/90 to-[#0a0a0a]" />
|
||||||
|
|
||||||
|
<div className="reveal-on-enter relative z-10 container mx-auto flex flex-col items-center gap-8 px-4 text-center md:px-6">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h1 className="text-5xl font-bold tracking-tighter text-white md:text-7xl">
|
||||||
|
{t("hero.title")}
|
||||||
|
<span className="text-cyan-400">{t("hero.titleHighlight")}</span>
|
||||||
|
</h1>
|
||||||
|
<p className="mx-auto max-w-3xl text-xl font-light text-zinc-400 md:text-2xl">
|
||||||
|
{t("hero.subtitle", {
|
||||||
|
stars: formattedStats.stars,
|
||||||
|
downloads: formattedStats.totalDownloads,
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<HeroStats
|
||||||
|
initialStats={{
|
||||||
|
stars: formattedStats.stars,
|
||||||
|
totalDownloads: formattedStats.totalDownloads,
|
||||||
|
monthlyDownloads: formattedStats.monthlyDownloads,
|
||||||
|
weeklyDownloads: formattedStats.weeklyDownloads,
|
||||||
|
}}
|
||||||
|
labels={{
|
||||||
|
githubStars: t("hero.githubStars", { count: "{count}" }),
|
||||||
|
specializedAgents: t("hero.specializedAgents", { count: "11" }),
|
||||||
|
totalDownloads: t("hero.totalDownloads", { count: "{count}" }),
|
||||||
|
monthlyDownloads: t("hero.monthlyDownloads", { count: "{count}" }),
|
||||||
|
lifecycleHooks: t("hero.lifecycleHooks", { count: "54+" }),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="w-full max-w-md">
|
||||||
|
<InstallCommand command={t("hero.installCommand")} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-4 sm:flex-row">
|
||||||
|
<Link href="/docs">
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
className="h-12 bg-cyan-500 px-8 text-lg font-bold text-black shadow-sm hover:bg-cyan-600"
|
||||||
|
>
|
||||||
|
{t("hero.getStarted")}
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="https://github.com/code-yeongyu/oh-my-openagent"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
variant="outline"
|
||||||
|
className="h-12 border-zinc-700 px-8 text-lg text-white hover:bg-zinc-800"
|
||||||
|
>
|
||||||
|
<GithubIcon className="mr-2 h-5 w-5" />
|
||||||
|
{t("hero.viewOnGitHub")}
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { Brain, Layers, ArrowRight } from "lucide-react"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
|
|
||||||
|
export async function PrometheusAtlasSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="border-y border-white/5 bg-[#0a0a0a] py-24" data-section="prometheus-atlas">
|
||||||
|
<div className="reveal-on-enter container mx-auto px-4 md:px-6">
|
||||||
|
<div className="mb-16 text-center">
|
||||||
|
<Badge className="mb-6 border-violet-500/20 bg-violet-500/10 px-4 py-1.5 text-violet-400">
|
||||||
|
{t("prometheusAtlas.badge")}
|
||||||
|
</Badge>
|
||||||
|
<h2 className="mb-4 text-4xl font-bold text-white md:text-5xl">
|
||||||
|
{t("prometheusAtlas.title")}
|
||||||
|
</h2>
|
||||||
|
<p className="mx-auto max-w-2xl text-xl text-zinc-400">{t("prometheusAtlas.headline")}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-12 grid grid-cols-1 gap-8 lg:grid-cols-2">
|
||||||
|
<div>
|
||||||
|
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="rounded-lg bg-violet-400/10 p-2">
|
||||||
|
<Brain className="h-6 w-6 text-violet-400" />
|
||||||
|
</div>
|
||||||
|
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
||||||
|
{t("prometheusAtlas.prometheus.model")}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<CardTitle className="mt-4 text-2xl text-violet-400">
|
||||||
|
{t("prometheusAtlas.prometheus.name")}
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription className="font-medium text-zinc-400">
|
||||||
|
{t("prometheusAtlas.prometheus.role")}
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<p className="leading-relaxed text-zinc-300">
|
||||||
|
{t("prometheusAtlas.prometheus.description")}
|
||||||
|
</p>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{([0, 1, 2, 3] as const).map((i) => (
|
||||||
|
<li key={i} className="flex items-center gap-2 text-sm text-zinc-400">
|
||||||
|
<ArrowRight className="h-3 w-3 shrink-0 text-violet-400" />
|
||||||
|
{t(`prometheusAtlas.prometheus.features.${i}`)}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="rounded-lg bg-violet-400/10 p-2">
|
||||||
|
<Layers className="h-6 w-6 text-violet-400" />
|
||||||
|
</div>
|
||||||
|
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
||||||
|
{t("prometheusAtlas.atlas.model")}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<CardTitle className="mt-4 text-2xl text-violet-400">
|
||||||
|
{t("prometheusAtlas.atlas.name")}
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription className="font-medium text-zinc-400">
|
||||||
|
{t("prometheusAtlas.atlas.role")}
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="space-y-4">
|
||||||
|
<p className="leading-relaxed text-zinc-300">
|
||||||
|
{t("prometheusAtlas.atlas.description")}
|
||||||
|
</p>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{([0, 1, 2, 3] as const).map((i) => (
|
||||||
|
<li key={i} className="flex items-center gap-2 text-sm text-zinc-400">
|
||||||
|
<ArrowRight className="h-3 w-3 shrink-0 text-violet-400" />
|
||||||
|
{t(`prometheusAtlas.atlas.features.${i}`)}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="overflow-x-auto rounded-xl border border-zinc-800 bg-zinc-900/20 p-6 md:p-8">
|
||||||
|
<div className="flex min-w-[600px] flex-col items-start justify-between gap-4 md:min-w-0 md:flex-row md:items-center md:gap-0">
|
||||||
|
{([1, 2, 3, 4, 5] as const).map((step, i) => (
|
||||||
|
<div key={step} className="flex flex-1 items-center gap-4">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="flex h-8 w-8 items-center justify-center rounded-full border border-zinc-700 bg-zinc-800 font-mono text-xs text-zinc-400">
|
||||||
|
{step}
|
||||||
|
</div>
|
||||||
|
<span className="text-sm whitespace-nowrap text-zinc-300">
|
||||||
|
{t(`prometheusAtlas.workflow.step${step}`)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{i < 4 && (
|
||||||
|
<ArrowRight className="ml-auto hidden h-4 w-4 shrink-0 text-zinc-600 md:block" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<p className="mt-6 border-t border-zinc-800 pt-6 text-center text-zinc-400 italic">
|
||||||
|
{t("prometheusAtlas.whyItWorks")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { Card, CardContent } from "@/components/ui/card"
|
||||||
|
import { Star } from "lucide-react"
|
||||||
|
import { REVIEW_KEYS } from "@/components/landing/constants"
|
||||||
|
|
||||||
|
export async function ReviewsSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="border-t border-white/5 bg-[#0a0a0a] py-24" data-section="reviews">
|
||||||
|
<div className="reveal-on-enter container mx-auto px-4 md:px-6">
|
||||||
|
<div>
|
||||||
|
<h2 className="mb-16 text-center text-4xl font-bold text-white md:text-5xl">
|
||||||
|
{t("reviews.title")}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{REVIEW_KEYS.map((key) => (
|
||||||
|
<div key={key}>
|
||||||
|
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
||||||
|
<CardContent className="pt-6">
|
||||||
|
<div className="mb-4 text-cyan-500">
|
||||||
|
<Star className="h-5 w-5 fill-cyan-500" />
|
||||||
|
</div>
|
||||||
|
<p className="mb-6 leading-relaxed text-zinc-300 italic">
|
||||||
|
“{t(`reviews.${key}.text`)}”
|
||||||
|
</p>
|
||||||
|
<p className="text-sm font-medium text-zinc-400">
|
||||||
|
— {t(`reviews.${key}.author`)}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { HardDrive } from "lucide-react"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
|
|
||||||
|
export async function SisyphusSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
data-section="sisyphus"
|
||||||
|
id="agents"
|
||||||
|
className="relative overflow-hidden bg-black py-24"
|
||||||
|
>
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,_var(--tw-gradient-stops))] from-cyan-900/20 via-black to-black opacity-50" />
|
||||||
|
<div className="reveal-on-enter relative z-10 container mx-auto px-4 md:px-6">
|
||||||
|
<div className="mx-auto max-w-4xl">
|
||||||
|
<div className="mb-6 flex items-center gap-3">
|
||||||
|
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-4 py-1.5 text-cyan-400">
|
||||||
|
{t("sisyphus.badge")}
|
||||||
|
</Badge>
|
||||||
|
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
||||||
|
{t("sisyphus.model")}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="mb-4 text-4xl font-bold text-white md:text-5xl">
|
||||||
|
<span className="text-cyan-400">{t("sisyphus.title")}</span>
|
||||||
|
</h2>
|
||||||
|
<h3 className="mb-6 text-2xl font-bold text-zinc-300 md:text-3xl">
|
||||||
|
{t("sisyphus.headline")}
|
||||||
|
</h3>
|
||||||
|
<p className="mb-12 max-w-3xl text-xl leading-relaxed text-zinc-400">
|
||||||
|
{t("sisyphus.description")}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mb-12 grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||||
|
{(["intent", "explore", "delegate", "verify"] as const).map((phase, i) => (
|
||||||
|
<div key={phase}>
|
||||||
|
<Card className="h-full border-zinc-800 bg-zinc-900/30">
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<div className="mb-1 font-mono text-xs text-cyan-400">PHASE {i + 1}</div>
|
||||||
|
<CardTitle className="text-lg text-white">
|
||||||
|
{t(`sisyphus.phases.${phase}.title`)}
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-sm text-zinc-400">
|
||||||
|
{t(`sisyphus.phases.${phase}.description`)}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="rounded-xl border border-cyan-400/20 bg-cyan-400/5 p-6 md:p-8">
|
||||||
|
<div className="flex items-start gap-4">
|
||||||
|
<div className="rounded-lg bg-cyan-400/10 p-3">
|
||||||
|
<HardDrive className="h-6 w-6 text-cyan-400" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 className="mb-2 text-xl font-bold text-cyan-400">
|
||||||
|
{t("sisyphus.boulderTitle")}
|
||||||
|
</h4>
|
||||||
|
<p className="leading-relaxed text-zinc-300">
|
||||||
|
{t("sisyphus.boulderDescription")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
|
import { ArrowRight, Zap } from "lucide-react"
|
||||||
|
import {
|
||||||
|
SUB_AGENT_KEYS,
|
||||||
|
AGENT_STYLES,
|
||||||
|
CATEGORY_ROUTING,
|
||||||
|
SKILL_INJECTIONS,
|
||||||
|
} from "@/components/landing/constants"
|
||||||
|
|
||||||
|
export async function SubAgentsSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="border-t border-white/5 bg-[#0a0a0a] py-24" data-section="sub-agents">
|
||||||
|
<div className="reveal-on-enter container mx-auto px-4 md:px-6">
|
||||||
|
<div className="mb-16 text-center">
|
||||||
|
<h2 className="mb-4 text-4xl font-bold text-white md:text-5xl">{t("agents.title")}</h2>
|
||||||
|
<p className="text-xl text-zinc-400">{t("agents.subtitle")}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-5">
|
||||||
|
{SUB_AGENT_KEYS.map((key) => {
|
||||||
|
const style = AGENT_STYLES[key]
|
||||||
|
const Icon = style.icon
|
||||||
|
return (
|
||||||
|
<div key={key}>
|
||||||
|
<Card
|
||||||
|
className={`h-full border-zinc-800 bg-zinc-900/30 ${style.border} ${style.bg}`}
|
||||||
|
>
|
||||||
|
<CardHeader className="pb-2">
|
||||||
|
<div className="flex items-start justify-between">
|
||||||
|
<div className={`rounded-lg bg-black/50 p-2 ${style.color}`}>
|
||||||
|
<Icon className="h-5 w-5" />
|
||||||
|
</div>
|
||||||
|
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
||||||
|
{t(`agents.${key}.model`)}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<CardTitle className={`mt-3 text-lg ${style.color}`}>
|
||||||
|
{t(`agents.${key}.name`)}
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription className="text-sm font-medium text-zinc-400">
|
||||||
|
{t(`agents.${key}.role`)}
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-sm leading-relaxed text-zinc-300">
|
||||||
|
{t(`agents.${key}.description`)}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
|
||||||
|
<div className="col-span-1 mt-4 md:col-span-2 lg:col-span-5">
|
||||||
|
<Card className="h-full overflow-hidden border-zinc-800 bg-zinc-900/30">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="mb-2 flex items-center gap-3">
|
||||||
|
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-3 py-1 text-cyan-400">
|
||||||
|
{t("agents.dynamicSystem.role")}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<CardTitle className="text-2xl text-cyan-400">
|
||||||
|
{t("agents.dynamicSystem.name")}
|
||||||
|
</CardTitle>
|
||||||
|
<CardDescription className="max-w-3xl text-base text-zinc-400">
|
||||||
|
{t("agents.dynamicSystem.description")}
|
||||||
|
</CardDescription>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="mt-4 grid grid-cols-1 gap-8 md:grid-cols-2">
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-sm font-bold tracking-wider text-zinc-300 uppercase">
|
||||||
|
Category Routing
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-2">
|
||||||
|
{CATEGORY_ROUTING.map((item) => (
|
||||||
|
<div
|
||||||
|
key={item.cat}
|
||||||
|
className="flex items-center justify-between rounded border border-zinc-800/50 bg-black/40 p-2"
|
||||||
|
>
|
||||||
|
<span className="font-mono text-sm text-cyan-400">{item.cat}</span>
|
||||||
|
<ArrowRight className="h-3 w-3 text-zinc-600" />
|
||||||
|
<span className="text-sm text-zinc-300">{item.model}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-sm font-bold tracking-wider text-zinc-300 uppercase">
|
||||||
|
Skill Injection
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-3">
|
||||||
|
{SKILL_INJECTIONS.map((skill) => (
|
||||||
|
<div
|
||||||
|
key={skill}
|
||||||
|
className="flex items-center gap-2 rounded border border-zinc-700/50 bg-zinc-800/30 p-3"
|
||||||
|
>
|
||||||
|
<Zap className="h-4 w-4 text-yellow-400" />
|
||||||
|
<span className="font-mono text-sm text-zinc-200">{skill}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="mt-6 rounded-lg border border-cyan-500/10 bg-cyan-500/5 p-4">
|
||||||
|
<p className="text-sm text-cyan-300 italic">
|
||||||
|
"The right model + right expertise, every time."
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { Network, Users, Terminal, Wrench, Sparkles, Sword, Shield } from "lucide-react"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
|
|
||||||
|
export async function TeamModeSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
id="team-mode"
|
||||||
|
className="relative overflow-hidden border-t border-white/5 bg-[#0a0a0a] py-24"
|
||||||
|
data-section="team-mode"
|
||||||
|
>
|
||||||
|
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-violet-900/10 via-black to-black opacity-70" />
|
||||||
|
<div className="reveal-on-enter relative z-10 container mx-auto px-4 md:px-6">
|
||||||
|
<div className="mx-auto max-w-5xl">
|
||||||
|
<div className="mb-6 flex flex-wrap items-center gap-3">
|
||||||
|
<Badge className="border-violet-500/20 bg-violet-500/10 px-4 py-1.5 font-mono text-violet-300">
|
||||||
|
{t("teamMode.badge")}
|
||||||
|
</Badge>
|
||||||
|
<Badge variant="outline" className="border-zinc-700 text-xs text-zinc-400">
|
||||||
|
opt-in
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="mb-4 text-4xl font-bold tracking-tight md:text-5xl">
|
||||||
|
<span className="text-cyan-400">{t("teamMode.title")}</span>
|
||||||
|
</h2>
|
||||||
|
<h3 className="mb-6 text-2xl font-bold text-zinc-200 md:text-3xl">
|
||||||
|
{t("teamMode.headline")}
|
||||||
|
</h3>
|
||||||
|
<p className="mb-12 max-w-3xl text-xl leading-relaxed text-zinc-400">
|
||||||
|
{t("teamMode.description")}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mb-16 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||||
|
{(
|
||||||
|
[
|
||||||
|
{ key: "lead", icon: Network },
|
||||||
|
{ key: "parallel", icon: Users },
|
||||||
|
{ key: "tmux", icon: Terminal },
|
||||||
|
{ key: "tools", icon: Wrench },
|
||||||
|
] as const
|
||||||
|
).map(({ key, icon: Icon }) => (
|
||||||
|
<div key={key}>
|
||||||
|
<Card className="h-full border-zinc-800 bg-zinc-900/30 transition-colors hover:border-cyan-500/30">
|
||||||
|
<CardHeader className="pb-3">
|
||||||
|
<div className="w-fit rounded-lg bg-cyan-500/10 p-2 text-cyan-300">
|
||||||
|
<Icon className="h-5 w-5" />
|
||||||
|
</div>
|
||||||
|
<CardTitle className="mt-3 text-lg text-cyan-200">
|
||||||
|
{t(`teamMode.features.${key}.title`)}
|
||||||
|
</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="text-sm leading-relaxed text-zinc-400">
|
||||||
|
{t(`teamMode.features.${key}.description`)}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-10 flex items-center gap-3">
|
||||||
|
<Sparkles className="h-4 w-4 text-violet-400" />
|
||||||
|
<span className="font-mono text-sm tracking-widest text-violet-400 uppercase">
|
||||||
|
{t("teamMode.poweredBy")}
|
||||||
|
</span>
|
||||||
|
<div className="h-px flex-1 bg-gradient-to-r from-violet-500/30 to-transparent" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-12 grid grid-cols-1 gap-6 lg:grid-cols-2">
|
||||||
|
{(
|
||||||
|
[
|
||||||
|
{ key: "hyperplan", icon: Sword },
|
||||||
|
{ key: "securityResearch", icon: Shield },
|
||||||
|
] as const
|
||||||
|
).map(({ key, icon: Icon }) => (
|
||||||
|
<div key={key}>
|
||||||
|
<Card className="h-full border-zinc-800 bg-zinc-900/30 transition-colors hover:border-violet-500/40">
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<div className="rounded-lg bg-violet-500/10 p-2 text-violet-300">
|
||||||
|
<Icon className="h-5 w-5" />
|
||||||
|
</div>
|
||||||
|
<CardTitle className="font-mono text-lg text-violet-300">
|
||||||
|
{t(`teamMode.skills.${key}.name`)}
|
||||||
|
</CardTitle>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<p className="leading-relaxed text-zinc-300">
|
||||||
|
{t(`teamMode.skills.${key}.description`)}
|
||||||
|
</p>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col items-start gap-4 rounded-xl border border-zinc-800 bg-black/40 p-6 sm:flex-row sm:items-center sm:justify-between">
|
||||||
|
<code className="font-mono text-sm break-all text-cyan-300">{t("teamMode.optIn")}</code>
|
||||||
|
<p className="text-sm text-zinc-400 italic sm:text-right">{t("teamMode.tagline")}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import type { JSX } from "react"
|
||||||
|
import { getTranslations } from "next-intl/server"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { TerminalTypewriter } from "@/components/landing/motion-wrappers"
|
||||||
|
|
||||||
|
export async function UltraworkSection(): Promise<JSX.Element> {
|
||||||
|
const t = await getTranslations("landing")
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
data-section="ultrawork"
|
||||||
|
id="features"
|
||||||
|
className="overflow-hidden border-t border-white/5 bg-[#0a0a0a] py-24"
|
||||||
|
>
|
||||||
|
<div className="reveal-on-enter container mx-auto px-4 md:px-6">
|
||||||
|
<div className="flex flex-col items-center gap-16 lg:flex-row">
|
||||||
|
<div className="flex-1 space-y-8">
|
||||||
|
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-4 py-1.5 text-cyan-400">
|
||||||
|
{t("ulw.badge")}
|
||||||
|
</Badge>
|
||||||
|
<h2 className="text-4xl font-black tracking-tighter text-cyan-400 md:text-5xl">
|
||||||
|
{t("ulw.title")}
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="text-3xl font-bold text-white">{t("ulw.headline")}</h3>
|
||||||
|
<p className="text-xl leading-relaxed text-zinc-400">{t("ulw.description")}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-wrap gap-3">
|
||||||
|
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-4 py-2 text-sm text-cyan-400">
|
||||||
|
{t("ulw.autoPlanning")}
|
||||||
|
</Badge>
|
||||||
|
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-4 py-2 text-sm text-cyan-400">
|
||||||
|
{t("ulw.deepResearch")}
|
||||||
|
</Badge>
|
||||||
|
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-4 py-2 text-sm text-cyan-400">
|
||||||
|
{t("ulw.selfCorrection")}
|
||||||
|
</Badge>
|
||||||
|
<Badge className="border-cyan-500/20 bg-cyan-500/10 px-4 py-2 text-sm text-cyan-400">
|
||||||
|
{t("ulw.parallelAgents")}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<p className="text-lg text-zinc-400/90 italic">{t("ulw.tagline")}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full max-w-xl flex-1">
|
||||||
|
<div className="overflow-hidden rounded-xl border border-zinc-800 bg-black shadow-xl shadow-cyan-500/5">
|
||||||
|
<div className="flex items-center gap-2 border-b border-zinc-800 bg-zinc-900/50 px-4 py-3">
|
||||||
|
<div className="h-3 w-3 rounded-full border border-red-500/50 bg-red-500/20" />
|
||||||
|
<div className="h-3 w-3 rounded-full border border-yellow-500/50 bg-yellow-500/20" />
|
||||||
|
<div className="h-3 w-3 rounded-full border border-green-500/50 bg-green-500/20" />
|
||||||
|
<div className="ml-2 font-mono text-xs text-zinc-400">{t("ulw.terminalTitle")}</div>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-4 overflow-x-auto p-6 font-mono text-sm">
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<span className="text-green-500">$</span>
|
||||||
|
<span className="text-cyan-500">~</span>
|
||||||
|
<TerminalTypewriter text={t("ulw.terminalInput")} />
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2 border-l-2 border-zinc-800 pl-4">
|
||||||
|
<div className="text-cyan-400">{t("ulw.steps.scanning")}</div>
|
||||||
|
<div className="text-zinc-400">{t("ulw.steps.context")}</div>
|
||||||
|
<div className="text-purple-400">{t("ulw.steps.planning")}</div>
|
||||||
|
<div className="text-amber-400">{t("ulw.steps.delegating")}</div>
|
||||||
|
<div className="text-blue-400">{t("ulw.steps.verifying")}</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2 pt-4">
|
||||||
|
<span className="text-green-500">ok</span>
|
||||||
|
<span className="font-bold text-green-400">{t("ulw.steps.complete")}</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<span className="text-green-500">$</span>
|
||||||
|
<span className="text-cyan-500">~</span>
|
||||||
|
<span className="animate-pulse text-white">_</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user