feat(marketing): add ZeroTier Network Governance page and content

Add comprehensive marketing content for ZeroTier Network Governance feature
including a dedicated landing page, navigation updates, and feature highlights
across the homepage and features page.

- Add new ZeroTierPage with feature documentation and use cases
- Add ZeroTier to navigation in MarketingLayout header and footer
- Update HomePage hero headline and add ZeroTier feature section
- Add ZeroTier features section to FeaturesPage
- Add ScrollToTop component for better navigation UX
- Move ApiDevTools to AuthenticatedLayout (dev mode only)
- Add SSR tests for marketing pages
- Update SSHCertificatesPage comparison table for clarity
- Add documentation link to MarketingLayout footer
This commit is contained in:
2026-04-06 20:57:30 +09:30
parent 3e0a7f9de4
commit 11f56c187f
8 changed files with 1215 additions and 522 deletions
+14 -4
View File
@@ -2,7 +2,8 @@ import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom";
import { useEffect } from "react";
// Layouts
import PublicLayout from "@/components/layouts/PublicLayout";
@@ -15,6 +16,7 @@ import FeaturesPage from "@/pages/marketing/FeaturesPage";
import PricingPage from "@/pages/marketing/PricingPage";
import SecurityPage from "@/pages/marketing/SecurityPage";
import SSHCertificatesPage from "@/pages/marketing/SSHCertificatesPage";
import ZeroTierPage from "@/pages/marketing/ZeroTierPage";
import DemoPage from "@/pages/marketing/DemoPage";
// Public pages
@@ -59,7 +61,6 @@ import OAuthProvidersPage from "@/pages/admin/OAuthProvidersPage";
import OrgSetupPage from "@/pages/auth/OrgSetupPage";
import NotFound from "@/pages/NotFound";
import ApiDevTools from "@/components/dev/ApiDevTools";
const queryClient = new QueryClient({
defaultOptions: {
@@ -82,12 +83,22 @@ const App = () => (
<Toaster />
<Sonner />
<BrowserRouter>
<ScrollToTop />
<AppRoutes />
</BrowserRouter>
</TooltipProvider>
</QueryClientProvider>
);
// Scroll to top on navigation
function ScrollToTop() {
const location = useLocation();
useEffect(() => {
window.scrollTo({ top: 0, left: 0, behavior: 'instant' });
}, [location.pathname]);
return null;
}
// Separate component so AuthProvider can use useNavigate
import { AuthProvider, useAuth } from "@/contexts/AuthContext";
import { OrgProvider } from "@/contexts/OrgContext";
@@ -148,6 +159,7 @@ function AppRoutes() {
<Route path="/pricing" element={<PricingPage />} />
<Route path="/security" element={<SecurityPage />} />
<Route path="/ssh-certificates" element={<SSHCertificatesPage />} />
<Route path="/zerotier" element={<ZeroTierPage />} />
<Route path="/demo" element={<DemoPage />} />
</Route>
@@ -208,8 +220,6 @@ function AppRoutes() {
<Route path="*" element={<NotFound />} />
</Routes>
{/* Dev tools - only shown in development */}
<ApiDevTools />
</OrgProvider>
</AuthProvider>
);
@@ -2,6 +2,7 @@ import { Outlet } from "react-router-dom";
import { SidebarProvider } from "@/components/ui/sidebar";
import { AppSidebar } from "@/components/navigation/AppSidebar";
import { TopBar } from "@/components/navigation/TopBar";
import ApiDevTools from "@/components/dev/ApiDevTools";
export default function AuthenticatedLayout() {
return (
@@ -15,6 +16,7 @@ export default function AuthenticatedLayout() {
</main>
</div>
</div>
{import.meta.env.DEV && <ApiDevTools />}
</SidebarProvider>
);
}
+3 -1
View File
@@ -17,6 +17,7 @@ const navigation = [
{ name: "Features", href: "/features" },
{ name: "Security", href: "/security" },
{ name: "SSH Certificates", href: "/ssh-certificates" },
{ name: "ZeroTier", href: "/zerotier" },
{ name: "Pricing", href: "/pricing" },
{ name: "Demo", href: "/demo" },
];
@@ -143,6 +144,7 @@ return (
<li><Link to="/features" className="text-sm text-muted-foreground hover:text-foreground transition-colors">Features</Link></li>
<li><Link to="/security" className="text-sm text-muted-foreground hover:text-foreground transition-colors">Security</Link></li>
<li><Link to="/ssh-certificates" className="text-sm text-muted-foreground hover:text-foreground transition-colors">SSH Certificates</Link></li>
<li><Link to="/zerotier" className="text-sm text-muted-foreground hover:text-foreground transition-colors">ZeroTier</Link></li>
<li><Link to="/pricing" className="text-sm text-muted-foreground hover:text-foreground transition-colors">Pricing</Link></li>
</ul>
</div>
@@ -152,7 +154,7 @@ return (
<h3 className="text-sm font-semibold text-foreground mb-3">Resources</h3>
<ul className="space-y-2">
<li><Link to="/demo" className="text-sm text-muted-foreground hover:text-foreground transition-colors">Demo</Link></li>
<li><a href="#" className="text-sm text-muted-foreground hover:text-foreground transition-colors">Documentation</a></li>
<li><a href="https://docs.secuird.tech/" target="_blank" rel="noopener noreferrer" className="text-sm text-muted-foreground hover:text-foreground transition-colors">Documentation</a></li>
<li><a href="#" className="text-sm text-muted-foreground hover:text-foreground transition-colors">API Reference</a></li>
<li><a href="#" className="text-sm text-muted-foreground hover:text-foreground transition-colors">Status</a></li>
</ul>
+113 -2
View File
@@ -28,6 +28,8 @@ Network,
ScanLine,
LogIn,
AppWindow,
Monitor,
Zap,
} from "lucide-react";
const authenticationFeatures = [
@@ -132,6 +134,39 @@ description: "Monitor certificate usage in real-time. Detect anomalies and suspi
},
];
const zerotierFeatures = [
{
icon: Monitor,
title: "Device Registration",
description: "Register ZeroTier nodes by Node ID. No shared secrets — users own their devices.",
},
{
icon: Users,
title: "Approval Workflows",
description: "Manager approval required before network access. Durable approvals survive across days.",
},
{
icon: Clock,
title: "Activation Sessions",
description: "Time-bounded access sessions. Re-authenticate to activate for a fixed period like an 8-hour workday.",
},
{
icon: Zap,
title: "Kill Switch",
description: "Instantly revoke all active memberships for a user across all networks. Lost laptop? Immediate response.",
},
{
icon: ShieldCheck,
title: "Complete Audit Trail",
description: "Every network access event logged. Know who accessed what, when, and from which device.",
},
{
icon: Network,
title: "Multi-Network Support",
description: "Manage production, staging, and lab networks separately with environment-based policies.",
},
];
const organizationFeatures = [
{
icon: Users,
@@ -393,8 +428,84 @@ return (
</div>
</section>
{/* ZeroTier Network Governance */}
<section id="zerotier" className="py-16 lg:py-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="grid lg:grid-cols-2 gap-12 items-center">
<div className="order-2 lg:order-1">
{/* Screenshot placeholder - replace with actual screenshot */}
<Card className="bg-card shadow-xl border-2 border-dashed border-muted-foreground/20">
<CardContent className="p-8 text-center">
<div className="flex flex-col items-center justify-center py-12 space-y-4">
<Network className="h-16 w-16 text-muted-foreground/40" />
<div className="space-y-2">
<p className="text-sm font-medium text-muted-foreground">ZeroTier Network Management</p>
<p className="text-xs text-muted-foreground/60">Screenshot placeholder — replace with:</p>
<ul className="text-xs text-muted-foreground/60 list-disc list-inside text-left">
<li>Networks list with environment tags</li>
<li>Member status and activation state</li>
<li>Pending requests and approvals</li>
</ul>
</div>
</div>
</CardContent>
</Card>
</div>
<div className="order-1 lg:order-2">
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/10 text-primary text-sm font-medium mb-4">
<Network className="h-4 w-4" />
ZeroTier Network Governance
</div>
<h2 className="text-3xl sm:text-4xl font-bold text-foreground mb-4">
Govern ZeroTier Access<br />
<span className="text-accent block mt-2">With Your Identity Platform</span>
</h2>
<p className="text-lg text-muted-foreground mb-6">
Add approval workflows, time-bounded activation sessions, and complete audit trails to your
ZeroTier networks. Stop using raw ZeroTier administration and give managers the controls they need.
</p>
<ul className="space-y-3 mb-8">
{[
"Devices registered by ZeroTier Node ID — no shared secrets",
"Manager approval separates authorization from activation",
"Activation sessions last hours, not days — automatic expiration",
"Kill switch for lost devices or immediate offboarding",
"Immutable audit trail for every network access event",
].map((item, index) => (
<li key={index} className="flex items-start gap-3">
<CheckCircle2 className="h-5 w-5 text-accent flex-shrink-0 mt-0.5" />
<span className="text-foreground">{item}</span>
</li>
))}
</ul>
<Link to="/zerotier">
<Button className="gap-2">
Learn About Network Governance
<ArrowRight className="h-4 w-4" />
</Button>
</Link>
</div>
</div>
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6 mt-12">
{zerotierFeatures.map((feature) => (
<Card key={feature.title} className="bg-card">
<CardContent className="pt-6">
<div className="h-10 w-10 rounded-lg bg-primary/10 flex items-center justify-center mb-3">
<feature.icon className="h-5 w-5 text-primary" />
</div>
<h3 className="text-base font-semibold text-foreground mb-1">{feature.title}</h3>
<p className="text-sm text-muted-foreground">{feature.description}</p>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* Organization Management */}
<section className="py-16 lg:py-24">
<section className="py-16 lg:py-24 bg-muted/30">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="grid lg:grid-cols-2 gap-12 items-center">
<div className="order-2 lg:order-1">
@@ -446,7 +557,7 @@ return (
</section>
{/* Compliance & Audit */}
<section className="py-16 lg:py-24 bg-muted/30">
<section className="py-16 lg:py-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="grid lg:grid-cols-2 gap-12 items-center">
<div>
+78 -5
View File
@@ -17,7 +17,8 @@ Clock,
ArrowRightLeft,
Eye,
Settings,
UserCheck
UserCheck,
Network
} from "lucide-react";
const features = [
@@ -45,6 +46,12 @@ title: "OIDC Provider Built-In",
description:
"Secuird acts as an OIDC identity provider for your internal applications. One identity, seamless access everywhere.",
},
{
icon: Network,
title: "ZeroTier Network Governance",
description:
"Control access to private ZeroTier networks with approval workflows, time-bounded activation sessions, and instant kill switches.",
},
];
const sshFeatures = [
@@ -74,6 +81,7 @@ const socialProviders = [
{ name: "Microsoft 365", icon: Building2 },
{ name: "Google Workspace", icon: Globe },
{ name: "GitHub", icon: Key },
{ name: "ZeroTier", icon: Network },
];
export default function HomePage() {
@@ -91,14 +99,14 @@ return (
{/* Headline */}
<h1 className="text-4xl sm:text-5xl lg:text-6xl font-bold tracking-tight text-foreground mb-6">
Enterprise Authentication,
<span className="text-primary block mt-2">Without the Enterprise Complexity</span>
Every Identity. One Platform.
<span className="text-primary block mt-2">Complete Access Control.</span>
</h1>
{/* Subheadline */}
<p className="text-lg sm:text-xl text-muted-foreground max-w-2xl mx-auto mb-8">
Secuird unifies social logins, MFA, and SSH certificate management in one platform.
Your team gets seamless access. You get complete control and auditability.
Secuird unifies Google, Microsoft, GitHub, and traditional authentication with MFA enforcement,
SSH certificates, and ZeroTier network governance all in one platform.
</p>
{/* CTA Buttons */}
@@ -225,6 +233,71 @@ return (
</div>
</section>
{/* ZeroTier Network Access Section */}
<section className="py-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="grid lg:grid-cols-2 gap-12 items-center">
<div>
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-primary/10 text-primary text-sm font-medium mb-4">
<Network className="h-4 w-4" />
ZeroTier Network Governance
</div>
<h2 className="text-3xl sm:text-4xl font-bold text-foreground mb-4">
Govern Your ZeroTier Networks<br />
<span className="text-primary">With Your Identity Platform</span>
</h2>
<p className="text-lg text-muted-foreground mb-6">
Stop managing ZeroTier access through raw administration interfaces. Secuird adds
approval workflows, time-bounded activation sessions, and complete audit trails
to your ZeroTier networks.
</p>
<ul className="space-y-3 mb-8">
{[
"Register devices by ZeroTier Node ID — no shared secrets",
"Manager approval before any network access is granted",
"Time-bounded activation sessions (e.g., 8-hour workday)",
"Instant kill switch to revoke all active memberships",
"Full audit trail of who accessed what network when",
].map((item) => (
<li key={item} className="flex items-start gap-3">
<CheckCircle2 className="h-5 w-5 text-accent flex-shrink-0 mt-0.5" />
<span className="text-foreground">{item}</span>
</li>
))}
</ul>
<Link to="/zerotier">
<Button className="gap-2">
Learn About Network Governance
<ArrowRight className="h-4 w-4" />
</Button>
</Link>
</div>
<div className="relative">
{/* Screenshot placeholder - replace with actual screenshot */}
<Card className="bg-card shadow-xl border-2 border-dashed border-muted-foreground/20">
<CardContent className="p-8 text-center">
<div className="flex flex-col items-center justify-center py-12 space-y-4">
<Network className="h-16 w-16 text-muted-foreground/40" />
<div className="space-y-2">
<p className="text-sm font-medium text-muted-foreground">ZeroTier Networks Dashboard</p>
<p className="text-xs text-muted-foreground/60">Screenshot placeholder replace with:</p>
<ul className="text-xs text-muted-foreground/60 list-disc list-inside">
<li>Networks list view</li>
<li>Device activation status</li>
<li>Member management panel</li>
</ul>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</section>
{/* How It Works */}
<section className="py-24 bg-muted/30">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
+8 -8
View File
@@ -68,14 +68,14 @@ code: "# Certificate auto-expires",
];
const comparisonFeatures = [
{ feature: "Lifetime", static: "Permanent", cert: "Minutes to hours" },
{ feature: "Rotation", static: "Manual, error-prone", cert: "Automatic" },
{ feature: "Auditability", static: "None", cert: "Full chain of custody" },
{ feature: "Revocation", static: "Distribute to all servers", cert: "Disable user" },
{ feature: "Access Control", static: "Manual key distribution", cert: "Group-based policies" },
{ feature: "Identity Link", static: "Anonymous", cert: "Verified identity" },
{ feature: "Onboarding", static: "Copy keys manually", cert: "Self-service" },
{ feature: "Offboarding", static: "Hunt and remove keys", cert: "Instant revocation" },
{ feature: "Key Lifetime", static: "Permanent — keys never expire", cert: "Minutes to hours — auto-expiration" },
{ feature: "Key Rotation", static: "Manual process, error-prone", cert: "Automatic with each certificate" },
{ feature: "Audit Trail", static: "No visibility into usage", cert: "Full chain of custody logged" },
{ feature: "Revocation", static: "Must reach all servers manually", cert: "Disable user — instant globally" },
{ feature: "Access Control", static: "Manual key distribution to servers", cert: "Group-based policies, self-service" },
{ feature: "Identity Link", static: "Anonymous — no user verification", cert: "Tied to verified corporate identity" },
{ feature: "Onboarding", static: "Admin copies keys to every server", cert: "User registers key once, self-service" },
{ feature: "Offboarding", static: "Hunt and remove keys from servers", cert: "Disable user — all certs invalidated" },
];
const useCases = [
+466
View File
@@ -0,0 +1,466 @@
import { Link } from "react-router-dom";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import {
Network,
Monitor,
Users,
Clock,
Zap,
ShieldCheck,
ArrowRight,
CheckCircle2,
ShieldAlert,
Globe,
Lock,
Key,
} from "lucide-react";
const benefits = [
{
icon: Monitor,
title: "Node ID Registration",
description: "Register ZeroTier nodes by their unique Node ID. No shared secrets — users own their devices, not the network.",
},
{
icon: Users,
title: "Approval Workflows",
description: "Manager approval required before network access. Durable approvals survive across days while maintaining security.",
},
{
icon: Clock,
title: "Time-Bounded Sessions",
description: "Activation sessions last hours, not days. Re-authenticate to activate for a fixed period like an 8-hour workday.",
},
{
icon: Zap,
title: "Instant Kill Switch",
description: "Revoke all active memberships for a user across all networks. Lost laptop? Immediate response.",
},
];
const howItWorks = [
{
step: "01",
title: "Register ZeroTier Node",
description: "Users register their ZeroTier Node ID in Secuird. This is a one-time setup — no shared secrets required.",
code: "zerotier-cli info",
},
{
step: "02",
title: "Request Network Access",
description: "When users need access to a ZeroTier network, they request access through Secuird.",
code: "Request via Secuird dashboard",
},
{
step: "03",
title: "Manager Approval",
description: "A manager reviews and approves the request. Approval is durable — it persists until explicitly revoked.",
code: "Approved in Secuird portal",
},
{
step: "04",
title: "Activate for a Session",
description: "User activates their access for a time-bounded session. When the session expires, they re-authenticate.",
code: "Session expires automatically",
},
];
const comparisonFeatures = [
{
feature: "Access Control",
traditional: "Shared secrets or public lists",
secuird: "Identity-based, approval workflows",
},
{
feature: "Session Duration",
traditional: "Permanent until manually removed",
secuird: "Hours — automatic expiration",
},
{
feature: "Revocation",
traditional: "Remove from every network manually",
secuird: "Disable user — instant global revoke",
},
{
feature: "Audit Trail",
traditional: "None",
secuird: "Complete log of all access events",
},
{
feature: "Manager Control",
traditional: "No approval workflow",
secuird: "Explicit approval before access granted",
},
{
feature: "Contractor Access",
traditional: "Share credentials, revoke later",
secuird: "Time-limited, self-service, audited",
},
];
const useCases = [
{
title: "Managed Service Providers (MSPs)",
description: "Manage access for multiple client networks without sharing credentials. Contractors come and go — maintain control with time-bounded sessions.",
features: [
"Isolate each client's network access",
"Time-limited access for contractors",
"Complete audit trail for compliance",
"Instant revocation when contracts end",
],
},
{
title: "Cloud Service Providers (CSPs)",
description: "Offer ZeroTier-based private networking to your customers with enterprise-grade access controls.",
features: [
"Multi-tenant network isolation",
"Approval workflows for sensitive networks",
"Usage auditing for billing",
"White-label options",
],
},
{
title: "Hyperscalers",
description: "Provide secure ZeroTier connectivity across distributed infrastructure with identity-based access control.",
features: [
"Scale to thousands of nodes",
"Identity-linked access everywhere",
"Automated compliance reporting",
"API-driven provisioning",
],
},
{
title: "Short-Term Contractors",
description: "Give contractors access to specific networks for specific periods. When the contract ends, access ends — automatically.",
features: [
"Hours-long activation sessions",
"No shared credentials",
"Full audit of what they accessed",
"One-click revocation",
],
},
];
const features = [
{
icon: Monitor,
title: "Node ID Registration",
description: "Register ZeroTier nodes by their unique Node ID. No shared secrets — users own their devices.",
},
{
icon: Users,
title: "Approval Workflows",
description: "Manager approval required before network access. Durable approvals survive across days.",
},
{
icon: Clock,
title: "Activation Sessions",
description: "Time-bounded access sessions. Re-authenticate to activate for a fixed period like an 8-hour workday.",
},
{
icon: Zap,
title: "Kill Switch",
description: "Instantly revoke all active memberships for a user across all networks. Lost laptop? Immediate response.",
},
{
icon: ShieldCheck,
title: "Complete Audit Trail",
description: "Every network access event logged. Know who accessed what, when, and from which device.",
},
{
icon: Network,
title: "Multi-Network Support",
description: "Manage production, staging, and lab networks separately with environment-based policies.",
},
];
export default function ZeroTierPage() {
return (
<>
{/* Hero */}
<section className="py-16 lg:py-24 bg-gradient-to-b from-background to-muted/30">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="grid lg:grid-cols-2 gap-12 items-center">
<div>
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-accent/10 text-accent text-sm font-medium mb-6">
<Network className="h-4 w-4" />
ZeroTier Network Governance
</div>
<h1 className="text-4xl sm:text-5xl font-bold tracking-tight text-foreground mb-6">
Identity-Based Access Control
<span className="text-accent block mt-2">For ZeroTier Networks</span>
</h1>
<p className="text-lg text-muted-foreground mb-8">
Stop managing ZeroTier access through raw administration interfaces. Secuird adds
approval workflows, time-bounded activation sessions, and complete audit trails
to your ZeroTier networks without requiring SSH certificates.
</p>
<div className="flex flex-col sm:flex-row gap-4">
<Link to="/register">
<Button size="lg" className="gap-2">
Start Free Trial
<ArrowRight className="h-4 w-4" />
</Button>
</Link>
<Link to="/demo">
<Button variant="outline" size="lg">
Watch Demo
</Button>
</Link>
</div>
</div>
<div className="relative">
<Card className="bg-card shadow-xl">
<CardContent className="p-8">
<div className="space-y-4">
<div className="flex items-center gap-3">
<div className="h-10 w-10 rounded-lg bg-accent/10 flex items-center justify-center">
<Network className="h-5 w-5 text-accent" />
</div>
<div>
<p className="text-sm font-medium text-foreground">Production Network</p>
<p className="text-xs text-muted-foreground">zt1abc...def</p>
</div>
<span className="ml-auto px-2 py-1 bg-success/10 text-success text-xs rounded-full">Active</span>
</div>
<div className="border-t pt-4">
<p className="text-sm text-muted-foreground mb-2">Pending Requests</p>
<div className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span>jane@contractor.io</span>
<span className="text-xs text-muted-foreground">2 hours ago</span>
</div>
<div className="flex items-center justify-between text-sm">
<span>build-server-03</span>
<span className="text-xs text-muted-foreground">5 hours ago</span>
</div>
</div>
</div>
<div className="border-t pt-4">
<p className="text-sm text-muted-foreground mb-2">Active Sessions</p>
<div className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span>john@company.com</span>
<span className="text-xs text-accent">Expires in 4h 23m</span>
</div>
</div>
</div>
</div>
</CardContent>
</Card>
</div>
</div>
</div>
</section>
{/* Not Tied to SSH */}
<section className="py-12 bg-muted/30">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="bg-accent/5 border border-accent/20 rounded-lg p-6">
<div className="flex items-start gap-4">
<ShieldAlert className="h-6 w-6 text-accent flex-shrink-0 mt-1" />
<div>
<h3 className="font-semibold text-foreground mb-1">Independent of SSH Certificates</h3>
<p className="text-sm text-muted-foreground">
ZeroTier Network Governance works completely independently of SSH Certificate Authority.
Use it on its own to control ZeroTier network access, or combine it with SSH certificates
for comprehensive infrastructure access control. Two powerful features, one unified platform.
</p>
</div>
</div>
</div>
</div>
</section>
{/* Benefits */}
<section className="py-16 lg:py-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold text-foreground mb-4">
Why ZeroTier Governance?
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Traditional ZeroTier management relies on shared secrets and manual administration.
Secuird brings identity-based access control to ZeroTier.
</p>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
{benefits.map((benefit) => (
<Card key={benefit.title} className="bg-card">
<CardContent className="pt-6">
<div className="h-12 w-12 rounded-lg bg-accent/10 flex items-center justify-center mb-4">
<benefit.icon className="h-6 w-6 text-accent" />
</div>
<h3 className="text-lg font-semibold text-foreground mb-2">{benefit.title}</h3>
<p className="text-sm text-muted-foreground">{benefit.description}</p>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* How It Works */}
<section className="py-16 lg:py-24 bg-muted/30">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold text-foreground mb-4">
How It Works
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Simple four-step process from registration to time-bounded access.
</p>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
{howItWorks.map((step) => (
<Card key={step.step} className="bg-card">
<CardContent className="pt-6">
<div className="text-5xl font-bold text-primary/10 mb-2">{step.step}</div>
<h3 className="text-lg font-semibold text-foreground mb-2">{step.title}</h3>
<p className="text-sm text-muted-foreground mb-4">{step.description}</p>
<pre className="p-2 bg-muted rounded text-xs font-mono text-muted-foreground overflow-x-auto">
<code>{step.code}</code>
</pre>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* Traditional vs Secuird */}
<section className="py-16 lg:py-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold text-foreground mb-4">
Traditional vs. Secuird-Governed ZeroTier
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
See the difference identity-based access control makes.
</p>
</div>
<Card className="overflow-hidden">
<CardContent className="p-0">
<div className="overflow-x-auto">
<table className="w-full">
<thead>
<tr className="border-b bg-muted/50">
<th className="px-6 py-4 text-left text-sm font-semibold text-foreground">Feature</th>
<th className="px-6 py-4 text-center text-sm font-semibold text-destructive">Traditional ZeroTier</th>
<th className="px-6 py-4 text-center text-sm font-semibold text-accent bg-accent/5">Secuird-Governed</th>
</tr>
</thead>
<tbody className="divide-y">
{comparisonFeatures.map((row) => (
<tr key={row.feature} className="hover:bg-muted/30">
<td className="px-6 py-4 text-sm font-medium text-foreground">{row.feature}</td>
<td className="px-6 py-4 text-sm text-center text-destructive/80">{row.traditional}</td>
<td className="px-6 py-4 text-sm text-center text-accent bg-accent/5 font-medium">{row.secuird}</td>
</tr>
))}
</tbody>
</table>
</div>
</CardContent>
</Card>
</div>
</section>
{/* Use Cases */}
<section className="py-16 lg:py-24 bg-muted/30">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold text-foreground mb-4">
Use Cases
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Perfect for organizations managing access to ZeroTier networks at scale.
</p>
</div>
<div className="grid md:grid-cols-2 gap-6">
{useCases.map((useCase) => (
<Card key={useCase.title} className="bg-card">
<CardContent className="pt-6">
<h3 className="text-lg font-semibold text-foreground mb-2">{useCase.title}</h3>
<p className="text-sm text-muted-foreground mb-4">{useCase.description}</p>
<ul className="space-y-2">
{useCase.features.map((feature) => (
<li key={feature} className="flex items-center gap-2 text-sm text-foreground">
<CheckCircle2 className="h-4 w-4 text-accent" />
{feature}
</li>
))}
</ul>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* Features Deep Dive */}
<section className="py-16 lg:py-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h2 className="text-3xl font-bold text-foreground mb-4">
Powerful Features
</h2>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
Everything you need to manage ZeroTier network access at scale.
</p>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{features.map((feature) => (
<Card key={feature.title} className="bg-card">
<CardContent className="pt-6">
<div className="h-10 w-10 rounded-lg bg-primary/10 flex items-center justify-center mb-3">
<feature.icon className="h-5 w-5 text-primary" />
</div>
<h3 className="text-base font-semibold text-foreground mb-1">{feature.title}</h3>
<p className="text-sm text-muted-foreground">{feature.description}</p>
</CardContent>
</Card>
))}
</div>
</div>
</section>
{/* CTA */}
<section className="py-16 lg:py-24">
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<Card className="bg-gradient-to-br from-primary to-primary/80 border-0 overflow-hidden relative">
<div className="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAiIGhlaWdodD0iNjAiIHZpZXdCb3g9IjAgMCA2MCA2MCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxnIGZpbGw9IiNmZmYiIGZpbGwtb3BhY2l0eT0iMC4wNSI+PHBhdGggZD0iTTM2IDM0djItSDI0djJoMTJ6Ii8+PC9nPjwvZz48L3N2Zz4=')] opacity-50" />
<CardContent className="p-12 text-center relative">
<h2 className="text-3xl sm:text-4xl font-bold text-primary-foreground mb-4">
Ready to Govern Your ZeroTier Networks?
</h2>
<p className="text-lg text-primary-foreground/80 max-w-2xl mx-auto mb-8">
Start your free trial today. No credit card required. Set up your first network governance policy in minutes.
</p>
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
<Link to="/register">
<Button size="lg" variant="secondary" className="gap-2 bg-white text-primary hover:bg-white/90 font-semibold">
Start Free Trial
<ArrowRight className="h-4 w-4" />
</Button>
</Link>
<Link to="/demo">
<Button size="lg" className="bg-transparent border-2 border-white text-white hover:bg-white/15 font-semibold">
Watch Demo
</Button>
</Link>
</div>
</CardContent>
</Card>
</div>
</section>
</>
);
}
@@ -0,0 +1,29 @@
import React from "react";
import { renderToString } from "react-dom/server";
import { MemoryRouter } from "react-router-dom";
import HomePage from "../HomePage";
import FeaturesPage from "../FeaturesPage";
// Basic SSR tests to verify marketing page content renders as expected.
// We SSR the components to a string and assert presence of key headlines/texts.
describe("Marketing Pages SSR", () => {
test("HomePage renders main hero headline", () => {
const html = renderToString(
React.createElement(MemoryRouter, null, React.createElement(HomePage))
);
expect(html).toContain("Every Identity. One Platform.");
// Ensure subheading is also present
expect(html).toContain("Secuird unifies Google, Microsoft, GitHub");
});
test("FeaturesPage renders hero section title", () => {
const html = renderToString(
React.createElement(MemoryRouter, null, React.createElement(FeaturesPage))
);
// The hero section uses a combined heading with a span; test for the main line.
expect(html).toContain("Everything You Need for Enterprise Identity");
// Also verify the badge text is present
expect(html).toContain("Complete Feature Set");
});
});