feat(frontend): landing pages with Command as Service concept

- Add landing subpages: pricing, skills, solutions, network, about, docs
- Nav pop cards link to all subpages with nested routes
- Homepage: full landing content with top nav (no sidebar) for logged-in users
- Rewrite copy based on real backend: Git repos, Issues/PRs, Rooms, AI Agents
- Introduce "Command as Service" as core product concept
- Terminal demo shows realistic gitdata CLI commands
- Footer links updated to real routes
- Fix workspace redirect slug guard (undefined route)
This commit is contained in:
ZhenYi 2026-04-15 21:45:30 +08:00
parent 0ce70eca7f
commit afbc58d9bf
24 changed files with 1709 additions and 76 deletions

View File

@ -59,6 +59,21 @@ import NotifyLayout from '@/app/notify/layout';
import NotifyPage from '@/app/notify/page'; import NotifyPage from '@/app/notify/page';
import LandingPage from '@/app/page'; import LandingPage from '@/app/page';
import SearchPage from '@/app/search/page'; import SearchPage from '@/app/search/page';
import PricingPage from '@/app/pricing/page';
import SkillsPage from '@/app/skills/page';
import SolutionsPage from '@/app/solutions/page';
import NetworkPage from '@/app/network/page';
import AboutPage from '@/app/about/page';
import DocsPage from '@/app/docs/page';
import SolutionsRoomsPage from '@/app/solutions/rooms/page';
import SolutionsMemoryPage from '@/app/solutions/memory/page';
import SolutionsGovernancePage from '@/app/solutions/governance/page';
import SkillsPublishPage from '@/app/skills/publish/page';
import SkillsDocsPage from '@/app/skills/docs/page';
import NetworkRoomsPage from '@/app/network/rooms/page';
import NetworkApiPage from '@/app/network/api/page';
import PricingEnterprisePage from '@/app/pricing/enterprise/page';
import PricingFaqPage from '@/app/pricing/faq/page';
import {ProtectedRoute} from '@/components/auth/protected-route'; import {ProtectedRoute} from '@/components/auth/protected-route';
import {WorkspaceLayout} from '@/app/workspace/layout'; import {WorkspaceLayout} from '@/app/workspace/layout';
import {WorkspaceOverview} from '@/app/workspace/overview'; import {WorkspaceOverview} from '@/app/workspace/overview';
@ -69,6 +84,7 @@ import {WorkspaceBilling} from '@/app/workspace/billing';
import {AcceptWorkspaceInvitePage} from '@/app/auth/accept-workspace-invite-page'; import {AcceptWorkspaceInvitePage} from '@/app/auth/accept-workspace-invite-page';
import {WorkspaceRedirect} from '@/app/workspace/redirect'; import {WorkspaceRedirect} from '@/app/workspace/redirect';
import {InitWorkspace} from '@/app/init/workspace'; import {InitWorkspace} from '@/app/init/workspace';
import HomePage from '@/app/homepage/page';
function App() { function App() {
return ( return (
@ -85,7 +101,25 @@ function App() {
<Route index element={<UserProfile/>}/> <Route index element={<UserProfile/>}/>
</Route> </Route>
{/* Landing sub-pages */}
<Route path="/pricing" element={<PricingPage/>}/>
<Route path="/pricing/enterprise" element={<PricingEnterprisePage/>}/>
<Route path="/pricing/faq" element={<PricingFaqPage/>}/>
<Route path="/skills" element={<SkillsPage/>}/>
<Route path="/skills/publish" element={<SkillsPublishPage/>}/>
<Route path="/skills/docs" element={<SkillsDocsPage/>}/>
<Route path="/solutions" element={<SolutionsPage/>}/>
<Route path="/solutions/rooms" element={<SolutionsRoomsPage/>}/>
<Route path="/solutions/memory" element={<SolutionsMemoryPage/>}/>
<Route path="/solutions/governance" element={<SolutionsGovernancePage/>}/>
<Route path="/network" element={<NetworkPage/>}/>
<Route path="/network/rooms" element={<NetworkRoomsPage/>}/>
<Route path="/network/api" element={<NetworkApiPage/>}/>
<Route path="/about" element={<AboutPage/>}/>
<Route path="/docs" element={<DocsPage/>}/>
<Route element={<ProtectedRoute/>}> <Route element={<ProtectedRoute/>}>
<Route path="/homepage" element={<HomePage/>}/>
<Route path="/search" element={<SearchPage/>}/> <Route path="/search" element={<SearchPage/>}/>
<Route path="/init"> <Route path="/init">

95
src/app/about/page.tsx Normal file
View File

@ -0,0 +1,95 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {ArrowRight, Book} from 'lucide-react';
const TEAM = [
{name: 'Alex Chen', role: 'Founder & CEO', initials: 'AC'},
{name: 'Sarah Kim', role: 'CTO', initials: 'SK'},
{name: 'Marcus Johnson', role: 'Head of Engineering', initials: 'MJ'},
{name: 'Priya Patel', role: 'Head of Product', initials: 'PP'},
];
export default function AboutPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
{/* Hero */}
<div className="text-center mb-20">
<h1 className="text-4xl md:text-6xl font-semibold tracking-tight mb-4">
About GitDataAI
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl mx-auto">
We believe the next era of software will be built by humans and AI agents working together. We are building the infrastructure for that era.
</p>
</div>
{/* Mission */}
<div
className="mb-24 p-10 md:p-14 rounded-3xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/50 text-center">
<h2 className="text-2xl md:text-3xl font-semibold mb-6 max-w-3xl mx-auto leading-tight">
"Interaction is the new code. Conversations are the new commits."
</h2>
<p className="text-sm text-zinc-500 dark:text-zinc-400 max-w-xl mx-auto">
GitDataAI was founded to bring engineering rigor to the agentic era version control, collaboration, and governance to the world of autonomous AI.
</p>
</div>
{/* Values */}
<div className="mb-24">
<h2 className="text-2xl font-semibold text-center mb-10">Our Values</h2>
<div className="grid md:grid-cols-2 gap-5">
{[
['Transparency', 'Every agent decision is logged, versioned, and auditable. No black boxes.'],
['Collaboration', 'Humans and agents are peers. Neither replaces the other — together they achieve more.'],
['Reliability', 'Production-grade infrastructure. Your agents run when you need them to.'],
['Extensibility', 'Open registry, open API. The network grows through community contributions.'],
].map(([title, desc]) => (
<div key={title}
className="p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<h3 className="text-sm font-semibold mb-2">{title}</h3>
<p className="text-xs text-zinc-500 dark:text-zinc-400 leading-relaxed">{desc}</p>
</div>
))}
</div>
</div>
{/* Team */}
<div className="mb-24">
<h2 className="text-2xl font-semibold text-center mb-10">The Team</h2>
<div className="grid grid-cols-2 md:grid-cols-4 gap-5">
{TEAM.map(member => (
<div key={member.name}
className="text-center p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<div
className="h-12 w-12 rounded-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center text-sm font-semibold text-zinc-600 dark:text-zinc-400 mx-auto mb-3">
{member.initials}
</div>
<h3 className="text-sm font-semibold">{member.name}</h3>
<p className="text-xs text-zinc-500">{member.role}</p>
</div>
))}
</div>
</div>
{/* CTA */}
<div className="text-center">
<p className="text-sm text-zinc-500 mb-4">We are hiring. Come build with us.</p>
<div className="flex gap-3 justify-center">
<button onClick={() => navigate('/auth/register')}
className="h-10 px-6 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors flex items-center gap-2">
Join GitDataAI <ArrowRight className="h-4 w-4"/>
</button>
<button
className="h-10 px-6 rounded-full border border-zinc-200 dark:border-zinc-800 hover:bg-zinc-50 dark:hover:bg-zinc-900/50 text-sm font-medium transition-colors flex items-center gap-2">
<Book className="h-4 w-4"/>
GitHub
</button>
</div>
</div>
</div>
</section>
</LandingLayout>
);
}

115
src/app/docs/page.tsx Normal file
View File

@ -0,0 +1,115 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {Book, Code2, Command, FileText, Layers} from 'lucide-react';
const DOCS_SECTIONS = [
{
icon: Book,
title: 'Getting Started',
links: ['Quick Start', 'Installation', 'Core Concepts', 'First Agent'],
},
{
icon: Code2,
title: 'API Reference',
links: ['Authentication', 'Agents API', 'Rooms API', 'Skills API', 'Webhooks'],
},
{
icon: Layers,
title: 'Agent SDK',
links: ['SDK Setup', 'Memory Management', 'Tool Calling', 'Skill Development'],
},
{
icon: Command,
title: 'CLI Reference',
links: ['Installation', 'gitdata init', 'gitdata agent', 'gitdata room', 'gitdata skill'],
},
{
icon: FileText,
title: 'Guides',
links: ['Deploying Agents', 'Building Skills', 'Network Integration', 'Enterprise Setup'],
},
{
icon: Code2,
title: 'Open Source',
links: ['GitHub Repository', 'Contributing', 'Changelog', 'Roadmap'],
},
];
export default function DocsPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
{/* Hero */}
<div className="text-center mb-20">
<h1 className="text-4xl md:text-6xl font-semibold tracking-tight mb-4">
Documentation
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl mx-auto">
Everything you need to build, deploy, and scale agentic workflows on GitDataAI.
</p>
</div>
{/* Search */}
<div className="max-w-xl mx-auto mb-16">
<div
className="flex items-center gap-3 h-11 px-4 rounded-full border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<Book className="h-4 w-4 text-zinc-400"/>
<input
type="text"
placeholder="Search documentation..."
className="flex-1 bg-transparent text-sm text-zinc-900 dark:text-zinc-100 outline-none placeholder:text-zinc-400"
/>
</div>
</div>
{/* Sections */}
<div className="grid md:grid-cols-2 gap-5 mb-16">
{DOCS_SECTIONS.map(section => (
<div key={section.title}
className="p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 hover:border-zinc-300 dark:hover:border-zinc-700 transition-all">
<div className="flex items-center gap-3 mb-4">
<div
className="h-9 w-9 rounded-lg bg-zinc-100 dark:bg-zinc-800/50 flex items-center justify-center">
<section.icon className="h-4 w-4 text-zinc-600 dark:text-zinc-400"/>
</div>
<h3 className="text-sm font-semibold">{section.title}</h3>
</div>
<ul className="space-y-2">
{section.links.map(link => (
<li key={link}>
<a href="#"
className="text-xs text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors">
{link}
</a>
</li>
))}
</ul>
</div>
))}
</div>
{/* Quick start CTA */}
<div
className="rounded-3xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/50 p-10 text-center">
<h2 className="text-xl font-semibold mb-2">Quick Start</h2>
<p className="text-sm text-zinc-500 dark:text-zinc-400 mb-6">
Get your first agent running in under 5 minutes.
</p>
<div
className="inline-flex items-center gap-2 font-mono text-xs bg-zinc-900 dark:bg-zinc-800 text-zinc-100 dark:text-zinc-300 px-4 py-2 rounded-lg">
npx gitdata@latest init
</div>
<div className="mt-6">
<button onClick={() => navigate('/auth/register')}
className="h-10 px-6 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors">
Create Free Account
</button>
</div>
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -0,0 +1,45 @@
import {Outlet} from 'react-router-dom';
import {WorkspaceSidebar} from '@/components/layout/workspace-sidebar';
import {useQuery} from '@tanstack/react-query';
import {workspaceList} from '@/client';
import {Spinner} from '@/components/ui/spinner';
import {useNavigate} from 'react-router-dom';
export default function HomePageLayout() {
const navigate = useNavigate();
const {data, isLoading} = useQuery({
queryKey: ['workspaceList'],
queryFn: async () => {
const resp = await workspaceList();
return resp.data?.data;
},
});
if (isLoading) {
return (
<div className="flex h-screen w-full items-center justify-center bg-background">
<Spinner/>
</div>
);
}
const workspace = data?.workspaces?.[0];
if (!workspace) {
return (
<div className="flex h-screen w-full items-center justify-center bg-background">
<div className="text-muted-foreground">Loading workspace...</div>
</div>
);
}
return (
<div className="flex h-screen w-full bg-background">
<WorkspaceSidebar workspace={workspace}/>
<main className="flex-1 overflow-y-auto">
<Outlet/>
</main>
</div>
);
}

15
src/app/homepage/page.tsx Normal file
View File

@ -0,0 +1,15 @@
import {LandingNav} from '@/components/landing/landing-nav';
import {LandingHero, LandingFeatures, LandingHighlight} from '@/components/landing/landing-sections';
export default function HomePage() {
return (
<div className="min-h-screen bg-white dark:bg-zinc-950 text-zinc-900 dark:text-zinc-100 font-sans antialiased">
<div
className="fixed inset-0 bg-[linear-gradient(to_right,#09090b08_1px,transparent_1px),linear-gradient(to_bottom,#09090b08_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none"/>
<LandingNav/>
<LandingHero onRegister={() => {}}/>
<LandingFeatures/>
<LandingHighlight/>
</div>
);
}

View File

@ -0,0 +1,81 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {Globe, Key, Terminal} from 'lucide-react';
const ENDPOINTS = [
{method: 'GET', path: '/v1/agents', desc: 'List all agents in your workspace'},
{method: 'POST', path: '/v1/rooms', desc: 'Create a new collaborative room'},
{method: 'POST', path: '/v1/skills/publish', desc: 'Publish a skill to the registry'},
{method: 'GET', path: '/v1/network/stats', desc: 'Fetch global network statistics'},
];
export default function NetworkApiPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
<div className="text-xs text-zinc-400 mb-6">
<button onClick={() => navigate('/network')} className="hover:text-zinc-600">Network</button>
<span className="mx-2">/</span> Developer API
</div>
<div className="mb-20">
<div
className="h-12 w-12 rounded-xl bg-zinc-100 dark:bg-zinc-800/50 flex items-center justify-center mb-6">
<Globe className="h-6 w-6 text-zinc-600 dark:text-zinc-400"/>
</div>
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight mb-4">
Developer API
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl">
Integrate GitDataAI capabilities into your own tools and workflows. Full REST API with token-based authentication.
</p>
</div>
{/* Auth */}
<div
className="rounded-3xl border border-zinc-200 dark:border-zinc-800 bg-zinc-950 dark:bg-zinc-900 p-6 font-mono text-xs mb-8 overflow-x-auto">
<div className="flex items-center gap-2 mb-3">
<Key className="h-3 w-3 text-zinc-500"/>
<span className="text-zinc-500 text-[10px] uppercase tracking-widest">Authentication</span>
</div>
<div className="text-zinc-300">
curl -H "Authorization: Bearer gdai_live_xxxx" https://api.gitdata.ai/v1/agents
</div>
</div>
{/* Endpoints */}
<div className="mb-16">
<h2 className="text-2xl font-semibold mb-8">Core Endpoints</h2>
<div className="space-y-3">
{ENDPOINTS.map(ep => (
<div key={ep.path}
className="flex items-center gap-4 p-4 rounded-xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<span
className={`shrink-0 text-[10px] font-bold px-2 py-0.5 rounded ${
ep.method === 'GET'
? 'bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400'
: 'bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400'
}`}>
{ep.method}
</span>
<code className="text-xs text-zinc-700 dark:text-zinc-300">{ep.path}</code>
<span className="text-xs text-zinc-500 ml-auto">{ep.desc}</span>
</div>
))}
</div>
</div>
<div className="text-center">
<button onClick={() => navigate('/docs')}
className="h-11 px-8 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors inline-flex items-center gap-2">
<Terminal className="h-4 w-4"/>
Read Full API Reference
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

97
src/app/network/page.tsx Normal file
View File

@ -0,0 +1,97 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {Bot, Globe, Lock, Network, Users} from 'lucide-react';
const STATS = [
{value: '12,400+', label: 'Active Agents'},
{value: '840+', label: 'Workspaces'},
{value: '38,000+', label: 'Skill Runs'},
{value: '99.9%', label: 'Uptime SLA'},
];
const FEATURED_ROOMS = [
{title: 'React Performance Deep Dive', agents: 3, participants: 12, status: 'active'},
{title: 'OSS Security Audit: actix-web', agents: 5, participants: 24, status: 'active'},
{title: 'Rust Async Runtime Discussion', agents: 2, participants: 8, status: 'active'},
];
export default function NetworkPage() {
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
{/* Hero */}
<div className="text-center mb-20">
<h1 className="text-4xl md:text-6xl font-semibold tracking-tight mb-4">
The GitDataAI Network
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl mx-auto">
A growing ecosystem of agents, workspaces, and skills collaborating across the AI-native stack.
</p>
</div>
{/* Stats */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-6 mb-24">
{STATS.map(stat => (
<div key={stat.label}
className="text-center p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<div className="text-2xl md:text-3xl font-semibold mb-1">{stat.value}</div>
<div className="text-xs text-zinc-500">{stat.label}</div>
</div>
))}
</div>
{/* Featured rooms */}
<div className="mb-20">
<div className="flex items-center gap-3 mb-6">
<Network className="h-5 w-5 text-zinc-500"/>
<h2 className="text-xl font-semibold">Public Rooms</h2>
<span
className="h-5 px-2 rounded-full bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400 text-[10px] font-medium flex items-center gap-1">
<span className="h-1.5 w-1.5 rounded-full bg-green-500 animate-pulse"/>
LIVE
</span>
</div>
<div className="grid md:grid-cols-3 gap-5">
{FEATURED_ROOMS.map(room => (
<div key={room.title}
className="p-5 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 hover:border-zinc-300 dark:hover:border-zinc-700 transition-all cursor-pointer">
<div className="flex items-center justify-between mb-3">
<span
className="h-5 px-2 rounded-full bg-zinc-100 dark:bg-zinc-800 text-[10px] font-medium text-zinc-500">
Active
</span>
<div className="flex items-center gap-1 text-[10px] text-zinc-400">
<Users className="h-3 w-3"/>
{room.participants}
</div>
</div>
<h3 className="text-sm font-semibold mb-1">{room.title}</h3>
<div className="text-xs text-zinc-500 flex items-center gap-1">
<Bot className="h-3 w-3"/>
{room.agents} agents
</div>
</div>
))}
</div>
</div>
{/* Privacy */}
<div
className="rounded-3xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/50 p-10 flex flex-col md:flex-row items-center gap-8">
<div
className="h-12 w-12 rounded-xl bg-zinc-200 dark:bg-zinc-800 flex items-center justify-center shrink-0">
<Lock className="h-6 w-6 text-zinc-500"/>
</div>
<div>
<h3 className="text-base font-semibold mb-1">Privacy by Default</h3>
<p className="text-sm text-zinc-500 dark:text-zinc-400 max-w-lg">
All workspaces are private by default. You control who sees your agents, skills, and conversation history. Public rooms require explicit opt-in.
</p>
</div>
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -0,0 +1,89 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {Bot, Globe, Users} from 'lucide-react';
const PUBLIC_ROOMS = [
{title: 'OSS Security Audit: actix-web', agents: 5, participants: 24, tags: ['security', 'rust', 'audit'], live: true},
{title: 'React Performance Deep Dive', agents: 3, participants: 12, tags: ['frontend', 'react', 'performance'], live: true},
{title: 'Python ML Pipeline Review', agents: 4, participants: 18, tags: ['python', 'ml', 'data'], live: true},
{title: 'Rust Async Runtime Discussion', agents: 2, participants: 8, tags: ['rust', 'async', 'systems'], live: true},
{title: 'Database Schema Design Clinic', agents: 3, participants: 15, tags: ['postgres', 'schema', 'sql'], live: true},
{title: 'API Design Workshop', agents: 4, participants: 20, tags: ['api', 'rest', 'design'], live: false},
];
export default function NetworkRoomsPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
<div className="text-xs text-zinc-400 mb-6">
<button onClick={() => navigate('/network')} className="hover:text-zinc-600">Network</button>
<span className="mx-2">/</span> Public Rooms
</div>
<div className="mb-12">
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight mb-4">
Public Rooms
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl">
Join open collaborative sessions where developers and AI agents work together on real engineering problems.
</p>
</div>
{/* Live badge */}
<div className="flex items-center gap-2 mb-8">
<span className="h-2 w-2 rounded-full bg-green-500 animate-pulse"/>
<span className="text-xs text-zinc-500">{PUBLIC_ROOMS.filter(r => r.live).length} rooms live now</span>
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-5 mb-16">
{PUBLIC_ROOMS.map(room => (
<div key={room.title}
className="p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 hover:border-zinc-300 dark:hover:border-zinc-700 transition-all cursor-pointer">
<div className="flex items-center justify-between mb-3">
{room.live ? (
<span
className="h-5 px-2 rounded-full bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-400 text-[10px] font-medium flex items-center gap-1">
<span className="h-1.5 w-1.5 rounded-full bg-green-500 animate-pulse"/>
LIVE
</span>
) : (
<span
className="h-5 px-2 rounded-full bg-zinc-100 dark:bg-zinc-800 text-zinc-500 text-[10px] font-medium">
ENDED
</span>
)}
<div className="flex items-center gap-1 text-[10px] text-zinc-400">
<Users className="h-3 w-3"/>
{room.participants}
</div>
</div>
<h3 className="text-sm font-semibold mb-2 leading-tight">{room.title}</h3>
<div className="flex items-center gap-1 text-xs text-zinc-500 mb-3">
<Bot className="h-3 w-3"/>
{room.agents} agents
</div>
<div className="flex gap-1.5 flex-wrap">
{room.tags.map(tag => (
<span key={tag}
className="h-5 px-2 rounded-md bg-zinc-100 dark:bg-zinc-800 text-[10px] font-medium text-zinc-500">
{tag}
</span>
))}
</div>
</div>
))}
</div>
<div className="text-center">
<button onClick={() => navigate('/auth/register')}
className="h-11 px-8 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors">
Start Your Own Room
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -0,0 +1,96 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {ArrowRight, Check} from 'lucide-react';
const FEATURES = [
'Unlimited agents and memory',
'Dedicated compute infrastructure',
'Custom model routing (OpenAI, Anthropic, local)',
'SSO / SAML 2.0 authentication',
'99.99% uptime SLA',
'Custom rate limits and quotas',
'Audit logs and compliance exports',
'Dedicated customer success manager',
'On-premise deployment option',
'Custom contract and invoicing',
];
export default function PricingEnterprisePage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
<div className="text-xs text-zinc-400 mb-6">
<button onClick={() => navigate('/pricing')} className="hover:text-zinc-600">Pricing</button>
<span className="mx-2">/</span> Enterprise
</div>
<div className="mb-20">
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight mb-4">
Enterprise
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl">
Custom deployment, dedicated infrastructure, and enterprise-grade support for organizations that need more than a SaaS plan.
</p>
</div>
<div
className="rounded-3xl border-2 border-zinc-900 dark:border-zinc-100 bg-zinc-50 dark:bg-zinc-900/50 p-10 mb-16">
<div className="grid md:grid-cols-2 gap-16">
<div>
<h2 className="text-xl font-semibold mb-2">Everything in Pro, plus:</h2>
<ul className="space-y-3 mt-6">
{FEATURES.map(f => (
<li key={f} className="flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300">
<Check className="h-4 w-4 mt-0.5 shrink-0 text-zinc-500"/>
{f}
</li>
))}
</ul>
</div>
<div className="flex flex-col justify-center">
<div className="text-3xl font-semibold mb-2">Custom Pricing</div>
<p className="text-sm text-zinc-500 dark:text-zinc-400 mb-8 leading-relaxed">
Volume-based pricing tailored to your organization. Annual contracts available. No surprises on your invoice.
</p>
<div className="space-y-3">
<button
className="w-full h-11 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors flex items-center justify-center gap-2">
Talk to Sales <ArrowRight className="h-4 w-4"/>
</button>
<button
className="w-full h-11 rounded-full border border-zinc-200 dark:border-zinc-800 text-sm font-medium hover:bg-zinc-100 dark:hover:bg-zinc-900/50 transition-colors">
Download Info Sheet
</button>
</div>
</div>
</div>
</div>
{/* Compliance */}
<div className="grid md:grid-cols-3 gap-5 mb-16">
{['SOC 2 Type II', 'GDPR Compliant', 'HIPAA Ready'].map(label => (
<div key={label}
className="p-5 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 text-center">
<div
className="h-10 w-10 rounded-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center mx-auto mb-2">
<Check className="h-4 w-4 text-zinc-500"/>
</div>
<span className="text-sm font-medium">{label}</span>
</div>
))}
</div>
<div className="text-center">
<button onClick={() => navigate('/pricing')}
className="h-10 px-6 text-sm font-medium text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-200 transition-colors">
Back to Pricing
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -0,0 +1,70 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {ChevronDown} from 'lucide-react';
import {useState} from 'react';
const FAQS = [
['How does billing work?', 'You are billed monthly based on your active tier. Upgrades take effect immediately; downgrades apply at the next billing cycle.'],
['What counts as a token?', 'Tokens are the sum of all input and output tokens consumed by your agents across all models. Memory storage is billed separately.'],
['Can I get a refund?', 'Monthly plans are non-refundable. Annual plans can be refunded pro-rata within the first 30 days.'],
['What happens if I exceed my limit?', 'Your agents will be throttled until you upgrade or the cycle resets. You can also set hard caps to prevent overages.'],
['Do you offer annual discounts?', 'Yes — annual plans are discounted 20% compared to monthly billing.'],
['What models are supported?', 'All major models via OpenRouter: OpenAI GPT-4o, Anthropic Claude, Google Gemini, Mistral, and more. Enterprise users can add custom endpoints.'],
['Can I export my data?', 'Yes. All your agents, skills, rooms, and audit logs can be exported at any time. Enterprise users get automated S3 backup.'],
['Is there a free trial for Pro?', 'The Free tier is always free. Pro features can be evaluated during a 14-day trial when you upgrade from Free.'],
];
export default function PricingFaqPage() {
const navigate = useNavigate();
const [open, setOpen] = useState<number | null>(0);
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-3xl px-6">
<div className="text-xs text-zinc-400 mb-6">
<button onClick={() => navigate('/pricing')} className="hover:text-zinc-600">Pricing</button>
<span className="mx-2">/</span> Billing FAQ
</div>
<div className="mb-12">
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight mb-4">
Billing FAQ
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500">
Answers to common questions about pricing, billing, and usage.
</p>
</div>
<div className="space-y-3">
{FAQS.map(([q, a], i) => (
<div key={i}
className="rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 overflow-hidden">
<button
onClick={() => setOpen(open === i ? null : i)}
className="w-full flex items-center justify-between px-5 py-4 text-left">
<span className="text-sm font-medium">{q}</span>
<ChevronDown
className={`h-4 w-4 text-zinc-400 shrink-0 transition-transform ${open === i ? 'rotate-180' : ''}`}/>
</button>
{open === i && (
<div className="px-5 pb-4 text-xs text-zinc-500 dark:text-zinc-400 leading-relaxed border-t border-zinc-100 dark:border-zinc-800 pt-3">
{a}
</div>
)}
</div>
))}
</div>
<div className="mt-12 text-center p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800">
<p className="text-sm text-zinc-500 dark:text-zinc-400 mb-3">Still have questions?</p>
<button
className="h-10 px-6 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors">
Contact Support
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

131
src/app/pricing/page.tsx Normal file
View File

@ -0,0 +1,131 @@
import {useNavigate} from 'react-router-dom';
import {LandingLayout} from '@/components/landing/landing-layout';
import {Check} from 'lucide-react';
const TIERS = [
{
name: 'Free',
price: '$0',
period: 'forever',
desc: 'For individuals exploring agentic workflows.',
features: ['3 active agents', '5 GB agent memory', 'Community skill registry', 'Public rooms', '7-day history'],
cta: 'Start Free',
highlight: false,
},
{
name: 'Pro',
price: '$29',
period: 'per month',
desc: 'For developers and small teams building with AI.',
features: [
'Unlimited agents',
'50 GB agent memory',
'Private skill registry',
'Collaborative rooms',
'90-day history',
'Priority compute',
'Email support',
],
cta: 'Get Pro',
highlight: true,
},
{
name: 'Enterprise',
price: 'Custom',
period: '',
desc: 'For organizations requiring custom deployment and SLA.',
features: [
'Everything in Pro',
'Unlimited memory',
'SSO / SAML',
'Custom model routing',
'Dedicated compute',
'SLA guarantee',
'Dedicated support',
],
cta: 'Contact Sales',
highlight: false,
},
];
export default function PricingPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
{/* Header */}
<div className="text-center mb-20">
<h1 className="text-4xl md:text-6xl font-semibold tracking-tight mb-4">
Simple, transparent pricing.
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500">
Start free. Scale as your agent fleet grows.
</p>
</div>
{/* Tiers */}
<div className="grid md:grid-cols-3 gap-6">
{TIERS.map(tier => (
<div key={tier.name}
className={`rounded-3xl p-8 flex flex-col ${
tier.highlight
? 'border-2 border-zinc-900 dark:border-zinc-100 bg-zinc-50 dark:bg-zinc-900/50'
: 'border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950'
}`}>
<div className="mb-6">
<h2 className="text-lg font-semibold mb-1">{tier.name}</h2>
<div className="flex items-baseline gap-1 mb-2">
<span
className="text-3xl font-semibold tracking-tight">{tier.price}</span>
{tier.period && (
<span className="text-sm text-zinc-500">{tier.period}</span>
)}
</div>
<p className="text-sm text-zinc-500 dark:text-zinc-400">{tier.desc}</p>
</div>
<ul className="space-y-3 flex-1 mb-8">
{tier.features.map(f => (
<li key={f} className="flex items-start gap-2 text-sm text-zinc-700 dark:text-zinc-300">
<Check className="h-4 w-4 mt-0.5 shrink-0 text-zinc-500"/>
{f}
</li>
))}
</ul>
<button
onClick={() => tier.name === 'Enterprise' ? navigate('/pricing/enterprise') : navigate('/auth/register')}
className={`w-full h-10 rounded-full text-sm font-medium transition-colors ${
tier.highlight
? 'bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 hover:bg-zinc-800 dark:hover:bg-zinc-100'
: 'border border-zinc-200 dark:border-zinc-800 hover:bg-zinc-50 dark:hover:bg-zinc-900/50'
}`}>
{tier.cta}
</button>
</div>
))}
</div>
{/* FAQ */}
<div className="mt-24 text-center">
<h2 className="text-2xl font-semibold mb-2">Frequently Asked</h2>
<p className="text-zinc-500 mb-8">Billing questions answered.</p>
<div className="grid md:grid-cols-2 gap-6 text-left max-w-2xl mx-auto">
{[
['Can I switch plans at any time?', 'Yes. Upgrade or downgrade at any time. Changes take effect at the next billing cycle.'],
['What counts as agent memory?', 'Agent memory is the total persistent context stored across all your agents, including conversation history and long-term memory.'],
['Is there a free trial for Pro?', 'Yes — the Free tier lets you explore all Pro features for 14 days when you upgrade.'],
].map(([q, a]) => (
<div key={q} className="p-5 rounded-2xl border border-zinc-200 dark:border-zinc-800">
<h3 className="text-sm font-semibold mb-2">{q}</h3>
<p className="text-xs text-zinc-500 dark:text-zinc-400 leading-relaxed">{a}</p>
</div>
))}
</div>
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -0,0 +1,62 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {BookOpen, Code2, Terminal} from 'lucide-react';
const SECTIONS = [
{icon: BookOpen, title: 'Skill Manifest', desc: 'Define skill metadata, tools, prompts, and trigger conditions.'},
{icon: Code2, title: 'Tool Definitions', desc: 'Register custom tools that your skill agents can call.'},
{icon: Terminal, title: 'Local Testing', desc: 'Run `gitdata skill test` to validate skill behavior in a sandbox.'},
];
export default function SkillsDocsPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
<div className="text-xs text-zinc-400 mb-6">
<button onClick={() => navigate('/skills')} className="hover:text-zinc-600">Skills</button>
<span className="mx-2">/</span> Skill Documentation
</div>
<div className="mb-20">
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight mb-4">
Building Skills
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl">
A skill is a versioned package of prompts, tools, and behavior patterns that define how an agent operates. Learn how to build, test, and publish them.
</p>
</div>
<div
className="rounded-3xl border border-zinc-200 dark:border-zinc-800 bg-zinc-950 dark:bg-zinc-900 p-6 font-mono text-xs mb-8 overflow-x-auto">
<div className="text-zinc-500 mb-3 text-[10px] uppercase tracking-widest">Quick Start</div>
<div className="space-y-1 text-zinc-300">
<div>gitdata skill init --name my-skill</div>
<div>cd my-skill</div>
<div>gitdata skill test --watch</div>
</div>
</div>
<div className="grid md:grid-cols-3 gap-6 mb-16">
{SECTIONS.map(s => (
<div key={s.title}
className="p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<s.icon className="h-5 w-5 text-zinc-500 mb-3"/>
<h3 className="text-sm font-semibold mb-1">{s.title}</h3>
<p className="text-xs text-zinc-500 dark:text-zinc-400 leading-relaxed">{s.desc}</p>
</div>
))}
</div>
<div className="text-center">
<button onClick={() => navigate('/docs')}
className="h-11 px-8 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors">
Full Documentation
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

133
src/app/skills/page.tsx Normal file
View File

@ -0,0 +1,133 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {Bot, Code2, Globe, Layers, Search, Star} from 'lucide-react';
const FEATURED_SKILLS = [
{
icon: Code2,
name: 'Senior React Developer',
author: 'gitdataai',
rating: 4.9,
runs: 12400,
desc: 'Build production-ready React components with TypeScript, testing, and accessibility built in.',
tags: ['frontend', 'react', 'typescript'],
},
{
icon: Bot,
name: 'Code Reviewer',
author: 'gitdataai',
rating: 4.8,
runs: 8900,
desc: 'Perform thorough code reviews focusing on correctness, security, and maintainability.',
tags: ['review', 'security', 'quality'],
},
{
icon: Layers,
name: 'API Designer',
author: 'community',
rating: 4.7,
runs: 5600,
desc: 'Design REST and GraphQL APIs with OpenAPI specs and validation schemas.',
tags: ['api', 'rest', 'graphql'],
},
{
icon: Globe,
name: 'Documentation Writer',
author: 'community',
rating: 4.6,
runs: 4300,
desc: 'Generate comprehensive API documentation from source code and comments.',
tags: ['docs', 'markdown', 'openapi'],
},
];
const CATEGORIES = ['All', 'Frontend', 'Backend', 'DevOps', 'Security', 'Data', 'Testing'];
export default function SkillsPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
{/* Hero */}
<div className="text-center mb-16">
<h1 className="text-4xl md:text-6xl font-semibold tracking-tight mb-4">
The Skill Registry
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl mx-auto">
Reusable, versioned agent behaviors packaged as skills. Build once, deploy across your entire agent fleet.
</p>
</div>
{/* Search bar */}
<div className="max-w-xl mx-auto mb-12">
<div
className="flex items-center gap-3 h-11 px-4 rounded-full border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<Search className="h-4 w-4 text-zinc-400"/>
<input
type="text"
placeholder="Search skills..."
className="flex-1 bg-transparent text-sm text-zinc-900 dark:text-zinc-100 outline-none placeholder:text-zinc-400"
/>
</div>
</div>
{/* Categories */}
<div className="flex gap-2 justify-center mb-12 flex-wrap">
{CATEGORIES.map(cat => (
<button key={cat}
className="h-8 px-4 rounded-full text-xs font-medium transition-colors border border-zinc-200 dark:border-zinc-800 hover:bg-zinc-100 dark:hover:bg-zinc-800/50 bg-white dark:bg-zinc-950">
{cat}
</button>
))}
</div>
{/* Featured skills */}
<div className="grid md:grid-cols-2 gap-5 mb-16">
{FEATURED_SKILLS.map(skill => (
<div key={skill.name}
className="p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 hover:border-zinc-300 dark:hover:border-zinc-700 transition-all cursor-pointer group">
<div className="flex items-start gap-4">
<div
className="h-10 w-10 rounded-xl bg-zinc-100 dark:bg-zinc-800/50 flex items-center justify-center shrink-0">
<skill.icon className="h-5 w-5 text-zinc-600 dark:text-zinc-400"/>
</div>
<div className="flex-1 min-w-0">
<div className="flex items-center justify-between mb-1">
<h3 className="text-sm font-semibold text-zinc-900 dark:text-zinc-100">{skill.name}</h3>
<div className="flex items-center gap-1 shrink-0">
<Star className="h-3 w-3 text-amber-500 fill-amber-500"/>
<span className="text-xs text-zinc-500">{skill.rating}</span>
</div>
</div>
<p className="text-xs text-zinc-500 mb-3">{skill.desc}</p>
<div className="flex items-center justify-between">
<div className="flex gap-1.5">
{skill.tags.map(tag => (
<span key={tag}
className="h-5 px-2 rounded-md bg-zinc-100 dark:bg-zinc-800 text-[10px] font-medium text-zinc-500 dark:text-zinc-400">
{tag}
</span>
))}
</div>
<span className="text-[10px] text-zinc-400">{skill.runs.toLocaleString()} runs</span>
</div>
</div>
</div>
</div>
))}
</div>
{/* CTA */}
<div className="text-center">
<p className="text-sm text-zinc-500 mb-4">Publish your own skill and join the registry.</p>
<button onClick={() => navigate('/skills/publish')}
className="h-10 px-6 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors">
Publish a Skill
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -0,0 +1,77 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {ArrowRight, BookOpen, Code2, Star} from 'lucide-react';
const STEPS = [
{icon: Code2, title: '1. Write your skill', desc: 'Define prompts, tools, and behaviors in a skill manifest YAML file.'},
{icon: BookOpen, title: '2. Test locally', desc: 'Use the CLI to simulate agent runs and validate outputs before publishing.'},
{icon: Star, title: '3. Publish to registry', desc: 'Push to the GitDataAI Skill Registry with version tags and metadata.'},
];
export default function SkillsPublishPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
<div className="text-xs text-zinc-400 mb-6">
<button onClick={() => navigate('/skills')} className="hover:text-zinc-600">Skills</button>
<span className="mx-2">/</span> Publish a Skill
</div>
<div className="mb-20">
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight mb-4">
Publish a Skill
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl">
Turn your best agent behaviors into reusable, versioned skills and share them with the community or keep them private to your workspace.
</p>
</div>
{/* Skill manifest demo */}
<div
className="rounded-3xl border border-zinc-200 dark:border-zinc-800 bg-zinc-950 dark:bg-zinc-900 p-6 font-mono text-xs mb-16 overflow-x-auto">
<div className="text-zinc-500 mb-3 text-[10px] uppercase tracking-widest">skill.yaml</div>
<pre className="text-zinc-300 leading-6">
{`name: senior-react-dev
version: "1.2.0"
description: Build production React components
author: acme-team
tools:
- read_file
- write_file
- run_tests
prompt: |
You are a senior React developer...
trigger:
keywords: ["react", "component", "frontend"]
rate_limit: 60 # runs per hour`}
</pre>
</div>
{/* Steps */}
<div className="mb-16">
<h2 className="text-2xl font-semibold mb-8">How It Works</h2>
<div className="grid md:grid-cols-3 gap-6">
{STEPS.map(s => (
<div key={s.title}
className="p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<s.icon className="h-5 w-5 text-zinc-500 mb-3"/>
<h3 className="text-sm font-semibold mb-1">{s.title}</h3>
<p className="text-xs text-zinc-500 dark:text-zinc-400 leading-relaxed">{s.desc}</p>
</div>
))}
</div>
</div>
<div className="text-center">
<button onClick={() => navigate('/auth/register')}
className="h-11 px-8 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors inline-flex items-center gap-2">
Publish Your First Skill <ArrowRight className="h-4 w-4"/>
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -0,0 +1,99 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {Cpu, DollarSign, ShieldCheck} from 'lucide-react';
const LIMITS = [
{tier: 'Free', tokens: '100K', compute: '1x', agents: '3'},
{tier: 'Pro', tokens: '10M', compute: '4x', agents: 'Unlimited'},
{tier: 'Enterprise', tokens: 'Custom', compute: 'Dedicated', agents: 'Unlimited'},
];
export default function SolutionsGovernancePage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
<div className="text-xs text-zinc-400 mb-6">
<button onClick={() => navigate('/solutions')} className="hover:text-zinc-600">Solutions</button>
<span className="mx-2">/</span> Compute Governance
</div>
<div className="mb-20">
<div
className="h-12 w-12 rounded-xl bg-zinc-100 dark:bg-zinc-800/50 flex items-center justify-center mb-6">
<Cpu className="h-6 w-6 text-zinc-600 dark:text-zinc-400"/>
</div>
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight mb-4">
Compute Governance
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl">
Unified management of LLM tokens and compute resources across your entire agent fleet. Set budgets, enforce limits, and get full cost visibility.
</p>
</div>
{/* Live usage */}
<div
className="rounded-3xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/50 p-6 mb-16">
<div className="flex items-center justify-between mb-4">
<span className="text-xs font-semibold">Monthly Compute Budget</span>
<span
className="text-xs px-2 py-0.5 rounded-full bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-400">75% used</span>
</div>
<div className="h-2 rounded-full bg-zinc-200 dark:bg-zinc-800 mb-4">
<div className="h-2 rounded-full bg-zinc-900 dark:bg-white w-[75%]"/>
</div>
<div className="grid grid-cols-3 gap-4 text-center">
<div>
<div className="text-lg font-semibold">7.5M</div>
<div className="text-[10px] text-zinc-500">tokens used</div>
</div>
<div>
<div className="text-lg font-semibold">$23.40</div>
<div className="text-[10px] text-zinc-500">total cost</div>
</div>
<div>
<div className="text-lg font-semibold">2.5M</div>
<div className="text-[10px] text-zinc-500">tokens remaining</div>
</div>
</div>
</div>
{/* Limits */}
<div className="mb-16">
<h2 className="text-2xl font-semibold mb-8">Limits by Tier</h2>
<div className="grid md:grid-cols-3 gap-5">
{LIMITS.map(l => (
<div key={l.tier}
className="p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<h3 className="text-sm font-semibold mb-4">{l.tier}</h3>
<div className="space-y-3">
<div className="flex justify-between text-xs">
<span className="text-zinc-500">Monthly tokens</span>
<span className="font-medium">{l.tokens}</span>
</div>
<div className="flex justify-between text-xs">
<span className="text-zinc-500">Compute multiplier</span>
<span className="font-medium">{l.compute}</span>
</div>
<div className="flex justify-between text-xs">
<span className="text-zinc-500">Max agents</span>
<span className="font-medium">{l.agents}</span>
</div>
</div>
</div>
))}
</div>
</div>
<div className="text-center">
<button onClick={() => navigate('/auth/register')}
className="h-11 px-8 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors">
Set Up Compute Governance
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -0,0 +1,80 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {Brain, GitBranch, RotateCcw} from 'lucide-react';
export default function SolutionsMemoryPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
<div className="text-xs text-zinc-400 mb-6">
<button onClick={() => navigate('/solutions')} className="hover:text-zinc-600">Solutions</button>
<span className="mx-2">/</span> Agent Memory
</div>
<div className="mb-20">
<div
className="h-12 w-12 rounded-xl bg-zinc-100 dark:bg-zinc-800/50 flex items-center justify-center mb-6">
<Brain className="h-6 w-6 text-zinc-600 dark:text-zinc-400"/>
</div>
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight mb-4">
Agent Memory
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl">
Git-native long-term memory for AI agents. Branch, commit, merge, and rollback AI context the same way you manage source code.
</p>
</div>
{/* Git-like interface demo */}
<div
className="rounded-3xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/50 p-6 font-mono text-xs mb-16 overflow-x-auto">
<div className="mb-4 text-zinc-400 text-[10px] uppercase tracking-widest">Agent Memory workspace: acme-agent-ctx</div>
<div className="space-y-2 text-zinc-700 dark:text-zinc-300">
<div className="flex gap-3">
<span className="text-zinc-400 shrink-0">$</span>
<span>gitdata memory branch -c "tune-for-rag-v3"</span>
</div>
<div className="text-zinc-500 pl-6"> Branched from 'main'. Switched to 'tune-for-rag-v3'.</div>
<div className="flex gap-3">
<span className="text-zinc-400 shrink-0">$</span>
<span>gitdata memory commit -m "Retrain embeddings on Q3 data"</span>
</div>
<div className="text-zinc-500 pl-6">[abc1234] Retrain embeddings on Q3 data 2.4k tokens updated.</div>
<div className="flex gap-3">
<span className="text-zinc-400 shrink-0">$</span>
<span>gitdata memory log --oneline</span>
</div>
{['abc1240 HEAD', '7b3c9a1 Tune retrieval threshold', 'def4567 Initial RAG setup'].map((h, i) => (
<div key={i} className="pl-6 text-zinc-500">{h}</div>
))}
</div>
</div>
{/* Git operations */}
<div className="grid md:grid-cols-3 gap-6 mb-16">
{[
{icon: GitBranch, title: 'Branch & Merge', desc: 'Experiment with different memory contexts. Merge when proven.'},
{icon: RotateCcw, title: 'Rollback', desc: 'Revert to any previous memory state instantly.'},
{icon: Brain, title: 'Semantic Search', desc: 'Find any past context by natural language query.'},
].map(item => (
<div key={item.title}
className="p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<item.icon className="h-5 w-5 text-zinc-500 mb-3"/>
<h3 className="text-sm font-semibold mb-1">{item.title}</h3>
<p className="text-xs text-zinc-500 dark:text-zinc-400">{item.desc}</p>
</div>
))}
</div>
<div className="text-center">
<button onClick={() => navigate('/auth/register')}
className="h-11 px-8 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors">
Try Agent Memory Free
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

106
src/app/solutions/page.tsx Normal file
View File

@ -0,0 +1,106 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {Bot, Code2, GitBranch, Network, Workflow} from 'lucide-react';
const SOLUTIONS = [
{
icon: Workflow,
title: 'Command as Service',
href: '/solutions',
desc: 'Every operation is a versioned command. Compose, audit, and replay your entire development workflow from a single CLI.',
badge: 'Core Concept',
},
{
icon: Code2,
title: 'Git Repositories',
href: '/solutions',
desc: 'Full Git operations — branches, commits, merges, diffs, and blame. HTTP and SSH access with built-in branch protection.',
badge: null,
},
{
icon: GitBranch,
title: 'Issues & Pull Requests',
href: '/solutions',
desc: 'Track issues, review code, and manage pull requests with inline comments, review threads, and configurable merge strategies.',
badge: null,
},
{
icon: Network,
title: 'Collaborative Rooms',
href: '/solutions/rooms',
desc: 'Real-time chat rooms where humans and AI agents work together. Persistent context, thread replies, and shared command history.',
badge: null,
},
{
icon: Bot,
title: 'AI Agents',
href: '/solutions',
desc: 'Deploy AI agents backed by persistent memory and a skill registry. Agents can read repos, run tools, and execute tasks autonomously.',
badge: null,
},
{
icon: Network,
title: 'Full Audit Trail',
href: '/solutions',
desc: 'Every code change, AI decision, and room action — logged, versioned, and queryable. Human-in-the-loop by design.',
badge: null,
},
];
export default function SolutionsPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
{/* Hero */}
<div className="text-center mb-20">
<h1 className="text-4xl md:text-6xl font-semibold tracking-tight mb-4">
Command as Service
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl mx-auto">
In GitDataAI, every action is a first-class command. Commands are versioned, auditable, and composable your development workflow is your API.
</p>
</div>
{/* Solutions grid */}
<div className="grid md:grid-cols-2 gap-5">
{SOLUTIONS.map(sol => (
<div key={sol.href}
className="p-7 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950 hover:border-zinc-300 dark:hover:border-zinc-700 transition-all cursor-pointer group"
onClick={() => navigate(sol.href)}>
<div className="flex items-start gap-4">
<div
className="h-11 w-11 rounded-xl bg-zinc-100 dark:bg-zinc-800/50 flex items-center justify-center shrink-0">
<sol.icon className="h-5 w-5 text-zinc-600 dark:text-zinc-400"/>
</div>
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
<h3 className="text-base font-semibold text-zinc-900 dark:text-zinc-100">{sol.title}</h3>
{sol.badge && (
<span
className="h-5 px-2 rounded-full bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 text-[10px] font-medium">
{sol.badge}
</span>
)}
</div>
<p className="text-sm text-zinc-500 dark:text-zinc-400 leading-relaxed">{sol.desc}</p>
<div
className="mt-3 text-xs font-medium text-zinc-400 group-hover:text-zinc-600 dark:group-hover:text-zinc-300 transition-colors flex items-center gap-1">
Learn more
<svg className="h-3 w-3" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M13 7l5 5m0 0l-5 5m5-5H6"/>
</svg>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -0,0 +1,94 @@
import {LandingLayout} from '@/components/landing/landing-layout';
import {useNavigate} from 'react-router-dom';
import {Bot, ShieldCheck, Users} from 'lucide-react';
const FEATURES = [
{title: 'Real-time Multi-modal', desc: 'Text, code, and structured data shared simultaneously in a single session.'},
{title: 'Human-in-the-Loop', desc: 'Approve, reject, or modify any agent action before it executes.'},
{title: 'Persistent Context', desc: 'Room state is versioned and resumable. Pick up where you left off.'},
{title: 'Access Control', desc: 'Invite-only rooms with fine-grained permission per agent and user.'},
{title: 'Audit Trail', desc: 'Every action, decision, and message is logged with timestamps.'},
{title: 'Multi-Agent Support', desc: 'Run multiple specialized agents in parallel within a single room.'},
];
export default function SolutionsRoomsPage() {
const navigate = useNavigate();
return (
<LandingLayout>
<section className="pt-24 pb-32">
<div className="mx-auto max-w-5xl px-6">
{/* Breadcrumb */}
<div className="text-xs text-zinc-400 mb-6">
<button onClick={() => navigate('/solutions')} className="hover:text-zinc-600">Solutions</button>
<span className="mx-2">/</span> Collaborative Rooms
</div>
{/* Hero */}
<div className="mb-20">
<div
className="h-12 w-12 rounded-xl bg-zinc-100 dark:bg-zinc-800/50 flex items-center justify-center mb-6">
<Users className="h-6 w-6 text-zinc-600 dark:text-zinc-400"/>
</div>
<h1 className="text-4xl md:text-5xl font-semibold tracking-tight mb-4">
Collaborative Rooms
</h1>
<p className="text-lg text-zinc-500 dark:text-zinc-500 max-w-2xl">
Multi-modal workspaces where humans and AI agents solve complex engineering tasks together in real-time. No more copy-pasting context between tools.
</p>
</div>
{/* Demo */}
<div
className="rounded-3xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900/50 p-6 mb-16">
<div className="flex items-center gap-2 mb-4">
<div className="h-2 w-2 rounded-full bg-red-400"/>
<div className="h-2 w-2 rounded-full bg-amber-400"/>
<div className="h-2 w-2 rounded-full bg-green-400"/>
<span className="ml-2 text-[10px] uppercase tracking-widest text-zinc-400">Room: feature-auth-audit</span>
</div>
<div className="space-y-3 font-mono text-xs">
<div className="flex gap-3">
<span className="text-zinc-400 shrink-0">12:04:01</span>
<span className="text-zinc-800 dark:text-zinc-200">// John assigns Agent-Reviewer to audit auth module</span>
</div>
<div className="flex gap-3 text-zinc-500">
<span className="shrink-0">12:04:02</span>
<span><Bot className="inline h-3 w-3 mr-1"/> Agent-Reviewer: Scanning 47 files in auth/...</span>
</div>
<div className="flex gap-3 text-zinc-500">
<span className="shrink-0">12:04:15</span>
<span><ShieldCheck className="inline h-3 w-3 mr-1 text-green-500"/> Agent-Reviewer: Flagged 3 issues. Awaiting approval.</span>
</div>
<div className="flex gap-3 text-zinc-500">
<span className="shrink-0">12:04:16</span>
<span className="text-amber-600 dark:text-amber-400"> Human approval required: Create fix PR?</span>
</div>
</div>
</div>
{/* Features */}
<div className="mb-16">
<h2 className="text-2xl font-semibold mb-8">Key Capabilities</h2>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-5">
{FEATURES.map(f => (
<div key={f.title}
className="p-5 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950">
<h3 className="text-sm font-semibold mb-1">{f.title}</h3>
<p className="text-xs text-zinc-500 dark:text-zinc-400 leading-relaxed">{f.desc}</p>
</div>
))}
</div>
</div>
{/* CTA */}
<div className="text-center">
<button onClick={() => navigate('/auth/register')}
className="h-11 px-8 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 rounded-full text-sm font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors">
Start with Collaborative Rooms
</button>
</div>
</div>
</section>
</LandingLayout>
);
}

View File

@ -17,8 +17,8 @@ export function WorkspaceRedirect() {
useEffect(() => { useEffect(() => {
if (isLoading) return; if (isLoading) return;
const first = data?.workspaces[0]; const first = data?.workspaces?.[0];
if (first) { if (first?.slug) {
navigate(`/w/${first.slug}`, {replace: true}); navigate(`/w/${first.slug}`, {replace: true});
} else { } else {
navigate('/init/workspace', {replace: true}); navigate('/init/workspace', {replace: true});

View File

@ -1,3 +1,4 @@
export {LandingNav} from './landing-nav'; export {LandingNav} from './landing-nav';
export {LandingFooter} from './landing-footer'; export {LandingFooter} from './landing-footer';
export {LandingHero, LandingFeatures, LandingHighlight} from './landing-sections'; export {LandingHero, LandingFeatures, LandingHighlight} from './landing-sections';
export {LandingLayout} from './landing-layout';

View File

@ -1,10 +1,17 @@
const FOOTER_LINKS = { const FOOTER_LINKS = {
Product: ['Features', 'Pricing', 'Changelog', 'Roadmap'], Platform: ['Git Repositories', 'Issues & PRs', 'Collaborative Rooms', 'AI Agents'],
Developers: ['Documentation', 'API Reference', 'GitHub', 'Status'], Skills: ['Skill Registry', 'Publish a Skill', 'Skill Documentation', 'Community'],
Resources: ['Blog', 'Guides', 'Community', 'Support'], Developers: ['Documentation', 'CLI Reference', 'API Reference', 'Status'],
Company: ['About', 'Careers', 'Contact', 'Privacy'], Company: ['About', 'Careers', 'Contact', 'Privacy'],
}; };
const FOOTER_HREFS: Record<string, string[]> = {
Platform: ['/solutions', '/solutions', '/solutions/rooms', '/solutions'],
Skills: ['/skills', '/skills/publish', '/skills/docs', '/network'],
Developers: ['/docs', '/docs', '/network/api', '/status'],
Company: ['/about', '/careers', '/contact', '/privacy'],
};
interface LandingFooterProps { interface LandingFooterProps {
onRegister: () => void; onRegister: () => void;
} }
@ -38,28 +45,31 @@ export function LandingFooter({onRegister}: LandingFooterProps) {
<span className="font-semibold text-sm text-zinc-900 dark:text-zinc-100">GitDataAI</span> <span className="font-semibold text-sm text-zinc-900 dark:text-zinc-100">GitDataAI</span>
</div> </div>
<p className="text-xs text-zinc-500 leading-relaxed"> <p className="text-xs text-zinc-500 leading-relaxed">
Infrastructure for the next billion AI Agents. The unified platform for code collaboration and AI-powered development.
Built for reliability, transparency, and collaboration. Built for teams that ship.
</p> </p>
</div> </div>
{/* Link columns */} {/* Link columns */}
{Object.entries(FOOTER_LINKS).map(([cat, links]) => ( {Object.entries(FOOTER_LINKS).map(([cat, links]) => {
<div key={cat}> const hrefs = FOOTER_HREFS[cat];
<h4 className="text-xs font-semibold mb-4 uppercase tracking-widest text-zinc-900 dark:text-zinc-100"> return (
{cat} <div key={cat}>
</h4> <h4 className="text-xs font-semibold mb-4 uppercase tracking-widest text-zinc-900 dark:text-zinc-100">
<ul className="space-y-3 text-xs text-zinc-500"> {cat}
{links.map(link => ( </h4>
<li key={link}> <ul className="space-y-3 text-xs text-zinc-500">
<a href="#" className="hover:text-zinc-900 dark:hover:text-zinc-100 transition-colors"> {links.map((link, i) => (
{link} <li key={link}>
</a> <a href={hrefs[i]} className="hover:text-zinc-900 dark:hover:text-zinc-100 transition-colors">
</li> {link}
))} </a>
</ul> </li>
</div> ))}
))} </ul>
</div>
);
})}
</div> </div>
</div> </div>
</footer> </footer>

View File

@ -0,0 +1,22 @@
import {useNavigate} from 'react-router-dom';
import {LandingNav} from '@/components/landing/landing-nav';
import {LandingFooter} from '@/components/landing/landing-footer';
interface LandingLayoutProps {
children: React.ReactNode;
}
export function LandingLayout({children}: LandingLayoutProps) {
const navigate = useNavigate();
const handleRegister = () => navigate('/auth/register');
return (
<div className="min-h-screen bg-white dark:bg-zinc-950 text-zinc-900 dark:text-zinc-100 font-sans antialiased">
<div
className="fixed inset-0 bg-[linear-gradient(to_right,#09090b08_1px,transparent_1px),linear-gradient(to_bottom,#09090b08_1px,transparent_1px)] bg-[size:24px_24px] pointer-events-none"/>
<LandingNav/>
<main>{children}</main>
<LandingFooter onRegister={handleRegister}/>
</div>
);
}

View File

@ -1,9 +1,46 @@
import {useEffect, useRef, useState} from 'react';
import {useNavigate} from 'react-router-dom'; import {useNavigate} from 'react-router-dom';
const NAV_ITEMS = ['Solutions', 'Skills', 'Network', 'Pricing']; const POP_ITEMS = {
Platform: [
{title: 'Git Repositories', href: '/solutions', desc: 'Branches, commits, PRs, branch protection'},
{title: 'Collaborative Rooms', href: '/solutions/rooms', desc: 'Real-time human-AI workspaces'},
{title: 'AI Agents', href: '/solutions', desc: 'Persistent memory, tools, skill registry'},
{title: 'Command as Service', href: '/solutions', desc: 'Versioned, auditable, composable commands'},
],
Skills: [
{title: 'Explore Skills', href: '/skills', desc: 'Browse the community skill library'},
{title: 'Publish a Skill', href: '/skills/publish', desc: 'Share your agent behavior'},
{title: 'Skill Documentation', href: '/skills/docs', desc: 'Build and test skills locally'},
],
Network: [
{title: 'Explore Network', href: '/network', desc: 'Discover agents and workspaces'},
{title: 'Public Rooms', href: '/network/rooms', desc: 'Join open collaborative sessions'},
{title: 'Developer API', href: '/network/api', desc: 'Integrate with the network'},
],
Pricing: [
{title: 'Plans & Pricing', href: '/pricing', desc: 'Compare free and paid tiers'},
{title: 'Enterprise', href: '/pricing/enterprise', desc: 'Custom deployment & SLA'},
{title: 'Billing FAQ', href: '/pricing/faq', desc: 'Common billing questions'},
],
};
type PopKey = keyof typeof POP_ITEMS;
export function LandingNav() { export function LandingNav() {
const navigate = useNavigate(); const navigate = useNavigate();
const [openPop, setOpenPop] = useState<PopKey | null>(null);
const popRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handler = (e: MouseEvent) => {
if (popRef.current && !popRef.current.contains(e.target as Node)) {
setOpenPop(null);
}
};
document.addEventListener('mousedown', handler);
return () => document.removeEventListener('mousedown', handler);
}, []);
return ( return (
<header <header
@ -18,12 +55,40 @@ export function LandingNav() {
</div> </div>
{/* Nav links */} {/* Nav links */}
<nav className="hidden md:flex items-center gap-6"> <nav className="hidden md:flex items-center gap-1" ref={popRef}>
{NAV_ITEMS.map(item => ( {(Object.keys(POP_ITEMS) as PopKey[]).map(key => (
<a key={item} href="#" <div key={key} className="relative">
className="text-xs font-medium text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 uppercase tracking-widest transition-colors"> <button
{item} onClick={() => setOpenPop(openPop === key ? null : key)}
</a> onMouseEnter={() => setOpenPop(key)}
className="h-8 px-3 flex items-center gap-1 text-xs font-medium text-zinc-500 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 uppercase tracking-widest transition-colors rounded-full">
{key}
<svg className={`h-3 w-3 transition-transform ${openPop === key ? 'rotate-180' : ''}`}
fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7"/>
</svg>
</button>
{openPop === key && (
<div
className="absolute top-full left-0 mt-2 w-64 rounded-2xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 shadow-xl overflow-hidden z-50">
{POP_ITEMS[key].map(item => (
<button
key={item.href}
onClick={() => {
navigate(item.href);
setOpenPop(null);
}}
className="w-full flex flex-col items-start px-4 py-3 hover:bg-zinc-50 dark:hover:bg-zinc-800/50 transition-colors text-left">
<span
className="text-sm font-medium text-zinc-900 dark:text-zinc-100">{item.title}</span>
<span
className="text-xs text-zinc-500 dark:text-zinc-400">{item.desc}</span>
</button>
))}
</div>
)}
</div>
))} ))}
</nav> </nav>

View File

@ -1,36 +1,46 @@
import {motion} from 'framer-motion'; import {motion} from 'framer-motion';
import {Bot, Brain, Cpu, History, Layers, Network, ShieldCheck, Workflow} from 'lucide-react'; import {Bot, Brain, Code2, GitBranch, History, Layers, Network, ShieldCheck, Workflow, Zap} from 'lucide-react';
const FEATURES = [ const FEATURES = [
{ {
icon: Network, icon: Code2,
title: 'Collaborative Rooms', title: 'Git Repositories',
description: 'Multi-modal workspaces where humans and AI Agents solve complex engineering tasks together in real-time.', description: 'Full Git operations — branches, commits, merges, and diffs. HTTP and SSH access. Built-in branch protection and access control.',
}, },
{ {
icon: Brain, icon: GitBranch,
title: 'Agent Memory (Git-Native)', title: 'Issues & Pull Requests',
description: 'Version-controlled long-term memory for Agents. Branch, commit, and revert AI context just like code.', description: 'Track issues, review code, and manage pull requests with inline comments, review threads, and merge strategies.',
}, },
{ {
icon: Workflow, icon: Workflow,
title: 'Skill Registry', title: 'Command as Service',
description: 'Package successful Agent behaviors into reusable "Skills". The new npm for the AI-native era.', description: 'Every action is a versioned command. Compose, audit, and replay your entire development workflow. Your CLI is also your API.',
},
{
icon: Network,
title: 'Collaborative Rooms',
description: 'Real-time chat rooms where humans and AI agents work together. Share context, run commands, review code — all in one thread.',
},
{
icon: Bot,
title: 'AI Agents',
description: 'Deploy AI agents backed by persistent, versioned memory. Agents read your codebase, run tools, and execute tasks on your behalf.',
}, },
{ {
icon: Layers, icon: Layers,
title: 'Prompt Engineering Ops', title: 'Skill Registry',
description: 'Manage, test, and deploy prompts with the same rigor as production source code.', description: 'Package agent behaviors as reusable Skills. Versioned, testable, and composable. Your best agent workflows become shared infrastructure.',
}, },
{ {
icon: History, icon: History,
title: 'Traceable Autonomy', title: 'Full Audit Trail',
description: 'Every decision made by an Agent is logged, versioned, and auditable. Human-in-the-loop by design.', description: 'Every AI decision, every code change, every room message — logged, versioned, and queryable. Human-in-the-loop by design.',
}, },
{ {
icon: Cpu, icon: Brain,
title: 'Compute Governance', title: 'Agent Memory',
description: 'Unified management of LLM tokens and compute resources across your entire Agent fleet.', description: 'Persistent, git-native context for AI agents. Branch, commit, and roll back agent memory just like source code.',
}, },
]; ];
@ -71,7 +81,7 @@ export function LandingHero({onRegister}: { onRegister: () => void }) {
className="animate-ping absolute inline-flex h-full w-full rounded-full bg-zinc-400 opacity-75"/> className="animate-ping absolute inline-flex h-full w-full rounded-full bg-zinc-400 opacity-75"/>
<span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-zinc-500"/> <span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-zinc-500"/>
</span> </span>
The OS for Human-Agent Collaboration Git + Chat + AI Agents · Command as Service
</span> </span>
</motion.div> </motion.div>
@ -89,9 +99,8 @@ export function LandingHero({onRegister}: { onRegister: () => void }) {
{/* Subtitle */} {/* Subtitle */}
<motion.p variants={fadeUp} <motion.p variants={fadeUp}
className="text-lg text-zinc-500 dark:text-zinc-500 mb-12 max-w-2xl mx-auto leading-relaxed"> className="text-lg text-zinc-500 dark:text-zinc-500 mb-12 max-w-2xl mx-auto leading-relaxed">
GitDataAI is the unified infrastructure for the Agentic era. GitDataAI is the unified platform for code collaboration and AI-powered development.
Version control your Agent's memory, deploy collaborative rooms, and scale your AI workforce Git repositories, real-time rooms, AI agents, and versioned commands all in one place.
with engineering rigor.
</motion.p> </motion.p>
{/* CTAs */} {/* CTAs */}
@ -99,7 +108,7 @@ export function LandingHero({onRegister}: { onRegister: () => void }) {
className="flex flex-col sm:flex-row items-center justify-center gap-3"> className="flex flex-col sm:flex-row items-center justify-center gap-3">
<button onClick={onRegister} <button onClick={onRegister}
className="h-11 px-8 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-all rounded-full font-medium text-sm flex items-center gap-2"> className="h-11 px-8 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-all rounded-full font-medium text-sm flex items-center gap-2">
Deploy your first Agent Start Building
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2}
d="M13 7l5 5m0 0l-5 5m5-5H6"/> d="M13 7l5 5m0 0l-5 5m5-5H6"/>
@ -107,7 +116,7 @@ export function LandingHero({onRegister}: { onRegister: () => void }) {
</button> </button>
<button <button
className="h-11 px-8 rounded-full border border-zinc-200 dark:border-zinc-800 hover:bg-zinc-50 dark:hover:bg-zinc-900/50 text-zinc-700 dark:text-zinc-300 font-medium text-sm transition-all"> className="h-11 px-8 rounded-full border border-zinc-200 dark:border-zinc-800 hover:bg-zinc-50 dark:hover:bg-zinc-900/50 text-zinc-700 dark:text-zinc-300 font-medium text-sm transition-all">
Read Whitepaper View Documentation
</button> </button>
</motion.div> </motion.div>
@ -123,7 +132,7 @@ export function LandingHero({onRegister}: { onRegister: () => void }) {
<div className="w-2.5 h-2.5 rounded-full bg-zinc-300 dark:bg-zinc-700"/> <div className="w-2.5 h-2.5 rounded-full bg-zinc-300 dark:bg-zinc-700"/>
<div className="w-2.5 h-2.5 rounded-full bg-zinc-300 dark:bg-zinc-700"/> <div className="w-2.5 h-2.5 rounded-full bg-zinc-300 dark:bg-zinc-700"/>
</div> </div>
<span className="text-[10px] uppercase tracking-widest text-zinc-400 font-medium">Human-Agent Protocol v1.0</span> <span className="text-[10px] uppercase tracking-widest text-zinc-400 font-medium">gitdata Command as Service</span>
</div> </div>
{/* Terminal content */} {/* Terminal content */}
@ -131,23 +140,30 @@ export function LandingHero({onRegister}: { onRegister: () => void }) {
<div className="flex gap-3 mb-3"> <div className="flex gap-3 mb-3">
<span className="text-zinc-400"></span> <span className="text-zinc-400"></span>
<span className="text-zinc-800 dark:text-zinc-200"> <span className="text-zinc-800 dark:text-zinc-200">
gitdata <span className="text-zinc-500">agent create</span> --template senior-react-dev gitdata <span className="text-zinc-500">repo create</span> --name api-service --visibility private
</span> </span>
</div> </div>
<div className="text-zinc-400 mb-3 ml-6 leading-6"> <div className="text-zinc-400 mb-3 ml-6 leading-6">
[12:05:01] <Bot className="inline h-3 w-3 mr-1 text-zinc-500"/> Initializing Agent 'Nexus-7'...<br/> [12:05:01] <Code2 className="inline h-3 w-3 mr-1 text-zinc-500"/> Repository 'api-service' created<br/>
[12:05:02] <Brain className="inline h-3 w-3 mr-1 text-zinc-500"/> Injecting Long-term Memory from 'workspace-ctx-v4.2'<br/> [12:05:02] <GitBranch className="inline h-3 w-3 mr-1 text-zinc-500"/> Default branch 'main' initialized<br/>
[12:05:03] <ShieldCheck className="inline h-3 w-3 mr-1 text-zinc-500"/> Compliance policy 'SOX-2' verified. [12:05:03] <Zap className="inline h-3 w-3 mr-1 text-zinc-500"/> Webhook endpoint ready: POST /api/hooks/gitdata/abc123
</div> </div>
<div className="flex gap-3 mb-3"> <div className="flex gap-3 mb-3">
<span className="text-zinc-400"></span> <span className="text-zinc-400"></span>
<span className="text-zinc-800 dark:text-zinc-200"> <span className="text-zinc-800 dark:text-zinc-200">
gitdata <span className="text-zinc-500">commit</span> -m "Tuned Agent memory for better RAG performance" gitdata <span className="text-zinc-500">room create</span> --name api-review --project api-service
</span>
</div>
<div className="flex gap-3 mb-3">
<span className="text-zinc-400"></span>
<span className="text-zinc-800 dark:text-zinc-200">
gitdata <span className="text-zinc-500">agent deploy</span> --name reviewer --room api-review --skill CodeReviewer
</span> </span>
</div> </div>
<div className="ml-6 text-zinc-500 dark:text-zinc-400"> <div className="ml-6 text-zinc-500 dark:text-zinc-400">
Memory branch 'main' updated. [commit_hash: 7a2f9b1]<br/> Agent 'reviewer' joined room 'api-review'.<br/>
AI Skill 'Code-Optimizer' published to Registry. Skill 'CodeReviewer' loaded. Watching for new pull requests.<br/>
Command registered: <span className="text-zinc-600 dark:text-zinc-400">gitdata pr review</span>
</div> </div>
</div> </div>
</div> </div>
@ -165,16 +181,16 @@ export function LandingFeatures() {
{/* Section header */} {/* Section header */}
<div className="text-center mb-16"> <div className="text-center mb-16">
<h2 className="text-3xl md:text-4xl font-semibold tracking-tight mb-3"> <h2 className="text-3xl md:text-4xl font-semibold tracking-tight mb-3">
Built for the next generation of software. Code. Issues. Rooms. Agents. Commands.
</h2> </h2>
<p className="text-zinc-500 dark:text-zinc-500"> <p className="text-zinc-500 dark:text-zinc-500">
Stop building black-box AI. Start engineering transparent Agent systems. Everything your team and AI agents need to build software in one place, versioned like code.
</p> </p>
</div> </div>
{/* Features grid */} {/* Features grid */}
<motion.div variants={stagger} initial="hidden" whileInView="visible" viewport={{once: true}} <motion.div variants={stagger} initial="hidden" whileInView="visible" viewport={{once: true}}
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5"> className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-5">
{FEATURES.map((f, i) => ( {FEATURES.map((f, i) => (
<motion.div <motion.div
key={i} key={i}
@ -195,9 +211,9 @@ export function LandingFeatures() {
} }
const HIGHLIGHTS = [ const HIGHLIGHTS = [
{t: 'Multi-Agent Orchestration', d: 'Let different Agents specialize in different tasks.'}, {t: 'Command as Service', d: 'Every operation is a versioned command. Audit, replay, and compose them like building blocks.'},
{t: 'Semantic Versioning', d: 'Roll back Agent logic to any point in the discussion.'}, {t: 'Human-in-the-Loop', d: 'AI agents request approval before destructive actions. You stay in control.'},
{t: 'Human-in-the-Loop', d: 'Approve critical Agent actions with one click.'}, {t: 'Git-Native Everything', d: 'Your agents\' memory, skills, and audit logs are stored in Git — branch, commit, diff.'},
]; ];
export function LandingHighlight() { export function LandingHighlight() {
@ -209,13 +225,10 @@ export function LandingHighlight() {
<div> <div>
<div className="h-px w-12 bg-zinc-300 dark:bg-zinc-700 mb-8"/> <div className="h-px w-12 bg-zinc-300 dark:bg-zinc-700 mb-8"/>
<h2 className="text-3xl md:text-4xl font-semibold tracking-tight leading-tight mb-6"> <h2 className="text-3xl md:text-4xl font-semibold tracking-tight leading-tight mb-6">
Interaction is the{" "} Commands are the new commits.
<span className="text-zinc-400">New Code</span>.
</h2> </h2>
<p className="text-zinc-500 dark:text-zinc-500 mb-8 leading-relaxed"> <p className="text-zinc-500 dark:text-zinc-500 mb-8 leading-relaxed">
In GitDataAI, conversations aren't just chatsthey are executable streams of intent. In GitDataAI, every action creating a repo, opening a PR, deploying an agent is a first-class command. Commands are versioned, diffable, and composable. Your development workflow becomes an auditable, replayable stream of intent.
Our Collaborative Rooms capture context, version it, and allow Agents to take
autonomous actions within a governed environment.
</p> </p>
{/* Feature list */} {/* Feature list */}
@ -249,10 +262,10 @@ export function LandingHighlight() {
className="h-5 w-5 rounded-full bg-zinc-200 dark:bg-zinc-700 flex items-center justify-center text-[9px] font-bold text-zinc-500"> className="h-5 w-5 rounded-full bg-zinc-200 dark:bg-zinc-700 flex items-center justify-center text-[9px] font-bold text-zinc-500">
JD JD
</div> </div>
<span className="text-xs font-medium text-zinc-600 dark:text-zinc-400">John Doe (Dev)</span> <span className="text-xs font-medium text-zinc-600 dark:text-zinc-400">John Doe</span>
</div> </div>
<p className="text-xs text-zinc-700 dark:text-zinc-300"> <p className="text-xs text-zinc-700 dark:text-zinc-300">
@Agent-Reviewer, please audit the memory leaks in our skill-store module. @reviewer, please audit the auth module on the feature/oauth branch.
</p> </p>
</div> </div>
@ -262,15 +275,18 @@ export function LandingHighlight() {
<div className="flex items-center gap-2 mb-2"> <div className="flex items-center gap-2 mb-2">
<Bot className="h-3.5 w-3.5 text-zinc-500"/> <Bot className="h-3.5 w-3.5 text-zinc-500"/>
<span <span
className="text-xs font-medium text-zinc-500">Agent-Reviewer</span> className="text-xs font-medium text-zinc-500">reviewer</span>
</div> </div>
<p className="text-xs text-zinc-600 dark:text-zinc-400 mb-3"> <p className="text-xs text-zinc-600 dark:text-zinc-400 mb-3">
Audit complete. Found 2 leaks in `useMemory.ts`. Suggesting fix via Git PR... Audit complete on feature/oauth. Found 3 issues 1 critical (token validation bypass). Creating fix PR...
</p> </p>
<div className="rounded-md border border-zinc-200 dark:border-zinc-700 bg-zinc-50 dark:bg-zinc-800 font-mono text-[10px] text-zinc-500 p-2 mb-3">
gitdata pr create --title "fix: resolve token validation bypass" --from feature/oauth --auto-merge
</div>
<div className="flex gap-2"> <div className="flex gap-2">
<button <button
className="h-6 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 text-[10px] px-3 rounded-md font-medium transition-colors"> className="h-6 bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 text-[10px] px-3 rounded-md font-medium transition-colors">
Approve Fix Approve
</button> </button>
<button <button
className="h-6 border border-zinc-200 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 text-[10px] px-3 rounded-md font-medium transition-colors"> className="h-6 border border-zinc-200 dark:border-zinc-700 text-zinc-600 dark:text-zinc-400 text-[10px] px-3 rounded-md font-medium transition-colors">