mirror of
https://github.com/hex248/sprint.git
synced 2026-02-08 10:33:01 +00:00
326 lines
14 KiB
TypeScript
326 lines
14 KiB
TypeScript
import { useState } from "react";
|
|
import { Link } from "react-router-dom";
|
|
import { LoginModal } from "@/components/login-modal";
|
|
import { useSession } from "@/components/session-provider";
|
|
import ThemeToggle from "@/components/theme-toggle";
|
|
import { Button } from "@/components/ui/button";
|
|
import Icon from "@/components/ui/icon";
|
|
|
|
// const faqs = [
|
|
// {
|
|
// question: "What payment methods do you accept?",
|
|
// answer: "We accept all major credit cards.",
|
|
// },
|
|
// {
|
|
// question: "What if I need more users?",
|
|
// answer:
|
|
// "Pro plan pricing scales with your team. Add or remove users anytime, and we'll adjust your billing automatically.",
|
|
// },
|
|
// {
|
|
// question: "Can I cancel anytime?",
|
|
// answer:
|
|
// "Absolutely. Cancel anytime with no questions asked. You'll keep access until the end of your billing period.",
|
|
// },
|
|
// {
|
|
// question: "Do you offer refunds?",
|
|
// answer: "Yes, we offer a 30-day money-back guarantee. If Sprint isn't right for you, just let us know.",
|
|
// },
|
|
// ];
|
|
|
|
export default function Landing() {
|
|
const { user, isLoading } = useSession();
|
|
const [loginModalOpen, setLoginModalOpen] = useState(false);
|
|
|
|
return (
|
|
<div className="min-h-screen flex flex-col" id="top">
|
|
<header className="sticky top-0 z-50 w-full border-b bg-background/80 backdrop-blur-md">
|
|
<div className="w-full flex h-14 items-center justify-between px-2">
|
|
<div className="flex items-center gap-2">
|
|
<img src="/favicon.svg" alt="Sprint" className="size-12 -mt-0.5" />
|
|
<span className="text-3xl font-basteleur font-700 transition-colors -mt-0.5">Sprint</span>
|
|
</div>
|
|
<nav className="flex items-center gap-6">
|
|
<a
|
|
href="#top"
|
|
className="hidden md:block text-sm font-500 hover:text-personality transition-colors"
|
|
>
|
|
Home
|
|
</a>
|
|
<a
|
|
href="#features"
|
|
className="hidden md:block text-sm font-500 hover:text-personality transition-colors"
|
|
>
|
|
Features
|
|
</a>
|
|
{/* <a
|
|
href="#pricing"
|
|
className="hidden md:block text-sm font-500 hover:text-personality transition-colors"
|
|
>
|
|
Pricing
|
|
</a> */}
|
|
{/* <a
|
|
href="#faq"
|
|
className="hidden md:block text-sm font-500 hover:text-personality transition-colors"
|
|
>
|
|
FAQ
|
|
</a> */}
|
|
<div className="flex items-center gap-2">
|
|
<ThemeToggle />
|
|
{!isLoading && user ? (
|
|
<Button asChild variant="outline" size="sm">
|
|
<Link to="/issues">Open app</Link>
|
|
</Button>
|
|
) : (
|
|
<Button variant="outline" size="sm" onClick={() => setLoginModalOpen(true)}>
|
|
Sign in
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
<main className="flex-1 flex flex-col items-center py-16 pt-14 px-4">
|
|
<div className="max-w-6xl w-full space-y-18">
|
|
{/* hero section */}
|
|
<div className="text-center space-y-8">
|
|
<div className="flex justify-center mb-8">
|
|
<img src="/favicon.svg" alt="Sprint" className="size-48" />
|
|
</div>
|
|
<div className="space-y-4">
|
|
<h1 className="text-[64px] font-basteleur font-700 leading-tight">
|
|
Ship faster without the chaos
|
|
</h1>
|
|
<p className="text-[24px] text-muted-foreground max-w-3xl mx-auto">
|
|
Sprint is project management that stays out of your way. Track issues, manage sprints, and
|
|
keep your team moving—without the Jira headache.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
|
|
{!isLoading && user ? (
|
|
<Button asChild size="lg" className="text-lg px-8 py-6">
|
|
<Link to="/issues">Open app</Link>
|
|
</Button>
|
|
) : (
|
|
<>
|
|
<Button size="lg" className="text-lg px-8 py-6" onClick={() => setLoginModalOpen(true)}>
|
|
Get started
|
|
</Button>
|
|
{/* <Button asChild variant="outline" size="lg" className="text-lg px-8 py-6">
|
|
<a href="#pricing">See pricing</a>
|
|
</Button> */}
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
{/* <p className="text-sm text-muted-foreground">Free forever · Upgrade when you need more</p> */}
|
|
</div>
|
|
|
|
{/* problem section */}
|
|
<div className="max-w-4xl mx-auto space-y-16">
|
|
<h2 className="text-4xl font-basteleur font-700 text-center">
|
|
Tired of spending more time managing Jira than building products?
|
|
</h2>
|
|
<div className="grid md:grid-cols-3 gap-6">
|
|
<div className="space-y-2">
|
|
<Icon icon="timerOff" iconStyle={"pixel"} className="size-16 mx-auto" />
|
|
<p className="text-center">
|
|
Wasting hours configuring workflows instead of shipping features
|
|
</p>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Icon icon="gridAdd" iconStyle={"pixel"} className="size-16 mx-auto" />
|
|
<p className="text-center">Drowning in features you'll never use while missing the basics</p>
|
|
</div>
|
|
<div className="space-y-2">
|
|
<Icon icon="bugOff" iconStyle={"pixel"} className="size-16 mx-auto" />
|
|
<p className="text-center">
|
|
The tools are full of bugs. Your flow state doesn't stand a chance
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* solution section */}
|
|
<div id="features" className="max-w-5xl mx-auto space-y-12 scroll-mt-4 border-t pt-24">
|
|
<h2 className="text-5xl font-basteleur font-700 text-center">
|
|
Everything you need, nothing you don't
|
|
</h2>
|
|
<div className="grid md:grid-cols-2 gap-8">
|
|
<div className="border p-8 space-y-4">
|
|
<Icon
|
|
icon="layoutDashboard"
|
|
iconStyle={"pixel"}
|
|
className="size-10"
|
|
color={"var(--personality)"}
|
|
/>
|
|
<h3 className="text-2xl font-basteleur font-700">See your work at a glance</h3>
|
|
<p className="text-muted-foreground text-lg">
|
|
Beautiful, intuitive issue tracking with customizable statuses. Organize by projects and
|
|
sprints. Find what you need in seconds, not minutes.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="border p-8 space-y-4">
|
|
<Icon icon="timer" iconStyle={"pixel"} className="size-10" color={"var(--personality)"} />
|
|
<h3 className="text-2xl font-basteleur font-700">Track time without thinking</h3>
|
|
<p className="text-muted-foreground text-lg">
|
|
Built-in time tracking that actually works. Start, pause, resume. See where your time goes
|
|
without juggling another tool.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="border p-8 space-y-4">
|
|
<Icon icon="rocket" iconStyle={"pixel"} className="size-10" color={"var(--personality)"} />
|
|
<h3 className="text-2xl font-basteleur font-700">Ship in sprints</h3>
|
|
<p className="text-muted-foreground text-lg">
|
|
Sprint planning that actually works. Set date ranges, assign issues, track velocity. Keep
|
|
your team aligned without the ceremony.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="border p-8 space-y-4">
|
|
<Icon icon="checkBox" iconStyle={"pixel"} className="size-10" color={"var(--personality)"} />
|
|
<h3 className="text-2xl font-basteleur font-700">Only use what you need</h3>
|
|
<p className="text-muted-foreground text-lg">
|
|
Every feature is optional. Sprints, time tracking, and other modules can be enabled or
|
|
disabled individually at the organization level. Keep your interface as minimal as your
|
|
workflow.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* features list */}
|
|
<div className="max-w-4xl mx-auto border p-8 space-y-6">
|
|
<h2 className="text-3xl font-basteleur font-700 text-center">
|
|
Built for developers, by a developer
|
|
</h2>
|
|
<div className="grid md:grid-cols-2 gap-x-8 gap-y-3">
|
|
{[
|
|
"Organization and project management",
|
|
"Customizable issue statuses",
|
|
"Sprint planning with date ranges",
|
|
"Built-in time tracking",
|
|
"Native desktop app (Tauri)",
|
|
"Clean, resizable interface",
|
|
"Issue assignment and collaboration",
|
|
"Individual feature toggles (org level)",
|
|
].map((feature) => (
|
|
<div key={feature} className="flex items-start gap-2">
|
|
<Icon icon="check" iconStyle={"pixel"} className="size-6" color={"var(--personality)"} />
|
|
<span>{feature}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* pricing section */}
|
|
{/* <div id="pricing" className="max-w-5xl mx-auto space-y-12 scroll-mt-4 border-t pt-24">
|
|
<div className="text-center space-y-6">
|
|
<h2 className="text-5xl font-basteleur font-700">Simple, transparent pricing</h2>
|
|
<p className="text-xl text-muted-foreground max-w-2xl mx-auto">
|
|
Choose the plan that fits your team. Scale as you grow.
|
|
</p>
|
|
<Button asChild variant="outline" size="lg" className="text-lg px-8 py-6">
|
|
<Link to="/plans">View plans</Link>
|
|
</Button>
|
|
</div>
|
|
</div> */}
|
|
|
|
{/* faq section */}
|
|
{/* <div id="faq" className="w-full max-w-5xl flex justify-center scroll-mt-4 border-t pt-24">
|
|
<div className="w-full max-w-4xl flex flex-col items-center space-y-12">
|
|
<h2 className="text-5xl font-basteleur font-700 text-center">Frequently Asked Questions</h2>
|
|
<div className="grid gap-8 max-w-3xl">
|
|
{faqs.map((faq) => (
|
|
<div key={faq.question} className="space-y-2">
|
|
<h4 className="text-lg font-700">{faq.question}</h4>
|
|
<p className="text-muted-foreground">{faq.answer}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div> */}
|
|
|
|
{/* TODO:> commented out until we have actual testimonies */}
|
|
{/* social proof placeholder */}
|
|
{/* <div className="max-w-4xl mx-auto text-center space-y-8">
|
|
<h2 className="text-4xl font-basteleur font-700">Join developers who've escaped Jira</h2>
|
|
<div className="grid md:grid-cols-3 gap-8">
|
|
<div className="border p-6 space-y-4">
|
|
<p className="text-lg italic text-muted-foreground">
|
|
"Finally, a project management tool that doesn't slow me down"
|
|
</p>
|
|
<p className="text-sm font-700">Early user feedback</p>
|
|
</div>
|
|
<div className="border p-6 space-y-4">
|
|
<p className="text-lg italic text-muted-foreground">
|
|
"Built by someone who actually understands developer workflows"
|
|
</p>
|
|
<p className="text-sm font-700">Early user feedback</p>
|
|
</div>
|
|
<div className="border p-6 space-y-4">
|
|
<p className="text-lg italic text-muted-foreground">
|
|
"The simplicity is refreshing. No bloat, just what we need"
|
|
</p>
|
|
<p className="text-sm font-700">Early user feedback</p>
|
|
</div>
|
|
</div>
|
|
</div> */}
|
|
|
|
{/* final cta */}
|
|
<div className="max-w-5xl mx-auto text-center space-y-6 border-t pt-16">
|
|
<h2 className="text-5xl font-basteleur font-700">Ready to ship faster?</h2>
|
|
<p className="text-xl text-muted-foreground">
|
|
Start tracking issues, managing sprints, and shipping products in minutes
|
|
</p>
|
|
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
|
|
{!isLoading && user ? (
|
|
<Button asChild size="lg" className="text-lg px-8 py-6">
|
|
<Link to="/issues">Open app</Link>
|
|
</Button>
|
|
) : (
|
|
<Button size="lg" className="text-lg px-8 py-6" onClick={() => setLoginModalOpen(true)}>
|
|
Get started
|
|
</Button>
|
|
)}
|
|
</div>
|
|
{/* <p className="text-sm text-muted-foreground">
|
|
Free forever · Upgrade when you need more · Cancel anytime
|
|
</p> */}
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<LoginModal open={loginModalOpen} onOpenChange={setLoginModalOpen} />
|
|
|
|
<footer className="flex flex-col items-center gap-2 py-1 border-t">
|
|
<div className="flex justify-center gap-2 items-center">
|
|
<span className="font-300 text-lg text-muted-foreground">
|
|
Built by{" "}
|
|
<a
|
|
href="https://ob248.com"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="hover:text-personality font-700"
|
|
>
|
|
Oliver Bryan
|
|
</a>
|
|
</span>
|
|
<a href="https://ob248.com" target="_blank" rel="noopener noreferrer">
|
|
<img src="oliver-bryan.svg" alt="Oliver Bryan" className="w-4 h-4" />
|
|
</a>
|
|
</div>
|
|
<Link
|
|
to="/the-boring-stuff"
|
|
className="text-sm text-muted-foreground hover:text-personality transition-colors"
|
|
>
|
|
The boring stuff — Privacy Policy & ToS
|
|
</Link>
|
|
</footer>
|
|
</div>
|
|
);
|
|
}
|