landing page revamp

This commit is contained in:
marko-kraemer 2025-09-04 00:23:39 -07:00
parent f73d0f5db6
commit cbdff6deaa
8 changed files with 627 additions and 50 deletions

View File

@ -18,6 +18,7 @@ import { QuoteSection } from '@/components/home/sections/quote-section';
import { TestimonialSection } from '@/components/home/sections/testimonial-section';
import { FAQSection } from '@/components/home/sections/faq-section';
import { AgentShowcaseSection } from '@/components/home/sections/agent-showcase-section';
import { DeliverablesSection } from '@/components/home/sections/deliverables-section';
export default function Home() {
return (
@ -27,7 +28,9 @@ export default function Home() {
<main className="flex flex-col items-center justify-center min-h-screen w-full">
<div className="w-full divide-y divide-border">
<HeroSection />
<DeliverablesSection />
<BentoSection />
{/* <AgentShowcaseSection /> */}
<OpenSourceSection />
<PricingSection />

View File

@ -32,6 +32,9 @@ export function SecondBentoAnimation() {
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://upload.wikimedia.org/wikipedia/commons/3/34/Microsoft_Office_Excel_%282019%E2%80%93present%29.svg" alt="Excel" className="size-8" />
</div>
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://upload.wikimedia.org/wikipedia/commons/7/7e/Gmail_icon_%282020%29.svg" alt="Gmail" className="size-8" />
</div>
</OrbitingCircles>
<OrbitingCircles index={1} iconSize={60} speed={0.5}>
@ -39,10 +42,16 @@ export function SecondBentoAnimation() {
<img src="https://upload.wikimedia.org/wikipedia/commons/a/a5/Google_Calendar_icon_%282020%29.svg" alt="Google Calendar" className="size-8" />
</div>
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://upload.wikimedia.org/wikipedia/commons/7/7e/Gmail_icon_%282020%29.svg" alt="Gmail" className="size-8" />
<img src="https://upload.wikimedia.org/wikipedia/commons/4/45/Notion_app_logo.png" alt="Notion" className="size-8" />
</div>
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://upload.wikimedia.org/wikipedia/commons/4/45/Notion_app_logo.png" alt="Notion" className="size-8" />
<img src="https://upload.wikimedia.org/wikipedia/commons/6/6b/WhatsApp.svg" alt="WhatsApp" className="size-8" />
</div>
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://upload.wikimedia.org/wikipedia/commons/a/ab/Logo_TV_2015.svg" alt="Trello" className="size-8" />
</div>
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://upload.wikimedia.org/wikipedia/commons/0/05/Google_Sheets_icon_%282020%29.svg" alt="Google Sheets" className="size-8" />
</div>
</OrbitingCircles>
@ -62,6 +71,48 @@ export function SecondBentoAnimation() {
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://cdn.worldvectorlogo.com/logos/asana-logo.svg" alt="Asana" className="size-8" />
</div>
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://upload.wikimedia.org/wikipedia/commons/c/c9/Microsoft_Office_Teams_%282018%E2%80%93present%29.svg" alt="Teams" className="size-8" />
</div>
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Mail_%28iOS%29.svg/1024px-Mail_%28iOS%29.svg.png" alt="Apple Mail" className="size-8" />
</div>
<div className="size-12 bg-white rounded-full flex items-center justify-center shadow-lg border border-gray-100">
<img src="https://upload.wikimedia.org/wikipedia/commons/c/ca/LinkedIn_logo_initials.png" alt="LinkedIn" className="size-8" />
</div>
</OrbitingCircles>
{/* Additional outer ring for more tools */}
<OrbitingCircles
index={3}
iconSize={50}
radius={320}
speed={0.3}
>
<div className="size-10 bg-white rounded-full flex items-center justify-center shadow-md border border-gray-100 opacity-75">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e1/Google_Chrome_icon_%28February_2022%29.svg/480px-Google_Chrome_icon_%28February_2022%29.svg.png" alt="Chrome" className="size-6" />
</div>
<div className="size-10 bg-white rounded-full flex items-center justify-center shadow-md border border-gray-100 opacity-75">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/5f/Twitter_bird_logo_2012.svg/512px-Twitter_bird_logo_2012.svg.png" alt="Twitter" className="size-6" />
</div>
<div className="size-10 bg-white rounded-full flex items-center justify-center shadow-md border border-gray-100 opacity-75">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a5/Instagram_icon.png/600px-Instagram_icon.png" alt="Instagram" className="size-6" />
</div>
<div className="size-10 bg-white rounded-full flex items-center justify-center shadow-md border border-gray-100 opacity-75">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/05/Facebook_Logo_%282019%29.png/600px-Facebook_Logo_%282019%29.png" alt="Facebook" className="size-6" />
</div>
<div className="size-10 bg-white rounded-full flex items-center justify-center shadow-md border border-gray-100 opacity-75">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/Zoom_Icon.png/600px-Zoom_Icon.png" alt="Zoom" className="size-6" />
</div>
<div className="size-10 bg-white rounded-full flex items-center justify-center shadow-md border border-gray-100 opacity-75">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/7/78/Dropbox_Icon.svg/480px-Dropbox_Icon.svg.png" alt="Dropbox" className="size-6" />
</div>
<div className="size-10 bg-white rounded-full flex items-center justify-center shadow-md border border-gray-100 opacity-75">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/GitHub_Invertocat_Logo.svg/480px-GitHub_Invertocat_Logo.svg.png" alt="GitHub" className="size-6" />
</div>
<div className="size-10 bg-white rounded-full flex items-center justify-center shadow-md border border-gray-100 opacity-75">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/04/ChatGPT_logo.svg/480px-ChatGPT_logo.svg.png" alt="OpenAI" className="size-6" />
</div>
</OrbitingCircles>
</div>
</div>

View File

@ -9,21 +9,21 @@ export function BentoSection() {
{
id: 1,
content: <FirstBentoAnimation />,
title: 'Design with conversation',
title: 'Describe your needs',
description:
'Simply describe what you need your agent to accomplish, and Suna will build it for you.',
'Tell Kortix what you need and customize your AI worker for your use cases.',
},
{
id: 2,
content: <SecondBentoAnimation />,
title: 'Integrate everything',
title: 'Connect 100s of tools',
description:
'Connect to your favorite tools and services with our extensive library of integrations.',
},
{
id: 3,
content: <ThirdBentoAnimation />,
title: 'Automate intelligently',
title: 'Deploy and personalize',
description:
'Watch your agent handle complex tasks and workflows with advanced AI reasoning.',
},
@ -38,10 +38,10 @@ export function BentoSection() {
<div className="max-w-6xl mx-auto border-l border-r border-border">
<SectionHeader>
<h2 className="text-3xl md:text-4xl font-medium tracking-tighter text-center text-balance pb-1">
Build Your AI Worker in 3 Simple Steps
Create a New AI Worker in 3 Simple Steps
</h2>
<p className="text-muted-foreground text-center text-balance font-medium">
From description to deployment, create powerful AI Workers that work autonomously in minutes.
Customize powerful AI Workers to work on your tailored use cases.
</p>
</SectionHeader>

View File

@ -0,0 +1,421 @@
'use client';
import { useState, useEffect, useRef } from 'react';
import { motion, AnimatePresence, useScroll, useInView } from 'framer-motion';
interface DeliverableType {
type: string;
description: string;
preview: React.ReactNode;
}
const deliverables: DeliverableType[] = [
{
type: 'Presentations',
description: 'Create comprehensive, professional presentations with detailed research, compelling visuals, and strategic insights. From pitch decks to quarterly reports, our AI delivers presentation-ready content that impresses stakeholders and drives decisions.',
preview: (
<div className="w-full h-full bg-gradient-to-br from-red-50 to-pink-50 dark:from-red-950/20 dark:to-pink-950/20 rounded-2xl p-6 border border-red-200/50 dark:border-red-800/50 shadow-2xl">
<div className="grid grid-cols-2 gap-6 h-full">
{/* Left Column */}
<div className="space-y-4">
<div>
<h3 className="font-semibold text-sm mb-2 text-foreground">Phase 5: Pipeline Management</h3>
<ul className="space-y-1 text-xs text-muted-foreground">
<li> Update candidate status in real-time</li>
<li> Manage follow-up sequences</li>
<li> Track progression through hiring stages</li>
</ul>
</div>
<div>
<h3 className="font-semibold text-sm mb-2 text-foreground">Phase 6: Analytics & Reporting</h3>
<ul className="space-y-1 text-xs text-muted-foreground">
<li> Generate comprehensive weekly reports</li>
<li> Create data visualizations and charts</li>
<li> Provide strategic recommendations</li>
</ul>
</div>
<div className="bg-card/50 rounded-lg p-3 border border-border/50">
<h4 className="font-semibold text-xs mb-1 text-foreground">Automation Schedule</h4>
<p className="text-xs text-muted-foreground">Every Monday at 9:00 AM, your agent will automatically process new job positions.</p>
</div>
</div>
{/* Right Column */}
<div className="space-y-4">
<div className="bg-primary/5 rounded-lg p-4 border border-primary/20">
<h3 className="font-semibold text-sm mb-2 text-primary">Seed VC Associate Recruitment Campaign - COMPLETE</h3>
<p className="text-xs text-muted-foreground mb-3">I've successfully completed a comprehensive recruitment campaign for the Seed VC Associate position at Founders Future.</p>
<div className="space-y-2">
<h4 className="font-medium text-xs text-foreground">📊 FINAL DELIVERABLES:</h4>
<ul className="text-xs text-muted-foreground space-y-1">
<li><strong>1. Candidate Pipeline:</strong> 15 high-quality candidates identified and scored</li>
<li className="ml-4"> Top Tier (9-10/10): 3 exceptional candidates</li>
<li className="ml-4"> Strong Tier (7-8/10): 7 very good candidates</li>
<li className="ml-4"> Good Tier (5-6/10): 5 solid candidates</li>
<li><strong>2. Comprehensive Google Sheet:</strong> Live Candidate Database</li>
<li><strong>3. Strategic Insights & Recommendations</strong></li>
</ul>
</div>
</div>
<div className="bg-secondary/5 rounded-lg p-3 border border-secondary/20">
<h4 className="font-medium text-xs mb-2 text-secondary">🎯 TOP 3 CANDIDATES TO PRIORITIZE</h4>
<p className="text-xs text-muted-foreground">Market Analysis, Compensation Insights, Sourcing Strategy recommendations included.</p>
</div>
</div>
</div>
</div>
),
},
{
type: 'Spreadsheets',
description: 'Transform raw data into actionable insights with advanced spreadsheet analysis, automated calculations, and dynamic reporting. Our AI creates sophisticated data models that track performance, identify trends, and support strategic decision-making.',
preview: (
<div className="w-full h-full bg-gradient-to-br from-green-50 to-emerald-50 dark:from-green-950/20 dark:to-emerald-950/20 rounded-2xl p-6 border border-green-200/50 dark:border-green-800/50 shadow-2xl">
<div className="h-full">
<div className="grid grid-cols-6 gap-1 h-full">
<div className="space-y-1">
<div className="h-6 bg-green-200 dark:bg-green-800 rounded text-xs flex items-center justify-center font-semibold">Name</div>
{Array.from({ length: 12 }).map((_, i) => (
<div key={i} className="h-4 bg-green-100 dark:bg-green-900/50 rounded text-xs flex items-center px-1">
Candidate {i + 1}
</div>
))}
</div>
<div className="space-y-1">
<div className="h-6 bg-green-200 dark:bg-green-800 rounded text-xs flex items-center justify-center font-semibold">Score</div>
{[9.2, 8.8, 8.5, 8.3, 7.9, 7.7, 7.5, 7.2, 6.9, 6.5, 6.2, 6.0].map((score, i) => (
<div key={i} className="h-4 bg-green-100 dark:bg-green-900/50 rounded text-xs flex items-center justify-center">
{score}
</div>
))}
</div>
<div className="space-y-1">
<div className="h-6 bg-green-200 dark:bg-green-800 rounded text-xs flex items-center justify-center font-semibold">Experience</div>
{['5-7y', '4-6y', '6-8y', '3-5y', '4-7y', '5-6y', '3-4y', '2-4y', '4-5y', '3-6y', '2-3y', '1-3y'].map((exp, i) => (
<div key={i} className="h-4 bg-green-100 dark:bg-green-900/50 rounded text-xs flex items-center justify-center">
{exp}
</div>
))}
</div>
<div className="space-y-1">
<div className="h-6 bg-green-200 dark:bg-green-800 rounded text-xs flex items-center justify-center font-semibold">Location</div>
{['SF', 'NYC', 'LA', 'SF', 'NYC', 'Austin', 'SF', 'Seattle', 'NYC', 'Boston', 'SF', 'LA'].map((loc, i) => (
<div key={i} className="h-4 bg-green-100 dark:bg-green-900/50 rounded text-xs flex items-center justify-center">
{loc}
</div>
))}
</div>
<div className="space-y-1">
<div className="h-6 bg-green-200 dark:bg-green-800 rounded text-xs flex items-center justify-center font-semibold">Status</div>
{['Contacted', 'Interview', 'Pending', 'Contacted', 'New', 'Interview', 'Contacted', 'New', 'Pending', 'New', 'Contacted', 'New'].map((status, i) => (
<div key={i} className={`h-4 rounded text-xs flex items-center justify-center ${
status === 'Interview' ? 'bg-yellow-200 dark:bg-yellow-800' :
status === 'Contacted' ? 'bg-blue-200 dark:bg-blue-800' :
status === 'Pending' ? 'bg-orange-200 dark:bg-orange-800' :
'bg-gray-200 dark:bg-gray-800'
}`}>
{status}
</div>
))}
</div>
<div className="space-y-1">
<div className="h-6 bg-green-200 dark:bg-green-800 rounded text-xs flex items-center justify-center font-semibold">Notes</div>
{Array.from({ length: 12 }).map((_, i) => (
<div key={i} className="h-4 bg-green-100 dark:bg-green-900/50 rounded text-xs flex items-center px-1">
Notes...
</div>
))}
</div>
</div>
</div>
</div>
),
},
{
type: 'Design',
description: 'Generate stunning visual designs, wireframes, and mockups that capture your brand vision. From user interface designs to marketing materials, our AI creates cohesive visual assets that engage audiences and communicate effectively.',
preview: (
<div className="w-full h-full bg-gradient-to-br from-purple-50 to-violet-50 dark:from-purple-950/20 dark:to-violet-950/20 rounded-2xl p-6 border border-purple-200/50 dark:border-purple-800/50 shadow-2xl flex items-center justify-center">
<div className="relative w-full max-w-sm h-80 bg-card rounded-xl shadow-lg border border-border p-4">
<div className="absolute top-4 left-4 w-16 h-4 bg-purple-200 dark:bg-purple-800 rounded"></div>
<div className="absolute top-10 left-4 w-24 h-2 bg-purple-100 dark:bg-purple-900 rounded"></div>
<div className="absolute top-20 left-4 right-4 h-32 bg-gradient-to-br from-purple-100 to-violet-100 dark:from-purple-900/50 dark:to-violet-900/50 rounded-lg border border-purple-200 dark:border-purple-800 flex items-center justify-center">
<div className="text-center">
<div className="w-12 h-12 bg-purple-300 dark:bg-purple-700 rounded-full mx-auto mb-2"></div>
<div className="w-20 h-2 bg-purple-200 dark:bg-purple-800 rounded mx-auto"></div>
</div>
</div>
<div className="absolute bottom-16 left-4 right-4 space-y-2">
<div className="h-2 bg-purple-100 dark:bg-purple-900 rounded w-full"></div>
<div className="h-2 bg-purple-100 dark:bg-purple-900 rounded w-3/4"></div>
<div className="h-2 bg-purple-100 dark:bg-purple-900 rounded w-5/6"></div>
</div>
<div className="absolute bottom-4 right-4 w-16 h-8 bg-purple-500 dark:bg-purple-600 rounded text-white text-xs flex items-center justify-center">
CTA
</div>
</div>
</div>
),
},
{
type: 'Documentation',
description: 'Produce detailed, well-structured documentation that makes complex information accessible. From technical manuals to user guides, our AI creates clear, comprehensive documentation that improves understanding and reduces support overhead.',
preview: (
<div className="w-full h-full bg-gradient-to-br from-blue-50 to-indigo-50 dark:from-blue-950/20 dark:to-indigo-950/20 rounded-2xl p-6 border border-blue-200/50 dark:border-blue-800/50 shadow-2xl">
<div className="space-y-4 h-full">
<div className="h-6 bg-blue-200 dark:bg-blue-800 rounded w-2/3"></div>
<div className="space-y-2">
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-full"></div>
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-11/12"></div>
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-10/12"></div>
</div>
<div className="pt-2">
<div className="h-4 bg-blue-200 dark:bg-blue-800 rounded w-1/2 mb-2"></div>
<div className="space-y-2">
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-full"></div>
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-9/12"></div>
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-10/12"></div>
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-8/12"></div>
</div>
</div>
<div className="pt-2">
<div className="h-4 bg-blue-200 dark:bg-blue-800 rounded w-2/5 mb-2"></div>
<div className="space-y-2">
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-full"></div>
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-11/12"></div>
<div className="h-3 bg-blue-100 dark:bg-blue-900 rounded w-7/12"></div>
</div>
</div>
<div className="bg-blue-100 dark:bg-blue-900/50 rounded-lg p-3 border border-blue-200 dark:border-blue-800">
<div className="h-3 bg-blue-200 dark:bg-blue-800 rounded w-1/3 mb-2"></div>
<div className="space-y-1">
<div className="h-2 bg-blue-150 dark:bg-blue-850 rounded w-full"></div>
<div className="h-2 bg-blue-150 dark:bg-blue-850 rounded w-4/5"></div>
</div>
</div>
</div>
</div>
),
},
{
type: 'Data Visualizations',
description: 'Build interactive dashboards and compelling data visualizations that tell your data story. Our AI transforms complex datasets into clear, actionable charts and graphs that reveal patterns, highlight opportunities, and support data-driven decisions.',
preview: (
<div className="w-full h-full bg-gradient-to-br from-orange-50 to-amber-50 dark:from-orange-950/20 dark:to-amber-950/20 rounded-2xl p-6 border border-orange-200/50 dark:border-orange-800/50 shadow-2xl">
<div className="h-full flex flex-col">
<div className="mb-4">
<div className="h-4 bg-orange-200 dark:bg-orange-800 rounded w-1/2 mb-2"></div>
<div className="h-2 bg-orange-100 dark:bg-orange-900 rounded w-3/4"></div>
</div>
<div className="flex-1 flex items-end justify-center space-x-2">
{[
{ height: '60%', label: 'Q1' },
{ height: '80%', label: 'Q2' },
{ height: '100%', label: 'Q3' },
{ height: '75%', label: 'Q4' },
{ height: '90%', label: 'Q5' }
].map((bar, i) => (
<div key={i} className="flex flex-col items-center">
<div
className="w-8 bg-gradient-to-t from-orange-400 to-orange-300 dark:from-orange-600 dark:to-orange-500 rounded-t"
style={{ height: bar.height }}
></div>
<div className="text-xs mt-1 text-orange-600 dark:text-orange-400">{bar.label}</div>
</div>
))}
</div>
<div className="mt-4 grid grid-cols-3 gap-2">
<div className="bg-orange-100 dark:bg-orange-900/50 rounded p-2 text-center">
<div className="text-lg font-bold text-orange-600 dark:text-orange-400">85%</div>
<div className="text-xs text-orange-500 dark:text-orange-500">Growth</div>
</div>
<div className="bg-orange-100 dark:bg-orange-900/50 rounded p-2 text-center">
<div className="text-lg font-bold text-orange-600 dark:text-orange-400">$2.4M</div>
<div className="text-xs text-orange-500 dark:text-orange-500">Revenue</div>
</div>
<div className="bg-orange-100 dark:bg-orange-900/50 rounded p-2 text-center">
<div className="text-lg font-bold text-orange-600 dark:text-orange-400">156</div>
<div className="text-xs text-orange-500 dark:text-orange-500">Clients</div>
</div>
</div>
</div>
</div>
),
},
];
export function DeliverablesSection() {
const [activeIndex, setActiveIndex] = useState(0);
const containerRef = useRef<HTMLDivElement>(null);
const isInView = useInView(containerRef, { margin: "-50%" });
const { scrollYProgress } = useScroll({
target: containerRef,
offset: ['start end', 'end start']
});
// Calculate which deliverable should be active based on scroll progress
useEffect(() => {
const unsubscribe = scrollYProgress.on('change', (latest) => {
if (latest > 0.1 && latest < 0.9) {
const adjustedProgress = (latest - 0.1) / 0.8; // Normalize to 0-1 range
const index = Math.min(
Math.floor(adjustedProgress * deliverables.length),
deliverables.length - 1
);
setActiveIndex(index);
}
});
return unsubscribe;
}, [scrollYProgress]);
return (
<section
ref={containerRef}
id="deliverables"
className="flex flex-col items-center justify-center w-full relative"
>
<div className="relative w-full px-6">
<div className="max-w-6xl mx-auto border-l border-r border-border">
{/* Section Header */}
<div className="flex flex-col items-center justify-center gap-6 py-20 px-6">
<h2 className="text-3xl md:text-4xl font-medium tracking-tighter text-center text-balance">
24/7 AI Workers for Every Task
</h2>
<p className="text-muted-foreground text-center text-balance font-medium max-w-3xl text-lg">
From presentations to data analysis, our AI workers handle complex deliverables while you focus on what matters most. Each worker is specialized, intelligent, and works around the clock to deliver professional results.
</p>
</div>
{/* Sticky Content Area - Locks during scroll */}
<div className="sticky top-0 h-screen flex items-center justify-center w-full bg-background border-t border-border">
<div className="relative w-full">
<div className="max-w-6xl mx-auto px-6">
{/* Content Grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20 items-center">
{/* Left Side - Text */}
<motion.div
initial={{ opacity: 0, x: -50 }}
animate={{ opacity: isInView ? 1 : 0, x: isInView ? 0 : -50 }}
transition={{ duration: 0.8 }}
className="flex flex-col items-start justify-center gap-2"
>
<motion.h3
className="text-3xl md:text-4xl lg:text-5xl font-medium tracking-tighter text-balance mb-6"
key={`title-${activeIndex}`}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<span className="text-foreground">AI Worker for </span>
<span className="text-primary">{deliverables[activeIndex].type}</span>
</motion.h3>
<motion.p
className="text-muted-foreground text-balance font-medium mb-8 text-lg leading-relaxed"
key={`desc-${activeIndex}`}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.1 }}
>
{deliverables[activeIndex].description}
</motion.p>
<motion.button
className="group inline-flex h-12 items-center justify-center gap-2 text-base font-medium tracking-wide rounded-full text-primary-foreground dark:text-black px-8 shadow-[inset_0_1px_2px_rgba(255,255,255,0.25),0_3px_3px_-1.5px_rgba(16,24,40,0.06),0_1px_1px_rgba(16,24,40,0.08)] bg-primary dark:bg-white hover:bg-primary/90 dark:hover:bg-white/90 transition-all duration-200 w-fit mb-8"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
>
<span>Get Started</span>
<span className="inline-flex items-center justify-center size-6 rounded-full bg-white/20 dark:bg-black/10 group-hover:bg-white/30 dark:group-hover:bg-black/20 transition-colors duration-200">
<svg
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="text-primary-foreground dark:text-black"
>
<path
d="M7 17L17 7M17 7H8M17 7V16"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</span>
</motion.button>
{/* Progress Indicator */}
<div className="flex space-x-3">
{deliverables.map((_, index) => (
<button
key={index}
onClick={() => setActiveIndex(index)}
className={`h-3 rounded-full transition-all duration-500 cursor-pointer hover:bg-primary/70 ${
index === activeIndex
? 'w-10 bg-primary shadow-lg shadow-primary/25'
: 'w-3 bg-muted-foreground/30'
}`}
/>
))}
</div>
</motion.div>
{/* Right Side - Preview */}
<motion.div
initial={{ opacity: 0, x: 50 }}
animate={{ opacity: isInView ? 1 : 0, x: isInView ? 0 : 50 }}
transition={{ duration: 0.8, delay: 0.2 }}
className="flex flex-col items-center justify-center h-[600px]"
>
<AnimatePresence mode="wait">
<motion.div
key={activeIndex}
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.95 }}
transition={{
duration: 0.5,
ease: [0.4, 0, 0.2, 1]
}}
className="w-full h-full"
>
{deliverables[activeIndex].preview}
</motion.div>
</AnimatePresence>
</motion.div>
</div>
</div>
</div>
</div>
{/* Spacer sections for scroll trigger - each deliverable gets its own scroll space */}
<div className="relative">
{deliverables.map((deliverable, index) => (
<div
key={index}
className="h-screen opacity-0 pointer-events-none"
data-deliverable={deliverable.type}
/>
))}
</div>
</div>
</div>
</section>
);
}

View File

@ -46,11 +46,46 @@ const BlurredDialogOverlay = () => (
<DialogOverlay className="bg-background/40 backdrop-blur-md" />
);
// Rotating text component for job types
const RotatingText = ({
texts,
className = ""
}: {
texts: string[];
className?: string;
}) => {
const [currentIndex, setCurrentIndex] = useState(0);
const [isVisible, setIsVisible] = useState(true);
useEffect(() => {
const interval = setInterval(() => {
setIsVisible(false);
setTimeout(() => {
setCurrentIndex((prev) => (prev + 1) % texts.length);
setIsVisible(true);
}, 150); // Half of the transition duration
}, 2000); // Change every 2 seconds
return () => clearInterval(interval);
}, [texts.length]);
return (
<span className={`inline-block transition-all duration-300 ${className}`}>
<span
className={`inline-block transition-opacity duration-300 ${
isVisible ? 'opacity-100' : 'opacity-0'
}`}
>
{texts[currentIndex]}
</span>
</span>
);
};
// Constant for localStorage key to ensure consistency
const PENDING_PROMPT_KEY = 'pendingAgentPrompt';
export function HeroSection() {
const { hero } = siteConfig;
const tablet = useMediaQuery('(max-width: 1024px)');
@ -325,11 +360,14 @@ export function HeroSection() {
</Link> */}
<div className="flex flex-col items-center justify-center gap-3 sm:gap-4 pt-8 sm:pt-12 max-w-4xl mx-auto">
<h1 className="text-3xl md:text-4xl lg:text-5xl xl:text-6xl font-medium tracking-tighter text-balance text-center px-2">
<span className="text-primary">Build, manage and train your </span>
<span className="text-secondary">AI Workforce.</span>
<span className="text-primary">Hire Kortix for </span>
<RotatingText
texts={['Research', 'Presentations', 'Docs', 'Spreadsheets', 'Design', 'Data Analysis', 'Email Management', 'Social Media', 'SEO', 'Lead Generation', 'Customer Support', 'Content Creation', 'Project Management', 'Sales', 'Marketing', 'Analytics']}
className="text-secondary"
/>
</h1>
<p className="text-base md:text-lg text-center text-muted-foreground font-medium text-balance leading-relaxed tracking-tight max-w-2xl px-2">
Kortix the simplest way to migrate from human to AI.
Deploy AI Workers that run your business autonomously.
</p>
</div>
@ -339,7 +377,7 @@ export function HeroSection() {
<ChatInput
ref={chatInputRef}
onSubmit={handleChatInputSubmit}
placeholder="Describe the agent you want to build or the task you want completed..."
placeholder="Give Kortix a task to complete..."
loading={isSubmitting}
disabled={isSubmitting}
value={inputValue}

View File

@ -285,8 +285,8 @@ export function OpenSourceSection() {
</motion.div>
</div>
),
title: 'Open Source Security',
description: 'Benefit from the security of open source code that thousands of eyes can review, audit, and improve.',
title: 'Secure Private Deployment',
description: 'Deploy 100% on-premises with complete data sovereignty. Your AI workers run entirely on your infrastructure with no external dependencies.',
showGitHubInfo: true,
},
{
@ -296,8 +296,8 @@ export function OpenSourceSection() {
<Globe className="top-28" />
</div>
),
title: 'Transparency & Trust',
description: 'We believe AI should be open and accessible to everyone. Our open source approach ensures accountability, innovation, and community collaboration.',
title: 'Enterprise-Grade Security',
description: 'Open source transparency meets enterprise security. Deploy behind your firewall with full control over models, data, and integrations.',
showFeatures: true,
},
];
@ -312,10 +312,10 @@ export function OpenSourceSection() {
{/* Section Header */}
<SectionHeader>
<h2 className="text-3xl md:text-4xl font-medium tracking-tighter text-center text-balance">
100% Open Source
100% Open AI
</h2>
<p className="text-muted-foreground text-center text-balance font-medium">
Suna is fully open source. Join our community and help shape the future of AI.
Deploy securely on your own infrastructure with complete control over your data and AI workflows.
</p>
</SectionHeader>
@ -379,9 +379,9 @@ export function OpenSourceSection() {
</svg>
</div>
<div>
<h4 className="font-medium">Transparency</h4>
<h4 className="font-medium">On-Premises</h4>
<p className="text-muted-foreground text-sm">
Fully auditable codebase
100% private deployment
</p>
</div>
</div>

View File

@ -6,7 +6,20 @@ import { siteConfig } from '@/lib/home';
import { cn } from '@/lib/utils';
import { motion } from 'motion/react';
import React, { useState, useEffect, useCallback } from 'react';
import { CheckIcon } from 'lucide-react';
import {
CheckIcon,
Clock,
Bot,
FileText,
Settings,
Grid3X3,
Image,
Video,
Presentation,
Diamond,
Heart,
Zap
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import {
createCheckoutSession,
@ -56,6 +69,42 @@ interface PricingTierProps {
billingPeriod?: 'monthly' | 'yearly' | 'yearly_commitment';
}
// Feature icon mapping
const getFeatureIcon = (feature: string) => {
const featureLower = feature.toLowerCase();
if (featureLower.includes('token credits') || featureLower.includes('ai token')) {
return <Clock className="size-4" />;
}
if (featureLower.includes('custom agents') || featureLower.includes('agents')) {
return <Bot className="size-4" />;
}
if (featureLower.includes('private projects') || featureLower.includes('public projects')) {
return <FileText className="size-4" />;
}
if (featureLower.includes('custom abilities') || featureLower.includes('basic abilities')) {
return <Settings className="size-4" />;
}
if (featureLower.includes('integrations') || featureLower.includes('100+')) {
return <Grid3X3 className="size-4" />;
}
if (featureLower.includes('premium ai models')) {
return <Diamond className="size-4" />;
}
if (featureLower.includes('community support') || featureLower.includes('priority support')) {
return <Heart className="size-4" />;
}
if (featureLower.includes('image') || featureLower.includes('video') || featureLower.includes('slides') || featureLower.includes('generation')) {
return <Image className="size-4" />;
}
if (featureLower.includes('dedicated account manager')) {
return <Zap className="size-4" />;
}
// Default icon
return <CheckIcon className="size-4" />;
};
// Components
function PriceDisplay({ price, isCompact }: PriceDisplayProps) {
@ -263,7 +312,7 @@ function PricingTier({
isScheduled && currentSubscription?.scheduled_price_id === priceId;
const isPlanLoading = isLoading[priceId];
let buttonText = isAuthenticated ? 'Select Plan' : 'Start Free';
let buttonText = isAuthenticated ? 'Select Plan' : tier.buttonText;
let buttonDisabled = isPlanLoading;
let buttonVariant: ButtonVariant = null;
let ringClass = '';
@ -494,9 +543,9 @@ function PricingTier({
{tier.features && tier.features.length > 0 && (
<ul className="space-y-3">
{tier.features.map((feature) => (
<li key={feature} className="flex items-center gap-2">
<div className="size-5 min-w-5 rounded-full border border-primary/20 flex items-center justify-center">
<CheckIcon className="size-3 text-primary" />
<li key={feature} className="flex items-center gap-3">
<div className="size-5 min-w-5 flex items-center justify-center text-muted-foreground">
{getFeatureIcon(feature)}
</div>
<span className="text-sm">{feature}</span>
</li>

View File

@ -125,10 +125,10 @@ export const siteConfig = {
/** @deprecated */
hours: '60 min',
features: [
'$5 free AI tokens included',
'$5 AI token credits/m',
'2 custom agents',
'Public projects',
'Basic Models',
'Basic abilities',
'Community support',
],
stripePriceId: config.SUBSCRIPTION_TIERS.FREE.priceId,
@ -141,17 +141,19 @@ export const siteConfig = {
originalYearlyPrice: '$240',
discountPercentage: 15,
description: 'Best for individuals and small teams',
buttonText: 'Start Free',
buttonText: 'Get started',
buttonColor: 'bg-primary text-white dark:text-black',
isPopular: true,
/** @deprecated */
hours: '2 hours',
features: [
'$20 AI token credits/month',
'$20 AI token credits/m',
'5 custom agents',
'Private projects',
'Custom abilities',
'100+ integrations',
'Premium AI Models',
'Community support',
'Image, Video, Slides generation',
],
stripePriceId: config.SUBSCRIPTION_TIERS.TIER_2_20.priceId,
yearlyStripePriceId: config.SUBSCRIPTION_TIERS.TIER_2_20_YEARLY.priceId,
@ -165,17 +167,19 @@ export const siteConfig = {
originalYearlyPrice: '$600',
discountPercentage: 15,
description: 'Ideal for growing businesses',
buttonText: 'Start Free',
buttonText: 'Get started',
buttonColor: 'bg-secondary text-white',
isPopular: false,
/** @deprecated */
hours: '6 hours',
features: [
'$50 AI token credits/month',
'$50 AI token credits/m',
'20 custom agents',
'Private projects',
'Custom abilities',
'100+ integrations',
'Premium AI Models',
'Community support',
'Image, Video, Slides generation',
],
stripePriceId: config.SUBSCRIPTION_TIERS.TIER_6_50.priceId,
yearlyStripePriceId: config.SUBSCRIPTION_TIERS.TIER_6_50_YEARLY.priceId,
@ -189,16 +193,18 @@ export const siteConfig = {
originalYearlyPrice: '$1200',
discountPercentage: 15,
description: 'For established businesses',
buttonText: 'Start Free',
buttonText: 'Get started',
buttonColor: 'bg-secondary text-white',
isPopular: false,
hours: '12 hours',
features: [
'$100 AI token credits/month',
'$100 AI token credits/m',
'20 custom agents',
'Private projects',
'Custom abilities',
'100+ integrations',
'Premium AI Models',
'Community support',
'Image, Video, Slides generation',
],
stripePriceId: config.SUBSCRIPTION_TIERS.TIER_12_100.priceId,
yearlyStripePriceId: config.SUBSCRIPTION_TIERS.TIER_12_100_YEARLY.priceId,
@ -212,16 +218,19 @@ export const siteConfig = {
originalYearlyPrice: '$2400',
discountPercentage: 15,
description: 'For power users',
buttonText: 'Start Free',
buttonText: 'Get started',
buttonColor: 'bg-secondary text-white',
isPopular: false,
hours: '25 hours',
features: [
'$200 AI token credits/month',
'$200 AI token credits/m',
'100 custom agents',
'Private projects',
'Custom abilities',
'100+ integrations',
'Premium AI Models',
'Priority support',
'Priority Support',
'Image, Video, Slides generation',
],
stripePriceId: config.SUBSCRIPTION_TIERS.TIER_25_200.priceId,
yearlyStripePriceId: config.SUBSCRIPTION_TIERS.TIER_25_200_YEARLY.priceId,
@ -235,16 +244,18 @@ export const siteConfig = {
originalYearlyPrice: '$4800',
discountPercentage: 15,
description: 'For large teams',
buttonText: 'Start Free',
buttonText: 'Get started',
buttonColor: 'bg-secondary text-white',
isPopular: false,
hours: '50 hours',
features: [
'$400 AI token credits/month',
'$400 AI token credits/m',
'Private projects',
'Custom abilities',
'100+ integrations',
'Premium AI Models',
'Priority support',
'Custom integrations',
'Image, Video, Slides generation',
],
stripePriceId: config.SUBSCRIPTION_TIERS.TIER_50_400.priceId,
yearlyStripePriceId: config.SUBSCRIPTION_TIERS.TIER_50_400_YEARLY.priceId,
@ -258,16 +269,18 @@ export const siteConfig = {
originalYearlyPrice: '$9600',
discountPercentage: 15,
description: 'For scaling teams',
buttonText: 'Start Free',
buttonText: 'Get started',
buttonColor: 'bg-secondary text-white',
isPopular: false,
hours: '125 hours',
features: [
'$800 AI token credits/month',
'$800 AI token credits/m',
'Private projects',
'Custom abilities',
'100+ integrations',
'Premium AI Models',
'Priority support',
'Custom integrations',
'Image, Video, Slides generation',
'Dedicated account manager',
],
stripePriceId: config.SUBSCRIPTION_TIERS.TIER_125_800.priceId,
@ -282,16 +295,18 @@ export const siteConfig = {
originalYearlyPrice: '$12000',
discountPercentage: 15,
description: 'Maximum performance',
buttonText: 'Start Free',
buttonText: 'Get started',
buttonColor: 'bg-secondary text-white',
isPopular: false,
hours: '200 hours',
features: [
'$1000 AI token credits/month',
'$1000 AI token credits/m',
'Private projects',
'Custom abilities',
'100+ integrations',
'Premium AI Models',
'Priority support',
'Custom integrations',
'Image, Video, Slides generation',
'Dedicated account manager',
'Custom deployment',
],