import LanguageSwitch from "@/components/LanguageSwitch";
import { Button } from "@/components/ui/button";
import { useAuth } from "@/contexts/AuthContext";
import { useI18n } from "@/i18n/I18nProvider";
import {
ArrowRight,
Boxes,
Eye,
Github,
LayoutDashboard,
Terminal,
} from "lucide-react";
import { Link } from "react-router-dom";
const REPO_URL = "https://github.com/WebchemistCorp/devist";
export default function Landing() {
const { session } = useAuth();
return (
<div className="min-h-screen bg-background text-foreground">
<Header signedIn={!!session} />
<main>
<Hero signedIn={!!session} />
<About />
<Workflow />
</main>
<Footer />
</div>
);
}
function Header({ signedIn }: { signedIn: boolean }) {
const { t } = useI18n();
return (
<header className="sticky top-0 z-10 border-b bg-background/80 backdrop-blur">
<div className="mx-auto max-w-6xl px-6 h-14 flex items-center justify-between">
<Link to="/" className="flex items-center gap-2 font-semibold">
<span className="text-base">devist</span>
<span className="text-xs text-muted-foreground hidden sm:inline">
{t("landing.tagline")}
</span>
</Link>
<nav className="flex items-center gap-2">
<LanguageSwitch />
<a
href={REPO_URL}
target="_blank"
rel="noreferrer"
className="text-sm text-muted-foreground hover:text-foreground p-2 rounded-md hover:bg-muted"
title="GitHub"
>
<Github size={16} />
</a>
{signedIn ? (
<Link to="/dashboard">
<Button size="sm">{t("common.openDashboard")}</Button>
</Link>
) : (
<Link to="/login">
<Button size="sm" variant="ghost">
{t("common.signIn")}
</Button>
</Link>
)}
</nav>
</div>
</header>
);
}
function Hero({ signedIn }: { signedIn: boolean }) {
const { t } = useI18n();
return (
<section className="mx-auto max-w-6xl px-6 pt-20 pb-16">
<div className="max-w-3xl">
<h1 className="text-4xl sm:text-5xl font-bold tracking-tight">
{t("landing.tagline")}
</h1>
<p className="mt-5 text-lg text-muted-foreground leading-relaxed">
{t("landing.hero.subhead")}
</p>
<div className="mt-8 flex items-center gap-3 flex-wrap">
<Link to={signedIn ? "/dashboard" : "/login"}>
<Button size="lg" className="gap-2">
{signedIn
? t("common.openDashboard")
: t("landing.hero.getStarted")}
<ArrowRight size={16} />
</Button>
</Link>
<a href={REPO_URL} target="_blank" rel="noreferrer">
<Button size="lg" variant="outline" className="gap-2">
<Github size={16} />
{t("landing.hero.viewGitHub")}
</Button>
</a>
</div>
<pre className="mt-10 rounded-lg border bg-muted/40 p-4 text-sm overflow-x-auto">
<code>
<span className="text-muted-foreground">
{t("landing.hero.codeComment.install")}
</span>
{"\n"}
cargo install devist{"\n\n"}
<span className="text-muted-foreground">
{t("landing.hero.codeComment.scaffold")}
</span>
{"\n"}
devist init my-app --template react-vite{"\n"}
devist start my-app --dev
</code>
</pre>
</div>
</section>
);
}
function About() {
const { t } = useI18n();
const cards = [
{
icon: <Boxes size={20} />,
title: t("landing.about.templates.title"),
body: t("landing.about.templates.body"),
},
{
icon: <Eye size={20} />,
title: t("landing.about.worker.title"),
body: t("landing.about.worker.body"),
},
{
icon: <LayoutDashboard size={20} />,
title: t("landing.about.dashboard.title"),
body: t("landing.about.dashboard.body"),
},
];
return (
<section className="border-t bg-muted/20">
<div className="mx-auto max-w-6xl px-6 py-16">
<div className="max-w-2xl">
<h2 className="text-2xl sm:text-3xl font-bold tracking-tight">
{t("landing.about.title")}
</h2>
<p className="mt-3 text-muted-foreground">
{t("landing.about.subtitle")}
</p>
</div>
<div className="mt-10 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{cards.map((c) => (
<div
key={c.title}
className="rounded-lg border bg-card p-5 space-y-3"
>
<div className="inline-flex items-center justify-center w-9 h-9 rounded-md bg-foreground/5">
{c.icon}
</div>
<h3 className="font-semibold">{c.title}</h3>
<p className="text-sm text-muted-foreground leading-relaxed">
{c.body}
</p>
</div>
))}
</div>
</div>
</section>
);
}
function Workflow() {
const { t } = useI18n();
const steps = [
{
n: "1",
title: t("landing.workflow.install.title"),
cmd: "cargo install devist",
hint: t("landing.workflow.install.hint"),
},
{
n: "2",
title: t("landing.workflow.scaffold.title"),
cmd: "devist init my-app --template react-vite",
hint: t("landing.workflow.scaffold.hint"),
},
{
n: "3",
title: t("landing.workflow.startWorker.title"),
cmd: "devist worker start",
hint: t("landing.workflow.startWorker.hint"),
},
];
return (
<section className="border-t">
<div className="mx-auto max-w-6xl px-6 py-16">
<div className="max-w-2xl">
<h2 className="text-2xl sm:text-3xl font-bold tracking-tight">
{t("landing.workflow.title")}
</h2>
<p className="mt-3 text-muted-foreground">
{t("landing.workflow.subtitle")}
</p>
</div>
<ol className="mt-10 space-y-5">
{steps.map((s) => (
<li
key={s.n}
className="flex gap-5 items-start rounded-lg border bg-card p-5"
>
<div className="shrink-0 inline-flex items-center justify-center w-8 h-8 rounded-full bg-foreground text-background text-sm font-semibold">
{s.n}
</div>
<div className="flex-1 min-w-0 space-y-2">
<h3 className="font-semibold">{s.title}</h3>
<pre className="rounded border bg-muted/40 px-3 py-2 text-sm overflow-x-auto">
<code className="flex items-center gap-2">
<Terminal
size={14}
className="shrink-0 text-muted-foreground"
/>
{s.cmd}
</code>
</pre>
<p className="text-sm text-muted-foreground">{s.hint}</p>
</div>
</li>
))}
</ol>
</div>
</section>
);
}
function Footer() {
const { t } = useI18n();
return (
<footer className="border-t">
<div className="mx-auto max-w-6xl px-6 py-8 flex items-center justify-between text-sm text-muted-foreground">
<span>{t("footer.attribution")}</span>
<div className="flex items-center gap-4">
<a
href={REPO_URL}
target="_blank"
rel="noreferrer"
className="hover:text-foreground"
>
{t("footer.github")}
</a>
<a
href={`${REPO_URL}/blob/main/LICENSE`}
target="_blank"
rel="noreferrer"
className="hover:text-foreground"
>
{t("footer.license")}
</a>
</div>
</div>
</footer>
);
}