Seed: developer-tools template (15 files)

This commit is contained in:
2026-07-23 22:15:23 +00:00
parent 1e4613fd02
commit a8f3847a8f
+363
View File
@@ -0,0 +1,363 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import {
ArrowRight, Terminal, Zap, Shield, Globe, BarChart3, Lock,
Star, CheckCircle2, ChevronRight, Code2, Quote
} from "lucide-react";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
import { useSaasMutation } from "@/hooks/use-tygarun";
import { toast } from "sonner";
const languages = ["Python", "Node.js", "Go", "Ruby"];
const codeExamples: Record<string, string> = {
curl: `curl -X POST https://api.devstack.io/v1/deploy \\
-H 'Authorization: Bearer sk_live_...' \\
-H 'Content-Type: application/json' \\
-d '{"project": "my-app", "env": "production"}'`,
javascript: `import { DevStack } from '@devstack/sdk';
const client = new DevStack('sk_live_...');
const deploy = await client.deploys.create({
project: 'my-app',
env: 'production',
});
console.log(deploy.url);`,
python: `import devstack
client = devstack.Client("sk_live_...")
deploy = client.deploys.create(
project="my-app",
env="production",
)
print(deploy.url)`,
};
const features = [
{ icon: Terminal, title: "CLI-First Workflow", desc: "Deploy from your terminal with a single command. No dashboards required." },
{ icon: Zap, title: "Blazing Fast APIs", desc: "Sub-50ms response times globally with edge functions and smart caching." },
{ icon: Shield, title: "Enterprise Security", desc: "SOC 2 compliant with end-to-end encryption and role-based access controls." },
{ icon: Globe, title: "Global Edge Network", desc: "Deploy to 30+ regions worldwide with automatic failover and load balancing." },
{ icon: BarChart3, title: "Real-Time Analytics", desc: "Monitor API usage, latency, and errors in real time with built-in dashboards." },
{ icon: Lock, title: "API Key Management", desc: "Fine-grained API keys with scopes, rate limits, and automatic rotation." },
];
const integrations = ["React", "Next.js", "Node.js", "Python", "Go", "Ruby", "Docker", "AWS"];
const tiers = [
{
name: "Free",
price: "0",
desc: "For side projects and experiments",
calls: "10,000 API calls/mo",
features: ["10k requests/month", "Community support", "1 project", "Basic analytics"],
cta: "Start Free",
popular: false,
plan: "free",
},
{
name: "Pro",
price: "29",
desc: "For growing teams and startups",
calls: "1M API calls/mo",
features: ["1M requests/month", "Priority support", "Unlimited projects", "Advanced analytics", "Custom domains", "Team seats (5)"],
cta: "Start Trial",
popular: true,
plan: "pro",
},
{
name: "Enterprise",
price: "Custom",
desc: "For large-scale deployments",
calls: "Unlimited API calls",
features: ["Unlimited requests", "24/7 dedicated support", "SLA guarantee", "SSO & SAML", "On-premise option", "Custom integrations"],
cta: "Contact Sales",
popular: false,
plan: null,
},
];
const testimonials = [
{ name: "Sarah Chen", role: "CTO at Raycast", quote: "DevStack cut our API development time by 70%. The DX is unmatched.", stars: 5 },
{ name: "Marcus Rivera", role: "Lead Engineer at Vercel", quote: "Finally an API platform that thinks like a developer. Shipping is effortless now.", stars: 5 },
{ name: "Ava Patel", role: "Founder at Deno Labs", quote: "We migrated our entire backend in a weekend. The SDK is beautifully designed.", stars: 5 },
];
export default function IndexPage() {
const [codeTab, setCodeTab] = useState("curl");
const { mutate: createCheckout, loading: checkingOut } = useSaasMutation("billing", "/checkout");
const handlePlan = async (tier) => {
if (!tier.plan) return; // Enterprise → Contact Sales link
try {
const res = await createCheckout({ plan: tier.plan });
if (res?.url && res.url.indexOf("#") !== 0) { window.location.href = res.url; return; }
toast.success("Checkout started for the " + tier.name + " plan.");
} catch {
toast.error("Could not start checkout. Please try again.");
}
};
return (
<div className="min-h-screen bg-slate-950 text-white antialiased">
<Header />
{/* ── HERO ── */}
<section className="relative overflow-hidden pt-32 pb-24 sm:pt-40 sm:pb-32">
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-emerald-900/20 via-transparent to-transparent" />
<div className="absolute top-20 left-1/4 w-72 h-72 rounded-full bg-emerald-600/10 blur-[100px] pointer-events-none" />
<div className="absolute top-40 right-1/4 w-96 h-96 rounded-full bg-cyan-500/10 blur-[100px] pointer-events-none" />
<div className="relative mx-auto max-w-7xl px-6">
<div className="grid lg:grid-cols-2 gap-16 items-center">
<div>
<div className="flex flex-wrap items-center gap-2 mb-6">
{languages.map((lang) => (
<Badge key={lang} variant="secondary" className="bg-slate-800 text-slate-300 border-slate-700 text-xs">
{lang}
</Badge>
))}
</div>
<h1 className="text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl">
<span className="bg-gradient-to-r from-white via-emerald-200 to-emerald-400 bg-clip-text text-transparent">
Build Faster with DevStack
</span>
</h1>
<p className="mt-6 text-lg text-slate-400 max-w-xl leading-relaxed">
The API platform that lets you ship production-ready backends in minutes. Authentication, databases, deployments, and monitoring out of the box.
</p>
<div className="mt-8 flex flex-wrap gap-4">
<Button asChild className="rounded-full bg-emerald-500 hover:bg-emerald-400 text-slate-950 font-semibold px-8 active:scale-[0.98]">
<Link to="/docs">Get Started <ArrowRight className="ml-2 h-4 w-4" /></Link>
</Button>
<Button asChild variant="outline" className="rounded-full border-slate-700 text-slate-300 hover:bg-slate-800 hover:text-white active:scale-[0.98]">
<Link to="/docs">View Docs <ChevronRight className="ml-1 h-4 w-4" /></Link>
</Button>
</div>
</div>
{/* Code preview */}
<div className="relative">
<div className="rounded-xl border border-slate-800 bg-slate-900/80 backdrop-blur-sm overflow-hidden shadow-2xl shadow-black/40">
<div className="flex items-center gap-2 px-4 py-3 border-b border-slate-800 bg-slate-900/50">
<span className="h-3 w-3 rounded-full bg-red-500/70" />
<span className="h-3 w-3 rounded-full bg-amber-500/70" />
<span className="h-3 w-3 rounded-full bg-emerald-500/70" />
<span className="text-xs text-slate-500 ml-2 font-mono">terminal</span>
</div>
<pre className="p-6 text-sm font-mono leading-relaxed overflow-x-auto">
<code>
<span className="text-slate-500">$</span>{" "}
<span className="text-emerald-400">npm</span>{" "}
<span className="text-slate-300">install @devstack/sdk</span>
{"\n\n"}
<span className="text-slate-500">$</span>{" "}
<span className="text-emerald-400">devstack</span>{" "}
<span className="text-sky-400">deploy</span>{" "}
<span className="text-slate-300">--prod</span>
{"\n\n"}
<span className="text-emerald-400">{">"}</span>{" "}
<span className="text-slate-300">Deployed to</span>{" "}
<span className="text-emerald-400 underline">https://my-app.devstack.io</span>
</code>
</pre>
</div>
</div>
</div>
</div>
</section>
{/* ── QUICK START CODE BLOCK ── */}
<section className="py-24 bg-slate-900/50">
<div className="mx-auto max-w-4xl px-6">
<div className="text-center mb-12">
<Badge className="mb-4 bg-emerald-500/10 text-emerald-400 border-emerald-500/20">Quick Start</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl animate-fade-up">Up and running in seconds</h2>
<p className="mt-4 text-slate-400">Choose your language and make your first API call.</p>
</div>
<div className="rounded-xl border border-slate-800 bg-slate-900 overflow-hidden shadow-2xl shadow-black/30">
<Tabs value={codeTab} onValueChange={setCodeTab}>
<div className="flex items-center justify-between px-4 py-2 border-b border-slate-800 bg-slate-950/50">
<TabsList className="bg-transparent h-auto p-0 gap-0">
{Object.keys(codeExamples).map((key) => (
<TabsTrigger
key={key}
value={key}
className={`rounded-none border-b-2 px-4 py-2 text-sm font-mono data-[state=active]:border-emerald-500 data-[state=active]:text-emerald-400 data-[state=active]:bg-transparent border-transparent text-slate-500 bg-transparent hover:text-slate-300`}
>
{key}
</TabsTrigger>
))}
</TabsList>
<button
className="text-xs text-slate-500 hover:text-white transition-colors font-mono"
onClick={() => navigator.clipboard.writeText(codeExamples[codeTab])}
>
Copy
</button>
</div>
{Object.entries(codeExamples).map(([key, code]) => (
<TabsContent key={key} value={key} className="m-0">
<pre className="p-6 text-sm font-mono leading-relaxed overflow-x-auto text-slate-300">
<code>{code}</code>
</pre>
</TabsContent>
))}
</Tabs>
</div>
</div>
</section>
{/* ── FEATURES ── */}
<section className="py-24 bg-slate-950">
<div className="mx-auto max-w-7xl px-6">
<div className="text-center mb-16">
<Badge className="mb-4 bg-emerald-500/10 text-emerald-400 border-emerald-500/20">Features</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl animate-fade-up">Built for developers, by developers</h2>
<p className="mt-4 text-slate-400 max-w-2xl mx-auto">
Everything you need to build, deploy, and monitor production applications.
</p>
</div>
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6 stagger">
{features.map((f) => (
<Card key={f.title} className="backdrop-blur-sm bg-card/80 border-slate-800 hover:border-emerald-500/30 hover:-translate-y-1 hover:shadow-lg transition-all duration-300 hover:shadow-emerald-500/5">
<CardContent className="p-6">
<div className="h-10 w-10 rounded-lg bg-emerald-500/10 flex items-center justify-center mb-4">
<f.icon className="h-5 w-5 text-emerald-400" />
</div>
<h3 className="font-semibold text-white text-lg mb-2">{f.title}</h3>
<p className="text-sm text-slate-400 leading-relaxed">{f.desc}</p>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* ── INTEGRATIONS ── */}
<section className="py-24 bg-slate-900/30">
<div className="mx-auto max-w-7xl px-6 text-center">
<Badge className="mb-4 bg-emerald-500/10 text-emerald-400 border-emerald-500/20">Integrations</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl animate-fade-up">Works with your stack</h2>
<p className="mt-4 text-slate-400 max-w-xl mx-auto">First-class SDKs and integrations for every major platform.</p>
<div className="mt-12 grid grid-cols-4 sm:grid-cols-8 gap-6 stagger">
{integrations.map((tech) => (
<div
key={tech}
className="flex flex-col items-center gap-2 p-4 rounded-xl border border-slate-800 bg-slate-900/50 hover:border-emerald-500/30 hover:-translate-y-1 hover:shadow-lg transition-all duration-300"
>
<Code2 className="h-8 w-8 text-slate-500" />
<span className="text-xs text-slate-400 font-mono">{tech}</span>
</div>
))}
</div>
</div>
</section>
{/* ── PRICING ── */}
<section className="py-24 bg-slate-950">
<div className="mx-auto max-w-7xl px-6">
<div className="text-center mb-16">
<Badge className="mb-4 bg-emerald-500/10 text-emerald-400 border-emerald-500/20">Pricing</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl animate-fade-up">Simple, transparent pricing</h2>
<p className="mt-4 text-slate-400">Start free. Scale when you are ready.</p>
</div>
<div className="grid md:grid-cols-3 gap-6 max-w-5xl mx-auto stagger">
{tiers.map((tier) => (
<Card key={tier.name} className={`relative flex flex-col backdrop-blur-sm bg-card/80 hover:-translate-y-1 hover:shadow-lg transition-all duration-300 \${tier.popular ? "ring-2 ring-emerald-500 border-emerald-500/50 shadow-xl shadow-emerald-500/10" : "border-slate-800"}`}>
{tier.popular && (
<div className="absolute -top-4 left-1/2 -translate-x-1/2 bg-emerald-500 text-slate-950 px-4 py-1 rounded-full text-sm font-semibold shadow-lg">
Most Popular
</div>
)}
<CardHeader className="pb-4 pt-8">
<CardTitle className="text-xl text-white">{tier.name}</CardTitle>
<p className="text-sm text-slate-400 mt-1">{tier.desc}</p>
<div className="mt-4">
{tier.price === "Custom" ? (
<span className="text-4xl font-bold text-white">Custom</span>
) : (
<>
<span className="text-4xl font-bold text-white">\${tier.price}</span>
<span className="text-slate-500 ml-1">/mo</span>
</>
)}
</div>
<p className="text-sm text-emerald-400 mt-2 font-mono">{tier.calls}</p>
</CardHeader>
<CardContent className="flex-1 flex flex-col">
<ul className="space-y-3 flex-1">
{tier.features.map((f) => (
<li key={f} className="flex items-center gap-2 text-sm text-slate-300">
<CheckCircle2 className="h-4 w-4 text-emerald-500 flex-shrink-0" />
<span>{f}</span>
</li>
))}
</ul>
{tier.plan ? (
<Button
onClick={() => handlePlan(tier)}
disabled={checkingOut}
className={`mt-8 w-full rounded-full active:scale-[0.98] \${tier.popular ? "bg-emerald-500 hover:bg-emerald-400 text-slate-950 font-semibold" : "bg-slate-800 hover:bg-slate-700 text-white"}`}
>
{tier.cta}
</Button>
) : (
<Button asChild className="mt-8 w-full rounded-full active:scale-[0.98] bg-slate-800 hover:bg-slate-700 text-white">
<Link to="/docs">{tier.cta}</Link>
</Button>
)}
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* ── TESTIMONIALS ── */}
<section className="py-24 bg-slate-900/30">
<div className="mx-auto max-w-7xl px-6">
<div className="text-center mb-16">
<Badge className="mb-4 bg-emerald-500/10 text-emerald-400 border-emerald-500/20">Testimonials</Badge>
<h2 className="text-3xl font-bold tracking-tight sm:text-4xl animate-fade-up">Loved by developers</h2>
</div>
<div className="grid md:grid-cols-3 gap-6 stagger">
{testimonials.map((t) => (
<Card key={t.name} className="backdrop-blur-sm bg-card/80 border-slate-800 hover:border-emerald-500/20 transition-all">
<CardContent className="p-6">
<div className="flex gap-1 mb-4">
{Array.from({ length: t.stars }).map((_, i) => (
<Star key={i} className="h-4 w-4 fill-amber-400 text-amber-400" />
))}
</div>
<Quote className="h-6 w-6 text-emerald-500/30 mb-2" />
<p className="text-slate-300 text-sm leading-relaxed mb-4">{t.quote}</p>
<div className="flex items-center gap-3">
<div className="h-10 w-10 rounded-full bg-gradient-to-br from-emerald-500 to-cyan-500 flex items-center justify-center text-sm font-bold text-slate-950">
{t.name.charAt(0)}
</div>
<div>
<p className="text-sm font-semibold text-white">{t.name}</p>
<p className="text-xs text-slate-500">{t.role}</p>
</div>
</div>
</CardContent>
</Card>
))}
</div>
</div>
</section>
<Footer />
</div>
);
}