Initial commit — RoadCode import
This commit is contained in:
146
src/components/ActivityFeed.tsx
Normal file
146
src/components/ActivityFeed.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
interface Activity {
|
||||
id: string
|
||||
type: 'deploy' | 'task' | 'alert' | 'agent' | 'memory' | 'push' | 'pr' | 'issue'
|
||||
message: string
|
||||
timestamp: string
|
||||
agent?: string
|
||||
url?: string
|
||||
}
|
||||
|
||||
interface ActivityFeedProps {
|
||||
activities?: Activity[]
|
||||
liveUpdates?: boolean
|
||||
}
|
||||
|
||||
const typeIcons: Record<string, string> = {
|
||||
deploy: '🚀',
|
||||
task: '✅',
|
||||
alert: '⚠️',
|
||||
agent: '🤖',
|
||||
memory: '📚',
|
||||
push: '⬆️',
|
||||
pr: '🔀',
|
||||
issue: '📋',
|
||||
}
|
||||
|
||||
const typeColors: Record<string, string> = {
|
||||
deploy: 'text-blue-400',
|
||||
task: 'text-green-400',
|
||||
alert: 'text-yellow-400',
|
||||
agent: 'text-purple-400',
|
||||
memory: 'text-pink-400',
|
||||
push: 'text-cyan-400',
|
||||
pr: 'text-orange-400',
|
||||
issue: 'text-red-400',
|
||||
}
|
||||
|
||||
function timeAgo(date: string): string {
|
||||
const seconds = Math.floor((Date.now() - new Date(date).getTime()) / 1000)
|
||||
if (seconds < 60) return `${seconds}s ago`
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
if (minutes < 60) return `${minutes}m ago`
|
||||
const hours = Math.floor(minutes / 60)
|
||||
if (hours < 24) return `${hours}h ago`
|
||||
return `${Math.floor(hours / 24)}d ago`
|
||||
}
|
||||
|
||||
function mapGitHubEvent(event: any): Activity | null {
|
||||
const repo = event.repo?.name?.replace('BlackRoad-OS/', '') || 'unknown'
|
||||
const base = { id: event.id, timestamp: timeAgo(event.created_at) }
|
||||
|
||||
switch (event.type) {
|
||||
case 'PushEvent':
|
||||
const commits = event.payload?.commits?.length || 1
|
||||
return { ...base, type: 'push', message: `Pushed ${commits} commit${commits > 1 ? 's' : ''} to ${repo}` }
|
||||
case 'PullRequestEvent':
|
||||
return { ...base, type: 'pr', message: `${event.payload?.action} PR in ${repo}`, url: event.payload?.pull_request?.html_url }
|
||||
case 'IssuesEvent':
|
||||
return { ...base, type: 'issue', message: `${event.payload?.action} issue in ${repo}` }
|
||||
case 'CreateEvent':
|
||||
return { ...base, type: 'deploy', message: `Created ${event.payload?.ref_type} in ${repo}` }
|
||||
case 'WatchEvent':
|
||||
return { ...base, type: 'agent', message: `Starred ${repo}`, agent: event.actor?.login }
|
||||
case 'ForkEvent':
|
||||
return { ...base, type: 'task', message: `Forked ${repo}` }
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export default function ActivityFeed({ activities: initialActivities, liveUpdates = true }: ActivityFeedProps) {
|
||||
const [activities, setActivities] = useState<Activity[]>(initialActivities || [])
|
||||
const [loading, setLoading] = useState(!initialActivities)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (initialActivities) return
|
||||
|
||||
const fetchActivity = async () => {
|
||||
try {
|
||||
// Fetch from GitHub API (public events, no auth needed)
|
||||
const res = await fetch('https://api.github.com/orgs/BlackRoad-OS/events?per_page=15')
|
||||
if (!res.ok) throw new Error('Failed to fetch')
|
||||
const events = await res.json()
|
||||
const mapped = events.map(mapGitHubEvent).filter(Boolean) as Activity[]
|
||||
setActivities(mapped.slice(0, 10))
|
||||
setError(null)
|
||||
} catch (err) {
|
||||
setError('Could not load activity')
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
fetchActivity()
|
||||
if (liveUpdates) {
|
||||
const interval = setInterval(fetchActivity, 60000) // Refresh every minute
|
||||
return () => clearInterval(interval)
|
||||
}
|
||||
}, [initialActivities, liveUpdates])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="font-display text-xl font-semibold">Live Activity</h2>
|
||||
<div className="flex items-center gap-2">
|
||||
{liveUpdates && <span className="h-2 w-2 rounded-full bg-green-500 animate-pulse" />}
|
||||
<a href="https://github.com/BlackRoad-OS" target="_blank" rel="noopener" className="text-xs text-text-muted hover:text-text">
|
||||
View GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 space-y-3">
|
||||
{loading && (
|
||||
<div className="text-center py-8 text-text-dim">Loading activity...</div>
|
||||
)}
|
||||
{error && (
|
||||
<div className="text-center py-8 text-yellow-400">{error}</div>
|
||||
)}
|
||||
{!loading && !error && activities.map((activity) => (
|
||||
<div
|
||||
key={activity.id}
|
||||
className="flex items-start gap-3 rounded-lg border border-border bg-surface p-3 hover:border-accent/50 transition-colors"
|
||||
>
|
||||
<span className={`text-lg ${typeColors[activity.type] || 'text-gray-400'}`}>
|
||||
{typeIcons[activity.type] || '📌'}
|
||||
</span>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm">{activity.message}</p>
|
||||
<div className="mt-1 flex items-center gap-2 text-xs text-text-dim">
|
||||
{activity.agent && (
|
||||
<>
|
||||
<span className="text-accent">{activity.agent}</span>
|
||||
<span>•</span>
|
||||
</>
|
||||
)}
|
||||
<span>{activity.timestamp}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
76
src/components/AgentGrid.tsx
Normal file
76
src/components/AgentGrid.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
interface Agent {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
status: 'running' | 'idle' | 'error' | 'offline'
|
||||
lastActive: string
|
||||
tasks: number
|
||||
}
|
||||
|
||||
interface AgentGridProps {
|
||||
agents?: Agent[]
|
||||
}
|
||||
|
||||
const defaultAgents: Agent[] = [
|
||||
{ id: '1', name: 'Zeus', type: 'Orchestrator', status: 'running', lastActive: '2m ago', tasks: 12 },
|
||||
{ id: '2', name: 'Prometheus', type: 'Research', status: 'running', lastActive: 'now', tasks: 8 },
|
||||
{ id: '3', name: 'Athena', type: 'Analysis', status: 'idle', lastActive: '5m ago', tasks: 3 },
|
||||
{ id: '4', name: 'Hermes', type: 'Messenger', status: 'running', lastActive: 'now', tasks: 24 },
|
||||
{ id: '5', name: 'Apollo', type: 'Creative', status: 'running', lastActive: '1m ago', tasks: 5 },
|
||||
{ id: '6', name: 'Hephaestus', type: 'Builder', status: 'idle', lastActive: '10m ago', tasks: 2 },
|
||||
{ id: '7', name: 'Artemis', type: 'Monitor', status: 'running', lastActive: 'now', tasks: 47 },
|
||||
{ id: '8', name: 'Poseidon', type: 'Data', status: 'error', lastActive: '3m ago', tasks: 0 },
|
||||
]
|
||||
|
||||
const statusColors = {
|
||||
running: 'bg-green-500',
|
||||
idle: 'bg-yellow-500',
|
||||
error: 'bg-red-500',
|
||||
offline: 'bg-gray-500',
|
||||
}
|
||||
|
||||
const statusLabels = {
|
||||
running: 'Running',
|
||||
idle: 'Idle',
|
||||
error: 'Error',
|
||||
offline: 'Offline',
|
||||
}
|
||||
|
||||
export default function AgentGrid({ agents = defaultAgents }: AgentGridProps) {
|
||||
const runningCount = agents.filter(a => a.status === 'running').length
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="font-display text-xl font-semibold">AI Agents</h2>
|
||||
<div className="flex items-center gap-2 text-sm text-text-muted">
|
||||
<span className="flex h-2 w-2 rounded-full bg-green-500" />
|
||||
{runningCount} of {agents.length} running
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{agents.map((agent) => (
|
||||
<div
|
||||
key={agent.id}
|
||||
className="rounded-xl border border-border bg-surface p-4 transition hover:border-border-hover"
|
||||
>
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<h3 className="font-display font-semibold">{agent.name}</h3>
|
||||
<p className="text-xs text-text-muted">{agent.type}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className={`h-2 w-2 rounded-full ${statusColors[agent.status]}`} />
|
||||
<span className="text-xs text-text-muted">{statusLabels[agent.status]}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-4 flex items-center justify-between text-xs text-text-dim">
|
||||
<span>{agent.tasks} tasks</span>
|
||||
<span>{agent.lastActive}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
74
src/components/CTA.tsx
Normal file
74
src/components/CTA.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
export default function CTA() {
|
||||
return (
|
||||
<section className="px-6 py-24">
|
||||
<div className="mx-auto max-w-4xl rounded-2xl border border-border bg-gradient-to-br from-surface to-bg p-12 text-center">
|
||||
<h2 className="font-display text-3xl font-bold md:text-4xl">
|
||||
Ready to Build the <span className="gradient-text">Future</span>?
|
||||
</h2>
|
||||
<p className="mx-auto mt-6 max-w-xl text-text-muted">
|
||||
Join thousands of developers building with AI agents on BlackRoad.
|
||||
Start free, scale infinitely.
|
||||
</p>
|
||||
<div className="mt-10 flex flex-col items-center justify-center gap-4 sm:flex-row">
|
||||
<a
|
||||
href="/signup"
|
||||
className="inline-flex items-center gap-2 rounded-lg bg-text px-8 py-4 text-sm font-medium text-bg transition hover:opacity-90"
|
||||
>
|
||||
Get Started Free
|
||||
<svg
|
||||
className="h-4 w-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M13 7l5 5m0 0l-5 5m5-5H6"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="/contact"
|
||||
className="inline-flex items-center gap-2 rounded-lg border border-border px-8 py-4 text-sm font-medium text-text-muted transition hover:border-border-hover hover:text-text"
|
||||
>
|
||||
Talk to Sales
|
||||
</a>
|
||||
</div>
|
||||
<div className="mt-8 flex items-center justify-center gap-6 text-sm text-text-dim">
|
||||
<span className="flex items-center gap-2">
|
||||
<svg className="h-4 w-4 text-green-500" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
No credit card required
|
||||
</span>
|
||||
<span className="flex items-center gap-2">
|
||||
<svg className="h-4 w-4 text-green-500" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
5 agents free forever
|
||||
</span>
|
||||
<span className="flex items-center gap-2">
|
||||
<svg className="h-4 w-4 text-green-500" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
Self-host option
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
22
src/components/Cards.tsx
Normal file
22
src/components/Cards.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
const cards = [
|
||||
{ icon: '🤖', title: 'Agent Orchestration', desc: 'LangGraph + CrewAI powering 1,000 unique agents' },
|
||||
{ icon: '🧠', title: 'Lucidia Core', desc: 'Recursive AI with trinary logic and PS-SHA∞ memory' },
|
||||
{ icon: '⛓️', title: 'RoadChain', desc: 'Hyperledger Besu blockchain for agent identity' },
|
||||
{ icon: '🌐', title: 'Edge Network', desc: 'Cloudflare Workers + K3s for global deployment' },
|
||||
]
|
||||
|
||||
export default function Cards() {
|
||||
return (
|
||||
<section className="px-6 py-12">
|
||||
<div className="mx-auto grid max-w-6xl gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{cards.map((card) => (
|
||||
<div key={card.title} className="rounded-xl border border-border bg-surface p-6 transition hover:-translate-y-0.5 hover:border-border-hover">
|
||||
<div className="text-3xl">{card.icon}</div>
|
||||
<h3 className="mt-4 font-display text-base font-semibold">{card.title}</h3>
|
||||
<p className="mt-2 text-sm text-text-muted">{card.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
18
src/components/Footer.tsx
Normal file
18
src/components/Footer.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="border-t border-gray-800 px-6 py-12 text-center font-mono">
|
||||
<div className="flex justify-center gap-8">
|
||||
<a href="https://github.com/BlackRoad-OS" target="_blank" rel="noopener" className="text-sm text-gray-500 hover:text-white transition">
|
||||
GitHub
|
||||
</a>
|
||||
<a href="https://x.com/blackroad_io" target="_blank" rel="noopener" className="text-sm text-gray-500 hover:text-white transition">
|
||||
X
|
||||
</a>
|
||||
<a href="https://linkedin.com/company/blackroad-os" target="_blank" rel="noopener" className="text-sm text-gray-500 hover:text-white transition">
|
||||
LinkedIn
|
||||
</a>
|
||||
</div>
|
||||
<p className="mt-6 text-xs text-gray-600">© 2026 BlackRoad OS, Inc. · Delaware C-Corp</p>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
124
src/components/Header.tsx
Normal file
124
src/components/Header.tsx
Normal file
@@ -0,0 +1,124 @@
|
||||
import { useState } from 'react'
|
||||
|
||||
interface HeaderProps {
|
||||
user?: { name?: string; email: string } | null
|
||||
}
|
||||
|
||||
const navLinks = [
|
||||
{ href: '/products', label: 'Products' },
|
||||
{ href: '/features', label: 'Features' },
|
||||
{ href: '/pricing', label: 'Pricing' },
|
||||
{ href: '/about', label: 'About' },
|
||||
{ href: '/contact', label: 'Contact' },
|
||||
]
|
||||
|
||||
export default function Header({ user }: HeaderProps) {
|
||||
const [mobileOpen, setMobileOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 border-b border-border bg-bg/90 backdrop-blur-sm">
|
||||
<div className="mx-auto flex max-w-6xl items-center justify-between px-6 py-4">
|
||||
<a href="/" className="font-mono text-lg font-bold tracking-tight">
|
||||
BLACKROAD
|
||||
</a>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<nav className="hidden items-center gap-6 md:flex">
|
||||
{navLinks.map((link) => (
|
||||
<a
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className="text-sm text-text-muted transition hover:text-text"
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
))}
|
||||
<div className="h-4 w-px bg-border" />
|
||||
{user ? (
|
||||
<>
|
||||
<a href="/dashboard" className="text-sm text-text-muted hover:text-text">
|
||||
Dashboard
|
||||
</a>
|
||||
<span className="text-sm text-text">{user.name || user.email}</span>
|
||||
<a href="/api/logout" className="text-sm text-text-muted hover:text-text">
|
||||
Sign out
|
||||
</a>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<a href="/login" className="text-sm text-text-muted hover:text-text">
|
||||
Sign in
|
||||
</a>
|
||||
<a
|
||||
href="/signup"
|
||||
className="rounded-lg bg-text px-4 py-2 text-sm font-medium text-bg hover:opacity-90"
|
||||
>
|
||||
Get Started
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
</nav>
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
<button
|
||||
onClick={() => setMobileOpen(!mobileOpen)}
|
||||
className="flex h-10 w-10 items-center justify-center rounded-lg border border-border md:hidden"
|
||||
aria-label="Toggle menu"
|
||||
>
|
||||
<svg
|
||||
className="h-5 w-5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
{mobileOpen ? (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
||||
) : (
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
|
||||
)}
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Mobile Navigation */}
|
||||
{mobileOpen && (
|
||||
<nav className="border-t border-border bg-bg px-6 py-4 md:hidden">
|
||||
<div className="flex flex-col gap-4">
|
||||
{navLinks.map((link) => (
|
||||
<a
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
className="text-sm text-text-muted hover:text-text"
|
||||
>
|
||||
{link.label}
|
||||
</a>
|
||||
))}
|
||||
<div className="h-px bg-border" />
|
||||
{user ? (
|
||||
<>
|
||||
<a href="/dashboard" className="text-sm text-text-muted hover:text-text">
|
||||
Dashboard
|
||||
</a>
|
||||
<a href="/api/logout" className="text-sm text-text-muted hover:text-text">
|
||||
Sign out
|
||||
</a>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<a href="/login" className="text-sm text-text-muted hover:text-text">
|
||||
Sign in
|
||||
</a>
|
||||
<a
|
||||
href="/signup"
|
||||
className="inline-block rounded-lg bg-text px-4 py-2 text-center text-sm font-medium text-bg hover:opacity-90"
|
||||
>
|
||||
Get Started
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</nav>
|
||||
)}
|
||||
</header>
|
||||
)
|
||||
}
|
||||
36
src/components/Hero.tsx
Normal file
36
src/components/Hero.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
interface HeroProps {
|
||||
user?: { name?: string; email: string } | null
|
||||
}
|
||||
|
||||
export default function Hero({ user }: HeroProps) {
|
||||
return (
|
||||
<section className="px-6 py-32 text-center">
|
||||
<h1 className="font-mono text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl">
|
||||
BLACKROAD
|
||||
</h1>
|
||||
<p className="mx-auto mt-4 text-lg text-gray-400 font-mono">
|
||||
AI Agent Operating System
|
||||
</p>
|
||||
<p className="mx-auto mt-8 max-w-lg text-sm text-gray-500 font-mono leading-relaxed">
|
||||
Orchestrate autonomous AI agents across your infrastructure.<br />
|
||||
15 orgs. 1,085 repos. 205 deployments. One system.
|
||||
</p>
|
||||
<div className="mt-12 flex justify-center gap-4">
|
||||
{user ? (
|
||||
<a href="/dashboard" className="rounded bg-white px-6 py-3 text-sm font-medium text-black hover:opacity-90 font-mono">
|
||||
Dashboard →
|
||||
</a>
|
||||
) : (
|
||||
<>
|
||||
<a href="/signup" className="rounded bg-white px-6 py-3 text-sm font-medium text-black hover:opacity-90 font-mono">
|
||||
Get Started →
|
||||
</a>
|
||||
<a href="/login" className="rounded border border-gray-700 px-6 py-3 text-sm font-medium text-gray-400 hover:border-gray-500 hover:text-white font-mono">
|
||||
Sign In
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
43
src/components/Integrations.tsx
Normal file
43
src/components/Integrations.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
const integrations = [
|
||||
{ name: "OpenAI", icon: "🤖", category: "AI" },
|
||||
{ name: "Anthropic", icon: "🧬", category: "AI" },
|
||||
{ name: "Ollama", icon: "🦙", category: "AI" },
|
||||
{ name: "LangChain", icon: "🔗", category: "Framework" },
|
||||
{ name: "LangGraph", icon: "📊", category: "Framework" },
|
||||
{ name: "CrewAI", icon: "👥", category: "Framework" },
|
||||
{ name: "Cloudflare", icon: "☁️", category: "Cloud" },
|
||||
{ name: "Railway", icon: "🚂", category: "Cloud" },
|
||||
{ name: "Vercel", icon: "▲", category: "Cloud" },
|
||||
{ name: "GitHub", icon: "🐙", category: "DevOps" },
|
||||
{ name: "Stripe", icon: "💳", category: "Payments" },
|
||||
{ name: "Tailscale", icon: "🔒", category: "Network" },
|
||||
]
|
||||
|
||||
export default function Integrations() {
|
||||
return (
|
||||
<section className="border-y border-border bg-surface px-6 py-16">
|
||||
<div className="mx-auto max-w-4xl text-center">
|
||||
<h2 className="font-display text-2xl font-bold">
|
||||
Integrates with <span className="gradient-text">Everything</span>
|
||||
</h2>
|
||||
<p className="mt-4 text-text-muted">
|
||||
Connect to your favorite AI providers, frameworks, and cloud platforms
|
||||
</p>
|
||||
<div className="mt-10 flex flex-wrap justify-center gap-3">
|
||||
{integrations.map((int) => (
|
||||
<div
|
||||
key={int.name}
|
||||
className="flex items-center gap-2 rounded-full border border-border bg-bg px-4 py-2 transition hover:border-border-hover"
|
||||
>
|
||||
<span className="text-lg">{int.icon}</span>
|
||||
<span className="text-sm font-medium">{int.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-8 text-sm text-text-dim">
|
||||
+ 50 more integrations available via our SDK
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
23
src/components/QuickActions.tsx
Normal file
23
src/components/QuickActions.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
const actions = [
|
||||
{ icon: '➕', label: 'New Agent', href: '/dashboard/agents/new' },
|
||||
{ icon: '📊', label: 'Analytics', href: '/dashboard/analytics' },
|
||||
{ icon: '⚙️', label: 'Settings', href: '/dashboard/settings' },
|
||||
{ icon: '📚', label: 'Docs', href: '/docs' },
|
||||
]
|
||||
|
||||
export default function QuickActions() {
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{actions.map((action) => (
|
||||
<a
|
||||
key={action.label}
|
||||
href={action.href}
|
||||
className="flex items-center gap-2 rounded-lg border border-border bg-surface px-4 py-2 text-sm transition hover:border-border-hover hover:bg-bg"
|
||||
>
|
||||
<span>{action.icon}</span>
|
||||
<span>{action.label}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
30
src/components/Stats.tsx
Normal file
30
src/components/Stats.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
interface StatsProps {
|
||||
stats?: {
|
||||
agents?: string
|
||||
domains?: string
|
||||
github_orgs?: string
|
||||
repositories?: string
|
||||
}
|
||||
}
|
||||
|
||||
export default function Stats({ stats }: StatsProps) {
|
||||
const data = [
|
||||
{ value: stats?.agents || '1000', label: 'AI Agents' },
|
||||
{ value: stats?.domains || '21', label: 'Domains' },
|
||||
{ value: stats?.github_orgs || '16', label: 'GitHub Orgs' },
|
||||
{ value: stats?.repositories || '40+', label: 'Repositories' },
|
||||
]
|
||||
|
||||
return (
|
||||
<section className="border-t border-border px-6 py-12">
|
||||
<div className="mx-auto grid max-w-6xl grid-cols-2 gap-8 md:grid-cols-4">
|
||||
{data.map((stat) => (
|
||||
<div key={stat.label} className="text-center">
|
||||
<div className="font-display text-4xl font-bold text-accent">{stat.value}</div>
|
||||
<div className="mt-1 text-sm text-text-dim">{stat.label}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
54
src/components/Testimonials.tsx
Normal file
54
src/components/Testimonials.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
const testimonials = [
|
||||
{
|
||||
quote: "BlackRoad completely changed how we deploy AI agents. What used to take weeks now takes minutes.",
|
||||
author: "Sarah Chen",
|
||||
role: "CTO, Quantum Labs",
|
||||
avatar: "SC",
|
||||
},
|
||||
{
|
||||
quote: "The self-hosting option means we maintain complete control over our data. That's rare in this space.",
|
||||
author: "Marcus Johnson",
|
||||
role: "Security Lead, FinTech Corp",
|
||||
avatar: "MJ",
|
||||
},
|
||||
{
|
||||
quote: "Running 500 agents on edge hardware with sub-50ms latency. The architecture is genuinely impressive.",
|
||||
author: "Dr. Elena Rodriguez",
|
||||
role: "AI Research Director",
|
||||
avatar: "ER",
|
||||
},
|
||||
]
|
||||
|
||||
export default function Testimonials() {
|
||||
return (
|
||||
<section className="border-y border-border bg-surface px-6 py-16">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<h2 className="text-center font-display text-2xl font-bold">
|
||||
Trusted by <span className="gradient-text">Builders</span>
|
||||
</h2>
|
||||
<p className="mx-auto mt-4 max-w-lg text-center text-text-muted">
|
||||
Teams around the world use BlackRoad to power their AI infrastructure
|
||||
</p>
|
||||
<div className="mt-12 grid gap-6 md:grid-cols-3">
|
||||
{testimonials.map((t) => (
|
||||
<div
|
||||
key={t.author}
|
||||
className="rounded-xl border border-border bg-bg p-6"
|
||||
>
|
||||
<p className="text-sm leading-relaxed text-text-muted">"{t.quote}"</p>
|
||||
<div className="mt-6 flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-gradient-to-br from-amber-500 via-pink-500 to-blue-500 text-sm font-bold">
|
||||
{t.avatar}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium">{t.author}</p>
|
||||
<p className="text-xs text-text-muted">{t.role}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
68
src/components/UseCases.tsx
Normal file
68
src/components/UseCases.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
const useCases = [
|
||||
{
|
||||
icon: "🏢",
|
||||
title: "Enterprise Automation",
|
||||
description: "Deploy AI agents to automate complex business processes across departments",
|
||||
metrics: "75% reduction in manual tasks",
|
||||
},
|
||||
{
|
||||
icon: "🔬",
|
||||
title: "Research & Analysis",
|
||||
description: "Run parallel research agents that analyze documents, data, and web content",
|
||||
metrics: "10x faster literature review",
|
||||
},
|
||||
{
|
||||
icon: "🛠️",
|
||||
title: "DevOps & SRE",
|
||||
description: "Intelligent agents that monitor, diagnose, and remediate infrastructure issues",
|
||||
metrics: "60% faster incident response",
|
||||
},
|
||||
{
|
||||
icon: "🎯",
|
||||
title: "Sales & Marketing",
|
||||
description: "Personalized outreach agents that research leads and craft custom messages",
|
||||
metrics: "3x higher response rates",
|
||||
},
|
||||
{
|
||||
icon: "📊",
|
||||
title: "Data Processing",
|
||||
description: "ETL agents that clean, transform, and analyze data at scale",
|
||||
metrics: "Process 1M+ records/hour",
|
||||
},
|
||||
{
|
||||
icon: "🤝",
|
||||
title: "Customer Support",
|
||||
description: "Multi-agent support teams that handle inquiries with human-level nuance",
|
||||
metrics: "90% resolution rate",
|
||||
},
|
||||
]
|
||||
|
||||
export default function UseCases() {
|
||||
return (
|
||||
<section className="px-6 py-16">
|
||||
<div className="mx-auto max-w-6xl">
|
||||
<h2 className="text-center font-display text-2xl font-bold">
|
||||
Built for <span className="gradient-text">Every Use Case</span>
|
||||
</h2>
|
||||
<p className="mx-auto mt-4 max-w-lg text-center text-text-muted">
|
||||
From startups to enterprises, BlackRoad powers AI agents across industries
|
||||
</p>
|
||||
<div className="mt-12 grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{useCases.map((uc) => (
|
||||
<div
|
||||
key={uc.title}
|
||||
className="group rounded-xl border border-border bg-surface p-6 transition hover:-translate-y-0.5 hover:border-border-hover"
|
||||
>
|
||||
<div className="text-3xl">{uc.icon}</div>
|
||||
<h3 className="mt-4 font-display font-semibold group-hover:text-accent">
|
||||
{uc.title}
|
||||
</h3>
|
||||
<p className="mt-2 text-sm text-text-muted">{uc.description}</p>
|
||||
<p className="mt-4 text-xs font-medium text-accent">{uc.metrics}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user