+
{stats.map((stat) => (
+
);
}
diff --git a/components/sections/stats/stats-globe.tsx b/components/sections/stats/stats-globe.tsx
new file mode 100644
index 0000000..02b92c2
--- /dev/null
+++ b/components/sections/stats/stats-globe.tsx
@@ -0,0 +1,67 @@
+'use client';
+
+import { type COBEOptions } from 'cobe';
+import { useTheme } from 'next-themes';
+
+import { Globe } from '@/components/ui/globe';
+
+// Rotation per frame. Default globe is 0.005; lower is slower, 0 stops it.
+const GLOBE_SPEED = 0.003;
+
+const markers: COBEOptions['markers'] = [
+ { location: [37.7749, -122.4194], size: 0.08 },
+ { location: [40.7128, -74.006], size: 0.06 },
+ { location: [51.5072, -0.1276], size: 0.07 },
+ { location: [48.8566, 2.3522], size: 0.05 },
+ { location: [1.3521, 103.8198], size: 0.08 },
+ { location: [35.6762, 139.6503], size: 0.06 },
+ { location: [-33.8688, 151.2093], size: 0.05 },
+ { location: [-23.5505, -46.6333], size: 0.06 },
+];
+
+const darkGlobeConfig: COBEOptions = {
+ width: 800,
+ height: 800,
+ onRender: () => {},
+ devicePixelRatio: 2,
+ phi: 0,
+ theta: 0.22,
+ dark: 1,
+ diffuse: 1.2,
+ mapSamples: 20000,
+ mapBrightness: 5,
+ baseColor: [0.22, 0.22, 0.22],
+ markerColor: [1, 1, 1],
+ glowColor: [0.1, 0.1, 0.1],
+ markers,
+};
+
+const lightGlobeConfig: COBEOptions = {
+ ...darkGlobeConfig,
+ dark: 0,
+ diffuse: 0.4,
+ mapBrightness: 1.2,
+ baseColor: [0.88, 0.88, 0.88],
+ markerColor: [0.1, 0.1, 0.1],
+ glowColor: [0.96, 0.96, 0.96],
+};
+
+export function StatsGlobe() {
+ const { resolvedTheme } = useTheme();
+
+ return (
+
+ );
+}
diff --git a/components/shared/action-buttons.tsx b/components/shared/action-buttons.tsx
new file mode 100644
index 0000000..6b691d8
--- /dev/null
+++ b/components/shared/action-buttons.tsx
@@ -0,0 +1,41 @@
+import { Button } from '@/components/ui/button';
+import { cn } from '@/lib/utils';
+
+type Action = { label: string; href: string };
+
+export function ActionButtons({
+ primary,
+ secondary,
+ className,
+}: {
+ primary: Action;
+ secondary?: Action;
+ className?: string;
+}) {
+ return (
+
+ );
+}
diff --git a/components/site/logo.tsx b/components/shared/brand.tsx
similarity index 67%
rename from components/site/logo.tsx
rename to components/shared/brand.tsx
index 9a57975..d0de2a8 100644
--- a/components/site/logo.tsx
+++ b/components/shared/brand.tsx
@@ -1,6 +1,7 @@
import { cn } from '@/lib/utils';
+import { siteConfig } from '@/lib/site';
-export function Logo({ className }: { className?: string }) {
+export function Brand({ className }: { className?: string }) {
return (
- Vertex
+ {siteConfig.name}
);
}
diff --git a/components/shared/container.tsx b/components/shared/container.tsx
new file mode 100644
index 0000000..6fd73ce
--- /dev/null
+++ b/components/shared/container.tsx
@@ -0,0 +1,9 @@
+import { type ComponentProps } from 'react';
+
+import { cn } from '@/lib/utils';
+
+export function Container({ className, ...props }: ComponentProps<'div'>) {
+ return (
+
+ );
+}
diff --git a/components/shared/gradient-glow.tsx b/components/shared/gradient-glow.tsx
new file mode 100644
index 0000000..8fd173d
--- /dev/null
+++ b/components/shared/gradient-glow.tsx
@@ -0,0 +1,21 @@
+import { cn } from '@/lib/utils';
+
+/**
+ * Soft conic-gradient bloom used behind hero and CTA copy.
+ * Position and size it with `className`; it never captures pointer events.
+ */
+export function GradientGlow({ className }: { className?: string }) {
+ return (
+
+ );
+}
diff --git a/components/shared/section-heading.tsx b/components/shared/section-heading.tsx
new file mode 100644
index 0000000..aca4dcb
--- /dev/null
+++ b/components/shared/section-heading.tsx
@@ -0,0 +1,44 @@
+import { cn } from '@/lib/utils';
+
+export function SectionHeading({
+ eyebrow,
+ title,
+ description,
+ align = 'left',
+ className,
+}: {
+ eyebrow?: string;
+ title: string;
+ description?: string;
+ align?: 'left' | 'center';
+ className?: string;
+}) {
+ return (
+
+ {eyebrow && (
+
+ {eyebrow}
+
+ )}
+
+ {title}
+
+ {description && (
+
+ {description}
+
+ )}
+
+ );
+}
diff --git a/components/site/cta.tsx b/components/site/cta.tsx
deleted file mode 100644
index f2d235b..0000000
--- a/components/site/cta.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import { Button } from '@/components/ui/button';
-
-export function Cta() {
- return (
-
-
-
- Ship your first project in minutes.
-
-
- Import a repository or start from a template. No credit card required to
- deploy your first preview.
-
-
-
- );
-}
diff --git a/components/site/features.tsx b/components/site/features.tsx
deleted file mode 100644
index e6724b6..0000000
--- a/components/site/features.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-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:
,
- },
- {
- 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: (
- <>
-
-
- >
- ),
- },
- {
- 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: (
-
- ),
- },
-];
-
-export function Features() {
- return (
-
-
-
- The workflow
-
-
- From commit to production, without the ceremony.
-
-
-
-
- {features.map((feature) => (
-
-
-
- {feature.icon}
-
-
- {feature.step}
-
-
-
{feature.title}
-
- {feature.description}
-
-
- ))}
-
-
- );
-}
diff --git a/components/site/footer.tsx b/components/site/footer.tsx
deleted file mode 100644
index 4b93982..0000000
--- a/components/site/footer.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-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 (
-
-
-
-
-
-
- The frontend cloud for teams that ship.
-
-
- {columns.map((column) => (
-
-
- {column.heading}
-
-
- {column.links.map((link) => (
-
-
- {link}
-
-
- ))}
-
-
- ))}
-
-
-
© 2026 Vertex, Inc. All rights reserved.
-
-
-
-
- );
-}
diff --git a/components/site/hero.tsx b/components/site/hero.tsx
deleted file mode 100644
index fffdb54..0000000
--- a/components/site/hero.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { Button } from '@/components/ui/button';
-
-export function Hero() {
- return (
-
-
-
-
-
-
-
- Vertex Edge is now generally available
-
- →
-
-
-
-
- Build. Preview. Ship.
-
-
- 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.
-
-
-
-
-
- $
-
- vertex deploy --prod
-
-
-
-
-
- );
-}
diff --git a/components/site/navbar.tsx b/components/site/navbar.tsx
deleted file mode 100644
index 8069618..0000000
--- a/components/site/navbar.tsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import { Logo } from '@/components/site/logo';
-import { MobileNavigation } from '@/components/site/mobile-navigation';
-import { Button } from '@/components/ui/button';
-
-const navigationItems = [
- { label: 'Products', href: '#', description: 'Everything you need to ship' },
- { label: 'Solutions', href: '#', description: 'Built for teams of every size' },
- { label: 'Resources', href: '#', description: 'Guides, templates, and changelog' },
- { label: 'Docs', href: '#', description: 'Your first deploy starts here' },
- { label: 'Pricing', href: '#', description: 'Start free. Scale at your pace.' },
-];
-
-export function Navbar() {
- return (
-
-
-
-
-
- {navigationItems.map(({ label, href }) => (
-
-
- {label}
-
-
- ))}
-
-
-
-
-
- );
-}
diff --git a/components/site/stats-globe.tsx b/components/site/stats-globe.tsx
deleted file mode 100644
index 3284f50..0000000
--- a/components/site/stats-globe.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-'use client';
-
-import { type COBEOptions } from 'cobe';
-
-import { Globe } from '@/components/ui/globe';
-
-// Rotation per frame. Default globe is 0.005; lower is slower, 0 stops it.
-const GLOBE_SPEED = 0.003;
-
-const globeConfig: COBEOptions = {
- width: 800,
- height: 800,
- onRender: () => {},
- devicePixelRatio: 2,
- phi: 0,
- theta: 0.22,
- dark: 1,
- diffuse: 1.2,
- mapSamples: 20000,
- mapBrightness: 5,
- baseColor: [0.22, 0.22, 0.22],
- markerColor: [1, 1, 1],
- glowColor: [0.1, 0.1, 0.1],
- markers: [
- { location: [37.7749, -122.4194], size: 0.08 },
- { location: [40.7128, -74.006], size: 0.06 },
- { location: [51.5072, -0.1276], size: 0.07 },
- { location: [48.8566, 2.3522], size: 0.05 },
- { location: [1.3521, 103.8198], size: 0.08 },
- { location: [35.6762, 139.6503], size: 0.06 },
- { location: [-33.8688, 151.2093], size: 0.05 },
- { location: [-23.5505, -46.6333], size: 0.06 },
- ],
-};
-
-export function StatsGlobe() {
- return (
-
- );
-}
diff --git a/lib/site.ts b/lib/site.ts
new file mode 100644
index 0000000..e00759d
--- /dev/null
+++ b/lib/site.ts
@@ -0,0 +1,53 @@
+export const siteConfig = {
+ name: 'Vertex',
+ title: 'Vertex — Build. Preview. Ship.',
+ description:
+ 'Vertex gives frontend teams the tooling and cloud infrastructure to build, preview, and ship a faster web.',
+ tagline: 'The frontend cloud for teams that ship.',
+ links: {
+ github: 'https://github.com',
+ twitter: 'https://x.com',
+ login: '#',
+ signup: '#',
+ },
+};
+
+export type NavigationItem = {
+ label: string;
+ href: string;
+ description: string;
+};
+
+export const navigationItems: NavigationItem[] = [
+ { label: 'Products', href: '#', description: 'Everything you need to ship' },
+ { label: 'Solutions', href: '#', description: 'Built for teams of every size' },
+ { label: 'Resources', href: '#', description: 'Guides, templates, and changelog' },
+ { label: 'Docs', href: '#', description: 'Your first deploy starts here' },
+ { label: 'Pricing', href: '#', description: 'Start free. Scale at your pace.' },
+];
+
+export type FooterColumn = {
+ heading: string;
+ links: { label: string; href: string }[];
+};
+
+const link = (label: string, href = '#') => ({ label, href });
+
+export const footerColumns: FooterColumn[] = [
+ {
+ heading: 'Products',
+ links: ['Previews', 'Edge Network', 'Analytics', 'Storage', 'Firewall'].map((l) => link(l)),
+ },
+ {
+ heading: 'Resources',
+ links: ['Docs', 'Guides', 'Changelog', 'Templates', 'Status'].map((l) => link(l)),
+ },
+ {
+ heading: 'Company',
+ links: ['About', 'Careers', 'Blog', 'Customers', 'Contact'].map((l) => link(l)),
+ },
+ {
+ heading: 'Legal',
+ links: ['Privacy', 'Terms', 'Security', 'DPA', 'Cookies'].map((l) => link(l)),
+ },
+];