Initial commit: Next.js SaaS template

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Rami Bitar
2026-09-17 23:03:22 -04:00
co-authored by Claude Fable 5.1
commit b4d7778be2
88 changed files with 16134 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
import { Button } from '@/components/ui/button';
export function Cta() {
return (
<section className="relative mx-auto max-w-6xl overflow-hidden px-6 py-28 text-center">
<div
aria-hidden="true"
className="pointer-events-none absolute left-1/2 top-1/2 h-[300px] w-[600px] -translate-x-1/2 -translate-y-1/2 rounded-full opacity-25 blur-3xl"
style={{
background:
'conic-gradient(from 180deg at 50% 50%, #7c3aed, #2563eb, #06b6d4, #ec4899, #7c3aed)',
}}
/>
<h2 className="relative mx-auto max-w-2xl text-4xl font-semibold tracking-tight sm:text-5xl">
Ship your first project in minutes.
</h2>
<p className="relative mx-auto mt-5 max-w-xl text-lg text-white/55">
Import a repository or start from a template. No credit card required to
deploy your first preview.
</p>
<div className="relative mt-9 flex flex-col items-center justify-center gap-3 sm:flex-row">
<Button
asChild
size="lg"
className="h-11 rounded-full bg-white px-6 text-[15px] text-black hover:bg-white/90"
>
<a href="#">Start Deploying</a>
</Button>
<Button
asChild
size="lg"
variant="outline"
className="h-11 rounded-full border-white/20 bg-transparent px-6 text-[15px] text-white hover:bg-white/5 hover:text-white"
>
<a href="#">Talk to Sales</a>
</Button>
</div>
</section>
);
}
+86
View File
@@ -0,0 +1,86 @@
const features = [
{
step: '01',
title: 'Build',
description:
'Native support for 35+ frameworks. Push your code and Vertex handles the build pipeline, caching, and dependencies automatically.',
icon: <path d="M8 6L2 12l6 6M16 6l6 6-6 6" strokeWidth="1.5" fill="none" />,
},
{
step: '02',
title: 'Preview',
description:
'Every push gets a live preview URL. Share it, comment on it, and ship with confidence — no environment drift, no surprises.',
icon: (
<>
<rect
x="3"
y="4"
width="18"
height="14"
rx="2"
strokeWidth="1.5"
fill="none"
/>
<path d="M9 21h6M12 18v3" strokeWidth="1.5" fill="none" />
</>
),
},
{
step: '03',
title: 'Ship',
description:
'Deploy to a global edge network in seconds. Instant rollbacks, zero-downtime releases, and traffic that lands close to every user.',
icon: (
<path
d="M4 13l1.5-5.5A2 2 0 0 1 7.4 6h9.2a2 2 0 0 1 1.9 1.5L20 13M4 13v5h16v-5M4 13h16M8 17h.01M16 17h.01"
strokeWidth="1.5"
fill="none"
/>
),
},
];
export function Features() {
return (
<section className="mx-auto max-w-6xl px-6 py-24">
<div className="max-w-2xl">
<p className="font-mono text-xs uppercase tracking-[0.2em] text-white/40">
The workflow
</p>
<h2 className="mt-4 text-3xl font-semibold tracking-tight sm:text-4xl">
From commit to production, without the ceremony.
</h2>
</div>
<div className="mt-14 grid gap-px overflow-hidden rounded-2xl border border-white/10 bg-white/10 md:grid-cols-3">
{features.map((feature) => (
<div
key={feature.step}
className="group flex flex-col bg-black p-8 transition-colors hover:bg-white/[0.03]"
>
<div className="flex items-center justify-between">
<svg
width="28"
height="28"
viewBox="0 0 24 24"
stroke="currentColor"
className="text-white/80"
aria-hidden="true"
>
{feature.icon}
</svg>
<span className="font-mono text-xs text-white/30">
{feature.step}
</span>
</div>
<h3 className="mt-6 text-xl font-medium">{feature.title}</h3>
<p className="mt-3 text-sm leading-6 text-white/50">
{feature.description}
</p>
</div>
))}
</div>
</section>
);
}
+77
View File
@@ -0,0 +1,77 @@
import { RiGithubFill, RiTwitterXFill } from '@remixicon/react';
import { Logo } from '@/components/site/logo';
const columns = [
{
heading: 'Products',
links: ['Previews', 'Edge Network', 'Analytics', 'Storage', 'Firewall'],
},
{
heading: 'Resources',
links: ['Docs', 'Guides', 'Changelog', 'Templates', 'Status'],
},
{
heading: 'Company',
links: ['About', 'Careers', 'Blog', 'Customers', 'Contact'],
},
{
heading: 'Legal',
links: ['Privacy', 'Terms', 'Security', 'DPA', 'Cookies'],
},
];
export function Footer() {
return (
<footer className="border-t border-white/10">
<div className="mx-auto max-w-6xl px-6 py-16">
<div className="grid gap-10 md:grid-cols-[1.5fr_repeat(4,1fr)]">
<div>
<Logo />
<p className="mt-4 max-w-xs text-sm text-white/45">
The frontend cloud for teams that ship.
</p>
</div>
{columns.map((column) => (
<div key={column.heading}>
<h4 className="text-sm font-medium text-white/80">
{column.heading}
</h4>
<ul className="mt-4 space-y-3">
{column.links.map((link) => (
<li key={link}>
<a
href="#"
className="text-sm text-white/45 transition-colors hover:text-white"
>
{link}
</a>
</li>
))}
</ul>
</div>
))}
</div>
<div className="mt-14 flex flex-col items-start justify-between gap-4 border-t border-white/10 pt-8 text-sm text-white/40 sm:flex-row sm:items-center">
<span>© 2026 Vertex, Inc. All rights reserved.</span>
<div className="flex items-center gap-2">
<a
href="https://github.com"
aria-label="GitHub"
className="inline-flex size-8 items-center justify-center rounded-md text-white/45 transition-colors hover:bg-white/5 hover:text-white"
>
<RiGithubFill className="size-4" aria-hidden="true" />
</a>
<a
href="https://x.com"
aria-label="X (Twitter)"
className="inline-flex size-8 items-center justify-center rounded-md text-white/45 transition-colors hover:bg-white/5 hover:text-white"
>
<RiTwitterXFill className="size-4" aria-hidden="true" />
</a>
</div>
</div>
</div>
</footer>
);
}
+73
View File
@@ -0,0 +1,73 @@
import { Button } from '@/components/ui/button';
export function Hero() {
return (
<section className="relative overflow-hidden">
<div
aria-hidden="true"
className="pointer-events-none absolute inset-0 [mask-image:radial-gradient(ellipse_60%_50%_at_50%_0%,black,transparent)]"
style={{
backgroundImage:
'linear-gradient(to right, rgba(255,255,255,0.06) 1px, transparent 1px), linear-gradient(to bottom, rgba(255,255,255,0.06) 1px, transparent 1px)',
backgroundSize: '56px 56px',
}}
/>
<div
aria-hidden="true"
className="pointer-events-none absolute left-1/2 top-[-120px] h-[420px] w-[820px] -translate-x-1/2 rounded-full opacity-40 blur-3xl"
style={{
background:
'conic-gradient(from 180deg at 50% 50%, #7c3aed, #2563eb, #06b6d4, #ec4899, #7c3aed)',
}}
/>
<div className="relative mx-auto max-w-6xl px-6 pt-24 pb-20 text-center sm:pt-32">
<a
href="#"
className="group inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/5 px-3.5 py-1.5 text-xs text-white/70 transition-colors hover:border-white/25 hover:text-white"
>
<span className="inline-block h-1.5 w-1.5 rounded-full bg-emerald-400" />
Vertex Edge is now generally available
<span className="transition-transform group-hover:translate-x-0.5">
&rarr;
</span>
</a>
<h1 className="mx-auto mt-8 max-w-4xl bg-gradient-to-b from-white to-white/60 bg-clip-text text-5xl font-semibold leading-[1.05] tracking-tight text-transparent sm:text-7xl">
Build. Preview. Ship.
</h1>
<p className="mx-auto mt-6 max-w-2xl text-lg leading-8 text-white/55">
Vertex is the frontend cloud. Give your team the tooling and global
infrastructure to build, preview, and ship a faster web — from your
first commit to production traffic.
</p>
<div className="mt-10 flex flex-col items-center justify-center gap-3 sm:flex-row">
<Button
asChild
size="lg"
className="h-11 rounded-full bg-white px-6 text-[15px] text-black hover:bg-white/90"
>
<a href="#">Start Deploying</a>
</Button>
<Button
asChild
size="lg"
variant="outline"
className="h-11 rounded-full border-white/20 bg-transparent px-6 text-[15px] text-white hover:bg-white/5 hover:text-white"
>
<a href="#">Get a Demo</a>
</Button>
</div>
<div className="mx-auto mt-14 flex max-w-md items-center gap-3 rounded-xl border border-white/10 bg-white/[0.03] px-4 py-3 font-mono text-sm text-white/70">
<span className="text-white/30">$</span>
<span>
<span className="text-white">vertex</span> deploy --prod
</span>
<span className="ml-auto h-4 w-px animate-pulse bg-white/40" />
</div>
</div>
</section>
);
}
+85
View File
@@ -0,0 +1,85 @@
import Image from 'next/image';
import { Marquee } from '@/components/ui/marquee';
const customerLogos = [
{
name: 'Next.js',
src: 'https://sb.frontend.co/storage/v1/object/public/assets/logos/standard/nextjs-logo.svg',
width: 394,
height: 80,
},
{
name: 'OpenAI',
src: 'https://sb.frontend.co/storage/v1/object/public/assets/logos/standard/openai-logo.svg',
width: 512,
height: 126,
},
{
name: 'Stripe',
src: 'https://sb.frontend.co/storage/v1/object/public/assets/logos/standard/stripe-logo.svg',
width: 73,
height: 31,
},
{
name: 'Vercel',
src: 'https://sb.frontend.co/storage/v1/object/public/assets/logos/standard/vercel-logo.svg',
width: 2048,
height: 407,
},
{
name: 'Supabase',
src: 'https://sb.frontend.co/storage/v1/object/public/assets/logos/standard/supabase-logo.svg',
width: 581,
height: 113,
},
{
name: 'Anthropic',
src: 'https://sb.frontend.co/storage/v1/object/public/assets/logos/standard/anthropic-logo.svg',
width: 579,
height: 65,
},
{
name: 'Tailwind CSS',
src: 'https://sb.frontend.co/storage/v1/object/public/assets/logos/standard/tailwindcss-logo.svg',
width: 665,
height: 82,
},
{
name: 'Linear',
src: 'https://sb.frontend.co/storage/v1/object/public/assets/logos/standard/linear-logo.svg',
width: 122,
height: 31,
},
];
export function LogoCloud() {
return (
<section className="border-y border-white/10 bg-white/[0.02]">
<div className="mx-auto max-w-6xl px-6 py-12">
<p className="text-center text-xs font-medium uppercase tracking-[0.2em] text-white/40">
Trusted by fast-moving teams shipping to millions
</p>
<div className="relative mt-8 overflow-hidden [mask-image:linear-gradient(to_right,transparent,black_15%,black_85%,transparent)]">
<Marquee pauseOnHover className="[--duration:40s] [--gap:4rem]">
{customerLogos.map((logo) => (
<div
key={logo.name}
className="group flex h-12 items-center justify-center px-2"
>
<Image
src={logo.src}
alt={`${logo.name} logo`}
width={logo.width}
height={logo.height}
unoptimized
className="h-7 w-[120px] max-w-full object-contain opacity-40 brightness-0 invert transition-opacity duration-200 group-hover:opacity-80"
/>
</div>
))}
</Marquee>
</div>
</div>
</section>
);
}
+19
View File
@@ -0,0 +1,19 @@
import { cn } from '@/lib/utils';
export function Logo({ className }: { className?: string }) {
return (
<span className={cn('flex items-center gap-2 font-medium', className)}>
<svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
aria-hidden="true"
className="shrink-0"
>
<path d="M12 2L23 21H1L12 2Z" fill="currentColor" />
</svg>
<span className="text-[17px] tracking-tight">Vertex</span>
</span>
);
}
+45
View File
@@ -0,0 +1,45 @@
import { Logo } from '@/components/site/logo';
import { Button } from '@/components/ui/button';
const links = ['Products', 'Solutions', 'Resources', 'Docs', 'Pricing'];
export function Navbar() {
return (
<header className="sticky top-0 z-50 border-b border-white/10 bg-black/70 backdrop-blur-xl">
<nav className="mx-auto flex h-16 max-w-6xl items-center justify-between px-6">
<div className="flex items-center gap-8">
<Logo />
<ul className="hidden items-center gap-6 md:flex">
{links.map((link) => (
<li key={link}>
<a
href="#"
className="text-sm text-white/60 transition-colors hover:text-white"
>
{link}
</a>
</li>
))}
</ul>
</div>
<div className="flex items-center gap-2">
<Button
asChild
size="lg"
variant="ghost"
className="hidden text-white/70 hover:bg-white/5 hover:text-white sm:inline-flex"
>
<a href="#">Log In</a>
</Button>
<Button
asChild
size="lg"
className="rounded-full bg-white text-black hover:bg-white/90"
>
<a href="#">Sign Up</a>
</Button>
</div>
</nav>
</header>
);
}
+25
View File
@@ -0,0 +1,25 @@
const stats = [
{ value: '45ms', label: 'Median edge response, worldwide' },
{ value: '99.99%', label: 'Platform uptime over the last year' },
{ value: '35+', label: 'Frameworks supported out of the box' },
{ value: '1.2T', label: 'Requests served every month' },
];
export function Stats() {
return (
<section className="border-y border-white/10 bg-black">
<div className="mx-auto grid max-w-6xl grid-cols-2 gap-px overflow-hidden bg-white/10 lg:grid-cols-4">
{stats.map((stat) => (
<div key={stat.label} className="bg-black px-6 py-12 text-center">
<div className="text-4xl font-semibold tracking-tight sm:text-5xl">
{stat.value}
</div>
<div className="mx-auto mt-3 max-w-[16ch] text-sm text-white/45">
{stat.label}
</div>
</div>
))}
</div>
</section>
);
}