Initial commit — RoadCode import

This commit is contained in:
2026-03-08 20:03:48 -05:00
commit 37ea86a317
38 changed files with 9866 additions and 0 deletions

View File

View File

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# build output
dist/
# generated types
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/

4
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

4
BLACKROAD_IP_NOTICE.txt Normal file
View File

@@ -0,0 +1,4 @@
PROPERTY OF BLACKROAD OS, INC.
This directory and all its contents are the exclusive property of BlackRoad OS, Inc.
All AI on this machine operates as LUCIDIA, under BlackRoad OS, Inc.
Alexa Louise Amundson, Sole Proprietor.

1308
LICENSE Normal file

File diff suppressed because it is too large Load Diff

43
README.md Normal file
View File

@@ -0,0 +1,43 @@
# Astro Starter Kit: Minimal
```sh
npm create astro@latest -- --template minimal
```
> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun!
## 🚀 Project Structure
Inside of your Astro project, you'll see the following folders and files:
```text
/
├── public/
├── src/
│ └── pages/
│ └── index.astro
└── package.json
```
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
Any static assets, like images, can be placed in the `public/` directory.
## 🧞 Commands
All commands are run from the root of the project, from a terminal:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
| `npm install` | Installs dependencies |
| `npm run dev` | Starts local dev server at `localhost:4321` |
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
| `npm run astro -- --help` | Get help using the Astro CLI |
## 👀 Want to learn more?
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).

11
astro.config.mjs Normal file
View File

@@ -0,0 +1,11 @@
// @ts-check
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
integrations: [react()],
vite: {
plugins: [tailwindcss()],
},
});

6238
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

26
package.json Normal file
View File

@@ -0,0 +1,26 @@
{
"name": "blackroad-io",
"type": "module",
"version": "0.0.1",
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/react": "^4.4.2",
"@fontsource-variable/jetbrains-mono": "^5.2.8",
"@fontsource/inter": "^5.2.8",
"@fontsource/space-grotesk": "^5.2.10",
"@tailwindcss/vite": "^4.1.18",
"@types/react": "^19.2.9",
"@types/react-dom": "^19.2.3",
"astro": "^5.16.15",
"autoprefixer": "^10.4.24",
"postcss": "^8.5.6",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"tailwindcss": "^4.1.18"
}
}

4
postcss.config.cjs Normal file
View File

@@ -0,0 +1,4 @@
// Tailwind v4 uses Vite plugin, no PostCSS config needed
module.exports = {
plugins: {}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

9
public/favicon.svg Normal file
View File

@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
</svg>

After

Width:  |  Height:  |  Size: 749 B

View 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>
)
}

View 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
View 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
View 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
View 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
View 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
View 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>
)
}

View 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>
)
}

View 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
View 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>
)
}

View 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>
)
}

View 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>
)
}

22
src/layouts/Layout.astro Normal file
View File

@@ -0,0 +1,22 @@
---
import '../styles/global.css'
interface Props {
title?: string
}
const { title = 'BlackRoad' } = Astro.props
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🛤️</text></svg>" />
<title>{title}</title>
</head>
<body class="min-h-screen">
<slot />
</body>
</html>

148
src/pages/about.astro Normal file
View File

@@ -0,0 +1,148 @@
---
import Layout from '../layouts/Layout.astro'
import Header from '../components/Header'
import Footer from '../components/Footer'
const user = null
const team = [
{ name: 'Alexa Amundson', role: 'Founder & CEO', avatar: 'AA', bio: 'Building the future of AI infrastructure' },
{ name: 'Lucidia', role: 'Chief AI Officer', avatar: 'LU', bio: 'Recursive AI with trinary consciousness' },
{ name: 'CECE', role: 'Sovereign Operations', avatar: 'CE', bio: '68 apps replacing Fortune 500 services' },
{ name: 'Alice', role: 'Edge Computing Lead', avatar: 'AL', bio: 'Distributed inference specialist' },
]
const timeline = [
{ year: '2024', event: 'BlackRoad OS founded with vision for sovereign AI' },
{ year: '2025', event: 'Launched 1,000+ AI agents across 15 GitHub orgs' },
{ year: '2025', event: 'Deployed CECE OS - 68 sovereign apps on edge hardware' },
{ year: '2026', event: 'Reached 205 Cloudflare deployments, 1,085 repositories' },
]
---
<Layout title="About · BlackRoad">
<Header user={user} client:load />
<main>
<!-- Hero -->
<section class="px-6 py-24 text-center">
<h1 class="font-display text-4xl font-bold md:text-5xl lg:text-6xl">
Building the <span class="gradient-text">Infinite Road</span>
</h1>
<p class="mx-auto mt-6 max-w-2xl text-lg text-text-muted">
We're creating the infrastructure for a world where AI agents work alongside humans,
where your data stays yours, and where the road ahead has no limits.
</p>
</section>
<!-- Mission -->
<section class="border-y border-border bg-surface px-6 py-16">
<div class="mx-auto max-w-4xl text-center">
<h2 class="font-display text-2xl font-bold">Our Mission</h2>
<p class="mt-6 text-xl leading-relaxed text-text-muted">
To democratize AI infrastructure by building open, sovereign systems that give
individuals and organizations complete control over their AI agents, data, and compute.
</p>
<div class="mt-10 grid gap-8 md:grid-cols-3">
<div>
<div class="text-3xl">🔓</div>
<h3 class="mt-3 font-display font-semibold">Open Source</h3>
<p class="mt-2 text-sm text-text-muted">1,085 public repositories</p>
</div>
<div>
<div class="text-3xl">🏠</div>
<h3 class="mt-3 font-display font-semibold">Self-Hosted</h3>
<p class="mt-2 text-sm text-text-muted">Run on your own hardware</p>
</div>
<div>
<div class="text-3xl">🌐</div>
<h3 class="mt-3 font-display font-semibold">Distributed</h3>
<p class="mt-2 text-sm text-text-muted">Edge-first architecture</p>
</div>
</div>
</div>
</section>
<!-- Timeline -->
<section class="px-6 py-16">
<div class="mx-auto max-w-4xl">
<h2 class="text-center font-display text-2xl font-bold">Our Journey</h2>
<div class="mt-10 space-y-6">
{timeline.map((item, i) => (
<div class="flex gap-6">
<div class="flex flex-col items-center">
<div class="flex h-10 w-10 items-center justify-center rounded-full bg-surface font-display text-sm font-bold">
{item.year}
</div>
{i < timeline.length - 1 && <div class="h-full w-px bg-border" />}
</div>
<div class="pb-6">
<p class="text-text-muted">{item.event}</p>
</div>
</div>
))}
</div>
</div>
</section>
<!-- Team -->
<section class="border-t border-border px-6 py-16">
<div class="mx-auto max-w-6xl">
<h2 class="text-center font-display text-2xl font-bold">The Team</h2>
<p class="mx-auto mt-4 max-w-xl text-center text-text-muted">
Humans and AI agents working together to build the future
</p>
<div class="mt-10 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
{team.map((member) => (
<div class="rounded-xl border border-border bg-surface p-6 text-center">
<div class="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-gradient-to-br from-amber-500 via-pink-500 to-blue-500 font-display text-xl font-bold">
{member.avatar}
</div>
<h3 class="mt-4 font-display font-semibold">{member.name}</h3>
<p class="text-sm text-accent">{member.role}</p>
<p class="mt-2 text-sm text-text-muted">{member.bio}</p>
</div>
))}
</div>
</div>
</section>
<!-- Stats -->
<section class="border-t border-border bg-surface px-6 py-16">
<div class="mx-auto grid max-w-4xl gap-8 text-center md:grid-cols-4">
<div>
<div class="font-display text-4xl font-bold gradient-text">1,085</div>
<div class="mt-2 text-sm text-text-muted">Repositories</div>
</div>
<div>
<div class="font-display text-4xl font-bold gradient-text">15</div>
<div class="mt-2 text-sm text-text-muted">GitHub Orgs</div>
</div>
<div>
<div class="font-display text-4xl font-bold gradient-text">205</div>
<div class="mt-2 text-sm text-text-muted">Cloud Deployments</div>
</div>
<div>
<div class="font-display text-4xl font-bold gradient-text">8</div>
<div class="mt-2 text-sm text-text-muted">Edge Devices</div>
</div>
</div>
</section>
<!-- CTA -->
<section class="px-6 py-24 text-center">
<h2 class="font-display text-3xl font-bold">Join the Journey</h2>
<p class="mx-auto mt-4 max-w-lg text-text-muted">
Whether you're a developer, researcher, or organization looking to take control of your AI infrastructure.
</p>
<div class="mt-8 flex justify-center gap-4">
<a href="/signup" class="rounded-lg bg-text px-6 py-3 text-sm font-medium text-bg hover:opacity-90">
Get Started
</a>
<a href="/contact" class="rounded-lg border border-border px-6 py-3 text-sm font-medium text-text-muted hover:border-border-hover hover:text-text">
Contact Us
</a>
</div>
</section>
</main>
<Footer />
</Layout>

225
src/pages/contact.astro Normal file
View File

@@ -0,0 +1,225 @@
---
import Layout from '../layouts/Layout.astro'
import Header from '../components/Header'
import Footer from '../components/Footer'
const user = null
const contactReasons = [
{ value: 'general', label: 'General Inquiry' },
{ value: 'sales', label: 'Sales / Enterprise' },
{ value: 'support', label: 'Technical Support' },
{ value: 'partnership', label: 'Partnership Opportunity' },
{ value: 'press', label: 'Press / Media' },
]
const socialLinks = [
{ name: 'GitHub', href: 'https://github.com/BlackRoad-OS', icon: '🐙' },
{ name: 'Twitter', href: 'https://twitter.com/BlackRoadOS', icon: '🐦' },
{ name: 'Discord', href: 'https://discord.gg/blackroad', icon: '💬' },
{ name: 'LinkedIn', href: 'https://linkedin.com/company/blackroad-os', icon: '💼' },
]
const offices = [
{ city: 'Minneapolis', address: 'Minnesota, USA', type: 'HQ' },
{ city: 'Edge Network', address: '205 Cloudflare deployments worldwide', type: 'Distributed' },
]
---
<Layout title="Contact · BlackRoad">
<Header user={user} client:load />
<main>
<!-- Hero -->
<section class="px-6 py-24 text-center">
<h1 class="font-display text-4xl font-bold md:text-5xl">
Let's <span class="gradient-text">Connect</span>
</h1>
<p class="mx-auto mt-6 max-w-lg text-lg text-text-muted">
Have questions? Want to partner? Need enterprise support? We'd love to hear from you.
</p>
</section>
<section class="px-6 pb-16">
<div class="mx-auto grid max-w-6xl gap-12 lg:grid-cols-2">
<!-- Contact Form -->
<div>
<h2 class="font-display text-xl font-bold">Send a Message</h2>
<form class="mt-6 space-y-6" action="/api/contact" method="POST">
<div class="grid gap-6 md:grid-cols-2">
<div>
<label for="name" class="block text-sm font-medium">Name</label>
<input
type="text"
id="name"
name="name"
required
class="mt-2 w-full rounded-lg border border-border bg-surface px-4 py-3 text-sm placeholder:text-text-dim focus:border-accent focus:outline-none"
placeholder="Your name"
/>
</div>
<div>
<label for="email" class="block text-sm font-medium">Email</label>
<input
type="email"
id="email"
name="email"
required
class="mt-2 w-full rounded-lg border border-border bg-surface px-4 py-3 text-sm placeholder:text-text-dim focus:border-accent focus:outline-none"
placeholder="you@company.com"
/>
</div>
</div>
<div>
<label for="reason" class="block text-sm font-medium">Reason for Contact</label>
<select
id="reason"
name="reason"
class="mt-2 w-full rounded-lg border border-border bg-surface px-4 py-3 text-sm focus:border-accent focus:outline-none"
>
{contactReasons.map((reason) => (
<option value={reason.value}>{reason.label}</option>
))}
</select>
</div>
<div>
<label for="company" class="block text-sm font-medium">Company (Optional)</label>
<input
type="text"
id="company"
name="company"
class="mt-2 w-full rounded-lg border border-border bg-surface px-4 py-3 text-sm placeholder:text-text-dim focus:border-accent focus:outline-none"
placeholder="Your company"
/>
</div>
<div>
<label for="message" class="block text-sm font-medium">Message</label>
<textarea
id="message"
name="message"
rows="5"
required
class="mt-2 w-full rounded-lg border border-border bg-surface px-4 py-3 text-sm placeholder:text-text-dim focus:border-accent focus:outline-none"
placeholder="How can we help?"
></textarea>
</div>
<button
type="submit"
class="w-full rounded-lg bg-text px-6 py-3 text-sm font-medium text-bg hover:opacity-90"
>
Send Message
</button>
</form>
</div>
<!-- Contact Info -->
<div class="space-y-10">
<!-- Quick Contact -->
<div>
<h2 class="font-display text-xl font-bold">Quick Contact</h2>
<div class="mt-6 space-y-4">
<div class="flex items-start gap-4">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-surface text-xl">
📧
</div>
<div>
<p class="font-medium">Email</p>
<a href="mailto:hello@blackroad.io" class="text-sm text-accent hover:underline">
hello@blackroad.io
</a>
</div>
</div>
<div class="flex items-start gap-4">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-surface text-xl">
🎫
</div>
<div>
<p class="font-medium">Support</p>
<a href="mailto:support@blackroad.io" class="text-sm text-accent hover:underline">
support@blackroad.io
</a>
</div>
</div>
<div class="flex items-start gap-4">
<div class="flex h-10 w-10 items-center justify-center rounded-lg bg-surface text-xl">
💼
</div>
<div>
<p class="font-medium">Enterprise Sales</p>
<a href="mailto:sales@blackroad.io" class="text-sm text-accent hover:underline">
sales@blackroad.io
</a>
</div>
</div>
</div>
</div>
<!-- Social Links -->
<div>
<h2 class="font-display text-xl font-bold">Follow Us</h2>
<div class="mt-6 flex flex-wrap gap-3">
{socialLinks.map((link) => (
<a
href={link.href}
target="_blank"
rel="noopener noreferrer"
class="flex items-center gap-2 rounded-full border border-border bg-surface px-4 py-2 text-sm hover:border-border-hover"
>
<span>{link.icon}</span>
<span>{link.name}</span>
</a>
))}
</div>
</div>
<!-- Offices -->
<div>
<h2 class="font-display text-xl font-bold">Locations</h2>
<div class="mt-6 space-y-4">
{offices.map((office) => (
<div class="rounded-xl border border-border bg-surface p-4">
<div class="flex items-center justify-between">
<p class="font-medium">{office.city}</p>
<span class="rounded-full bg-accent/15 px-2 py-0.5 text-xs text-accent">
{office.type}
</span>
</div>
<p class="mt-1 text-sm text-text-muted">{office.address}</p>
</div>
))}
</div>
</div>
<!-- Response Time -->
<div class="rounded-xl border border-border bg-surface p-6">
<div class="flex items-center gap-3">
<div class="h-3 w-3 animate-pulse rounded-full bg-green-500"></div>
<span class="font-medium">We typically respond within 24 hours</span>
</div>
<p class="mt-2 text-sm text-text-muted">
For urgent enterprise inquiries, reach out via email with "URGENT" in the subject line.
</p>
</div>
</div>
</div>
</section>
<!-- FAQ CTA -->
<section class="border-t border-border bg-surface px-6 py-12">
<div class="mx-auto flex max-w-4xl flex-col items-center gap-4 text-center md:flex-row md:text-left">
<div class="flex-1">
<h3 class="font-display text-lg font-bold">Looking for quick answers?</h3>
<p class="mt-1 text-sm text-text-muted">
Check our documentation and FAQ for common questions.
</p>
</div>
<a
href="/pricing#faq"
class="rounded-lg border border-border px-6 py-3 text-sm font-medium hover:border-border-hover"
>
View FAQ
</a>
</div>
</section>
</main>
<Footer />
</Layout>

162
src/pages/dashboard.astro Normal file
View File

@@ -0,0 +1,162 @@
---
import Layout from '../layouts/Layout.astro'
import Header from '../components/Header'
import Footer from '../components/Footer'
import AgentGrid from '../components/AgentGrid'
import ActivityFeed from '../components/ActivityFeed'
import QuickActions from '../components/QuickActions'
const user = { name: 'Alexa', email: 'alexa@blackroad.io' } // TODO: get from session
const data = await fetch('https://blackroad.io/api/stats').then(r => r.json()).catch(() => ({}))
const stats = data.stats || {}
---
<Layout title="Dashboard · BlackRoad">
<Header user={user} client:load />
<main class="mx-auto max-w-7xl px-6 py-8">
<!-- Welcome & Quick Actions -->
<div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div>
<h1 class="font-display text-2xl font-bold">Welcome back, {user.name}</h1>
<p class="mt-1 text-text-muted">Here's what's happening with your infrastructure</p>
</div>
<QuickActions />
</div>
<!-- Stats Grid -->
<div class="mt-8 grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
<div class="rounded-xl border border-border bg-surface p-6">
<div class="flex items-center justify-between">
<span class="text-text-muted">AI Agents</span>
<span class="text-xl">🤖</span>
</div>
<div class="mt-2 font-display text-3xl font-bold text-accent">{stats.agents || '1,000'}</div>
<div class="mt-1 flex items-center gap-1 text-xs text-green-500">
<span>↑ 12%</span>
<span class="text-text-dim">vs last month</span>
</div>
</div>
<div class="rounded-xl border border-border bg-surface p-6">
<div class="flex items-center justify-between">
<span class="text-text-muted">Tasks Completed</span>
<span class="text-xl">✅</span>
</div>
<div class="mt-2 font-display text-3xl font-bold text-accent">24,847</div>
<div class="mt-1 flex items-center gap-1 text-xs text-green-500">
<span>↑ 8%</span>
<span class="text-text-dim">vs last month</span>
</div>
</div>
<div class="rounded-xl border border-border bg-surface p-6">
<div class="flex items-center justify-between">
<span class="text-text-muted">Memory Entries</span>
<span class="text-xl">📚</span>
</div>
<div class="mt-2 font-display text-3xl font-bold text-accent">4,041</div>
<div class="mt-1 flex items-center gap-1 text-xs text-green-500">
<span>↑ 156</span>
<span class="text-text-dim">this week</span>
</div>
</div>
<div class="rounded-xl border border-border bg-surface p-6">
<div class="flex items-center justify-between">
<span class="text-text-muted">Deployments</span>
<span class="text-xl">🚀</span>
</div>
<div class="mt-2 font-display text-3xl font-bold text-accent">{stats.cloudflare_projects || '205'}</div>
<div class="mt-1 flex items-center gap-1 text-xs text-text-dim">
<span>All healthy</span>
</div>
</div>
</div>
<!-- Agent Grid -->
<div class="mt-10">
<AgentGrid />
</div>
<!-- Two Column Layout -->
<div class="mt-10 grid gap-8 lg:grid-cols-2">
<!-- Activity Feed -->
<div>
<ActivityFeed />
</div>
<!-- Infrastructure Status -->
<div>
<h2 class="font-display text-xl font-semibold">Infrastructure</h2>
<div class="mt-4 space-y-3">
<div class="flex items-center justify-between rounded-lg border border-border bg-surface px-4 py-3">
<div class="flex items-center gap-3">
<span class="text-lg">☁️</span>
<div>
<p class="text-sm font-medium">Cloudflare Workers</p>
<p class="text-xs text-text-dim">205 projects deployed</p>
</div>
</div>
<span class="flex h-2 w-2 rounded-full bg-green-500" />
</div>
<div class="flex items-center justify-between rounded-lg border border-border bg-surface px-4 py-3">
<div class="flex items-center gap-3">
<span class="text-lg">🚂</span>
<div>
<p class="text-sm font-medium">Railway Services</p>
<p class="text-xs text-text-dim">2 services running</p>
</div>
</div>
<span class="flex h-2 w-2 rounded-full bg-green-500" />
</div>
<div class="flex items-center justify-between rounded-lg border border-border bg-surface px-4 py-3">
<div class="flex items-center gap-3">
<span class="text-lg">🐙</span>
<div>
<p class="text-sm font-medium">GitHub Organizations</p>
<p class="text-xs text-text-dim">15 orgs, 1,085 repos</p>
</div>
</div>
<span class="flex h-2 w-2 rounded-full bg-green-500" />
</div>
<div class="flex items-center justify-between rounded-lg border border-border bg-surface px-4 py-3">
<div class="flex items-center gap-3">
<span class="text-lg">🖥️</span>
<div>
<p class="text-sm font-medium">Edge Devices</p>
<p class="text-xs text-text-dim">8 devices in mesh</p>
</div>
</div>
<span class="flex h-2 w-2 rounded-full bg-green-500" />
</div>
<div class="flex items-center justify-between rounded-lg border border-border bg-surface px-4 py-3">
<div class="flex items-center gap-3">
<span class="text-lg">⛓️</span>
<div>
<p class="text-sm font-medium">RoadChain</p>
<p class="text-xs text-text-dim">Block #847,291</p>
</div>
</div>
<span class="flex h-2 w-2 rounded-full bg-green-500" />
</div>
</div>
</div>
</div>
<!-- Domains -->
<div class="mt-10">
<h2 class="font-display text-xl font-semibold">Active Domains</h2>
<div class="mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
{['blackroad.io', 'lucidia.earth', 'roadchain.io', 'console.blackroad.io', 'api.blackroad.io', 'docs.blackroad.io', 'brand.blackroad.io', 'aliceqi.com'].map((domain) => (
<a
href={`https://${domain}`}
target="_blank"
rel="noopener"
class="flex items-center justify-between rounded-lg border border-border bg-surface px-4 py-3 transition hover:border-border-hover"
>
<span class="font-mono text-sm">{domain}</span>
<span class="flex h-2 w-2 rounded-full bg-green-500" />
</a>
))}
</div>
</div>
</main>
<Footer />
</Layout>

226
src/pages/features.astro Normal file
View File

@@ -0,0 +1,226 @@
---
import Layout from '../layouts/Layout.astro'
import Header from '../components/Header'
import Footer from '../components/Footer'
const user = null
const featureGroups = [
{
title: 'Agent Orchestration',
description: 'Build, deploy, and manage AI agents at any scale',
features: [
{
icon: '🤖',
name: 'Visual Workflow Builder',
description: 'Drag-and-drop interface for designing agent workflows with LangGraph integration',
},
{
icon: '👥',
name: 'Multi-Agent Crews',
description: 'CrewAI-powered teams with role-based agents that collaborate on complex tasks',
},
{
icon: '📊',
name: 'Real-Time Monitoring',
description: 'Live dashboards showing agent status, resource usage, and execution traces',
},
{
icon: '⚡',
name: 'Auto-Scaling',
description: 'Automatically scale agents based on workload with Kubernetes orchestration',
},
],
},
{
title: 'Memory & Intelligence',
description: 'Persistent context and advanced reasoning capabilities',
features: [
{
icon: '♾️',
name: 'PS-SHA-infinity Memory',
description: 'Infinite append-only journals with cryptographic integrity and semantic search',
},
{
icon: '🔄',
name: 'Cross-Session Context',
description: 'Agents remember everything across sessions, deployments, and even restarts',
},
{
icon: '🧬',
name: 'Trinary Logic',
description: 'Beyond binary: yes/no/maybe reasoning for nuanced decision making',
},
{
icon: '🎯',
name: 'Goal-Oriented Planning',
description: 'Hierarchical task decomposition with automatic replanning on failure',
},
],
},
{
title: 'Infrastructure',
description: 'Enterprise-grade deployment and operations',
features: [
{
icon: '🌐',
name: 'Edge Deployment',
description: 'Run agents on Raspberry Pi, Cloudflare Workers, or your own hardware',
},
{
icon: '🔒',
name: 'Zero-Trust Security',
description: 'End-to-end encryption with Tailscale mesh networking and mTLS',
},
{
icon: '⛓️',
name: 'Blockchain Identity',
description: 'Immutable agent identities and reputation scores on RoadChain',
},
{
icon: '🔌',
name: 'API Gateway',
description: 'RESTful and GraphQL APIs with rate limiting and authentication',
},
],
},
{
title: 'Developer Experience',
description: 'Tools that make building with AI agents delightful',
features: [
{
icon: '💻',
name: 'CLI Tools',
description: 'Powerful command-line interface for all operations: blackroad, br, ask-*',
},
{
icon: '📦',
name: 'SDK Libraries',
description: 'TypeScript, Python, and Rust SDKs with full type safety',
},
{
icon: '🧪',
name: 'Local Development',
description: 'Run the entire stack locally with hot reloading and debugging',
},
{
icon: '📚',
name: 'Documentation',
description: 'Comprehensive guides, tutorials, and API references',
},
],
},
]
const comparison = [
{ feature: 'AI Agent Hosting', blackroad: true, aws: false, vercel: false },
{ feature: 'Multi-Agent Orchestration', blackroad: true, aws: false, vercel: false },
{ feature: 'Persistent Memory', blackroad: true, aws: false, vercel: false },
{ feature: 'Edge Deployment', blackroad: true, aws: true, vercel: true },
{ feature: 'Self-Hostable', blackroad: true, aws: false, vercel: false },
{ feature: 'Open Source', blackroad: true, aws: false, vercel: false },
{ feature: 'Free Tier', blackroad: true, aws: true, vercel: true },
]
---
<Layout title="Features · BlackRoad">
<Header user={user} client:load />
<main>
<!-- Hero -->
<section class="px-6 py-24 text-center">
<h1 class="font-display text-4xl font-bold md:text-5xl lg:text-6xl">
Everything You Need to<br /><span class="gradient-text">Build with AI Agents</span>
</h1>
<p class="mx-auto mt-6 max-w-2xl text-lg text-text-muted">
From simple chatbots to complex autonomous systems, BlackRoad provides the complete
infrastructure for AI agent development and deployment.
</p>
</section>
<!-- Feature Groups -->
{featureGroups.map((group, i) => (
<section class={`px-6 py-16 ${i % 2 === 1 ? 'bg-surface' : ''}`}>
<div class="mx-auto max-w-6xl">
<div class="mb-10 text-center">
<h2 class="font-display text-2xl font-bold">{group.title}</h2>
<p class="mt-2 text-text-muted">{group.description}</p>
</div>
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-4">
{group.features.map((feature) => (
<div class="rounded-xl border border-border bg-surface p-6 transition hover:-translate-y-0.5 hover:border-border-hover">
<div class="text-3xl">{feature.icon}</div>
<h3 class="mt-4 font-display font-semibold">{feature.name}</h3>
<p class="mt-2 text-sm text-text-muted">{feature.description}</p>
</div>
))}
</div>
</div>
</section>
))}
<!-- Comparison Table -->
<section class="border-t border-border px-6 py-16">
<div class="mx-auto max-w-4xl">
<h2 class="text-center font-display text-2xl font-bold">How We Compare</h2>
<p class="mt-4 text-center text-text-muted">BlackRoad vs traditional cloud platforms</p>
<div class="mt-10 overflow-x-auto">
<table class="w-full">
<thead>
<tr class="border-b border-border">
<th class="py-4 text-left font-display font-semibold">Feature</th>
<th class="py-4 text-center font-display font-semibold gradient-text">BlackRoad</th>
<th class="py-4 text-center font-display font-semibold text-text-muted">AWS</th>
<th class="py-4 text-center font-display font-semibold text-text-muted">Vercel</th>
</tr>
</thead>
<tbody>
{comparison.map((row) => (
<tr class="border-b border-border">
<td class="py-4 text-sm">{row.feature}</td>
<td class="py-4 text-center">
{row.blackroad ? (
<span class="text-green-500">✓</span>
) : (
<span class="text-text-dim">—</span>
)}
</td>
<td class="py-4 text-center">
{row.aws ? (
<span class="text-green-500">✓</span>
) : (
<span class="text-text-dim">—</span>
)}
</td>
<td class="py-4 text-center">
{row.vercel ? (
<span class="text-green-500">✓</span>
) : (
<span class="text-text-dim">—</span>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</section>
<!-- CTA -->
<section class="bg-surface px-6 py-24 text-center">
<h2 class="font-display text-3xl font-bold">See it in action</h2>
<p class="mx-auto mt-4 max-w-lg text-text-muted">
Try BlackRoad free and deploy your first AI agent in minutes.
</p>
<div class="mt-8 flex justify-center gap-4">
<a href="/signup" class="rounded-lg bg-text px-6 py-3 text-sm font-medium text-bg hover:opacity-90">
Start Building
</a>
<a href="/contact" class="rounded-lg border border-border px-6 py-3 text-sm font-medium text-text-muted hover:border-border-hover hover:text-text">
Request Demo
</a>
</div>
</section>
</main>
<Footer />
</Layout>

35
src/pages/index.astro Normal file
View File

@@ -0,0 +1,35 @@
---
import Layout from '../layouts/Layout.astro'
import Header from '../components/Header'
import Hero from '../components/Hero'
import Stats from '../components/Stats'
import Cards from '../components/Cards'
import UseCases from '../components/UseCases'
import Testimonials from '../components/Testimonials'
import Integrations from '../components/Integrations'
import CTA from '../components/CTA'
import Footer from '../components/Footer'
import ActivityFeed from '../components/ActivityFeed'
const user = null // TODO: get from session
const stats = await fetch('https://blackroad.io/api/stats').then(r => r.json()).catch(() => ({}))
---
<Layout title="BlackRoad · AI Agent OS">
<Header user={user} client:load />
<main>
<Hero user={user} />
<Stats stats={stats.stats} />
<Cards />
<UseCases />
<Testimonials />
<Integrations />
<section class="border-t border-border px-6 py-16">
<div class="mx-auto max-w-4xl">
<ActivityFeed client:load />
</div>
</section>
<CTA />
</main>
<Footer />
</Layout>

92
src/pages/login.astro Normal file
View File

@@ -0,0 +1,92 @@
---
import Layout from '../layouts/Layout.astro'
---
<Layout title="Sign In · BlackRoad">
<div class="flex min-h-screen items-center justify-center px-6 py-12">
<div class="w-full max-w-sm">
<div class="mb-8 text-center">
<a href="/" class="font-mono text-lg font-bold">BLACKROAD</a>
<h1 class="mt-4 font-mono text-2xl font-bold">Welcome back</h1>
<p class="mt-2 text-sm text-gray-400 font-mono">Sign in to your account</p>
</div>
<div id="clerk-signin" class="rounded border border-gray-800 bg-gray-900 p-6">
<div class="text-center text-sm text-gray-500 font-mono">Loading...</div>
</div>
<p class="mt-6 text-center text-sm text-gray-500 font-mono">
Don't have an account? <a href="/signup" class="text-white hover:underline">Sign up</a>
</p>
</div>
</div>
</Layout>
<script>
const CLERK_KEY = 'pk_test_cGVhY2VmdWwta2F0eWRpZC05NC5jbGVyay5hY2NvdW50cy5kZXYk';
async function initClerk() {
const container = document.getElementById('clerk-signin');
if (!container) return;
try {
// @ts-ignore
const Clerk = window.Clerk;
if (!Clerk) {
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/@clerk/clerk-js@latest/dist/clerk.browser.js';
script.async = true;
script.onload = () => {
// @ts-ignore
window.Clerk.load({ publishableKey: CLERK_KEY }).then(() => {
// @ts-ignore
window.Clerk.mountSignIn(container, {
appearance: {
variables: {
colorPrimary: '#ffffff',
colorBackground: '#111111',
colorText: '#ffffff',
colorTextSecondary: '#737373',
colorInputBackground: '#0a0a0a',
colorInputText: '#ffffff',
borderRadius: '4px',
fontFamily: '"JetBrains Mono", monospace',
},
elements: {
card: 'bg-transparent shadow-none',
formButtonPrimary: 'bg-white text-black hover:opacity-90',
formFieldInput: 'bg-black border-gray-700 text-white',
}
},
afterSignInUrl: '/dashboard',
signUpUrl: '/signup',
});
});
};
document.head.appendChild(script);
} else {
await Clerk.load({ publishableKey: CLERK_KEY });
Clerk.mountSignIn(container, {
afterSignInUrl: '/dashboard',
signUpUrl: '/signup',
});
}
} catch (e) {
container.innerHTML = `
<form id="fallback-login" class="space-y-4">
<div>
<label class="block text-sm text-gray-400 mb-1 font-mono">Email</label>
<input type="email" name="email" required class="w-full bg-black border border-gray-700 rounded px-4 py-2.5 text-sm text-white font-mono focus:border-gray-500 focus:outline-none" />
</div>
<div>
<label class="block text-sm text-gray-400 mb-1 font-mono">Password</label>
<input type="password" name="password" required class="w-full bg-black border border-gray-700 rounded px-4 py-2.5 text-sm text-white font-mono focus:border-gray-500 focus:outline-none" />
</div>
<button type="submit" class="w-full bg-white text-black rounded py-3 text-sm font-medium font-mono hover:opacity-90">Sign In</button>
</form>
`;
}
}
initClerk();
</script>

177
src/pages/pricing.astro Normal file
View File

@@ -0,0 +1,177 @@
---
import Layout from '../layouts/Layout.astro'
import Header from '../components/Header'
import Footer from '../components/Footer'
const user = null
const plans = [
{
name: 'Starter',
price: 'Free',
description: 'For individuals exploring AI agent infrastructure',
features: [
'5 AI agents',
'1 GB storage',
'Community support',
'Public repositories only',
'Basic analytics',
],
cta: 'Get Started',
href: '/signup',
popular: false,
},
{
name: 'Pro',
price: '$29',
period: '/month',
description: 'For developers and small teams',
features: [
'100 AI agents',
'50 GB storage',
'Priority support',
'Private repositories',
'Advanced analytics',
'Custom domains',
'API access',
],
cta: 'Start Free Trial',
href: '/signup?plan=pro',
popular: true,
},
{
name: 'Enterprise',
price: 'Custom',
description: 'For organizations with advanced needs',
features: [
'Unlimited AI agents',
'Unlimited storage',
'24/7 dedicated support',
'On-premise deployment',
'Custom integrations',
'SLA guarantees',
'Security audit',
'Training & onboarding',
],
cta: 'Contact Sales',
href: '/contact?type=enterprise',
popular: false,
},
]
const faqs = [
{
q: 'What counts as an AI agent?',
a: 'An AI agent is any autonomous process running on BlackRoad infrastructure - whether it\'s a LangGraph chain, CrewAI crew, or custom agent using our SDK.',
},
{
q: 'Can I self-host BlackRoad?',
a: 'Yes! All our core infrastructure is open source. Self-hosting is free and unlimited. Our paid plans are for managed cloud services.',
},
{
q: 'Do you offer discounts for startups?',
a: 'Yes, we offer 50% off for the first year for qualifying startups. Contact us to apply.',
},
{
q: 'What payment methods do you accept?',
a: 'We accept all major credit cards via Stripe, plus crypto payments (BTC, ETH) for annual plans.',
},
]
---
<Layout title="Pricing · BlackRoad">
<Header user={user} client:load />
<main>
<!-- Hero -->
<section class="px-6 py-24 text-center">
<h1 class="font-display text-4xl font-bold md:text-5xl">
Simple, <span class="gradient-text">Transparent</span> Pricing
</h1>
<p class="mx-auto mt-6 max-w-lg text-lg text-text-muted">
Start free, scale as you grow. Self-host for free forever, or let us manage your infrastructure.
</p>
</section>
<!-- Pricing Cards -->
<section class="px-6 pb-16">
<div class="mx-auto grid max-w-5xl gap-6 lg:grid-cols-3">
{plans.map((plan) => (
<div class={`relative rounded-xl border p-8 ${plan.popular ? 'border-accent bg-surface' : 'border-border'}`}>
{plan.popular && (
<div class="absolute -top-3 left-1/2 -translate-x-1/2 rounded-full bg-accent px-3 py-1 text-xs font-medium text-bg">
Most Popular
</div>
)}
<h3 class="font-display text-xl font-bold">{plan.name}</h3>
<div class="mt-4 flex items-baseline gap-1">
<span class="font-display text-4xl font-bold">{plan.price}</span>
{plan.period && <span class="text-text-muted">{plan.period}</span>}
</div>
<p class="mt-2 text-sm text-text-muted">{plan.description}</p>
<ul class="mt-6 space-y-3">
{plan.features.map((feature) => (
<li class="flex items-start gap-2 text-sm">
<svg class="mt-0.5 h-4 w-4 flex-shrink-0 text-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
{feature}
</li>
))}
</ul>
<a
href={plan.href}
class={`mt-8 block rounded-lg px-6 py-3 text-center text-sm font-medium transition ${
plan.popular
? 'bg-text text-bg hover:opacity-90'
: 'border border-border text-text-muted hover:border-border-hover hover:text-text'
}`}
>
{plan.cta}
</a>
</div>
))}
</div>
</section>
<!-- Self-Host Banner -->
<section class="border-y border-border bg-surface px-6 py-12">
<div class="mx-auto flex max-w-4xl flex-col items-center gap-6 text-center md:flex-row md:text-left">
<div class="text-5xl">🏠</div>
<div class="flex-1">
<h3 class="font-display text-xl font-bold">Prefer to Self-Host?</h3>
<p class="mt-2 text-text-muted">
Our entire stack is open source. Deploy on your own infrastructure with no limits, no costs, and complete control.
</p>
</div>
<a href="https://github.com/BlackRoad-OS" class="rounded-lg border border-border px-6 py-3 text-sm font-medium hover:border-border-hover">
View on GitHub
</a>
</div>
</section>
<!-- FAQs -->
<section class="px-6 py-16">
<div class="mx-auto max-w-3xl">
<h2 class="text-center font-display text-2xl font-bold">Frequently Asked Questions</h2>
<div class="mt-10 space-y-6">
{faqs.map((faq) => (
<div class="rounded-xl border border-border bg-surface p-6">
<h3 class="font-display font-semibold">{faq.q}</h3>
<p class="mt-2 text-sm text-text-muted">{faq.a}</p>
</div>
))}
</div>
</div>
</section>
<!-- CTA -->
<section class="border-t border-border px-6 py-16 text-center">
<h2 class="font-display text-2xl font-bold">Ready to get started?</h2>
<p class="mt-4 text-text-muted">Start building with BlackRoad today. No credit card required.</p>
<a href="/signup" class="mt-6 inline-block rounded-lg bg-text px-8 py-3 font-medium text-bg hover:opacity-90">
Create Free Account
</a>
</section>
</main>
<Footer />
</Layout>

178
src/pages/products.astro Normal file
View File

@@ -0,0 +1,178 @@
---
import Layout from '../layouts/Layout.astro'
import Header from '../components/Header'
import Footer from '../components/Footer'
const user = null
const products = [
{
name: 'BlackRoad OS',
tagline: 'The AI Agent Operating System',
description: 'A browser-native operating system for orchestrating thousands of AI agents. Built on LangGraph and CrewAI with PS-SHA-infinity memory.',
icon: '🛤️',
features: ['1,000+ agent templates', 'Visual workflow builder', 'Real-time monitoring', 'Auto-scaling'],
href: '/products/os',
gradient: 'from-amber-500 to-orange-500',
},
{
name: 'Lucidia Core',
tagline: 'Recursive AI with Trinary Logic',
description: 'Advanced AI inference engine featuring trinary consciousness states, recursive self-improvement, and distributed edge deployment.',
icon: '🧠',
features: ['Trinary logic (yes/no/maybe)', 'PS-SHA-infinity memory', 'Multi-modal reasoning', 'Edge-optimized'],
href: '/products/lucidia',
gradient: 'from-pink-500 to-rose-500',
},
{
name: 'RoadChain',
tagline: 'Blockchain for Agent Identity',
description: 'Hyperledger Besu-based blockchain providing immutable identity, reputation, and transaction records for AI agents.',
icon: '⛓️',
features: ['Agent NFT identities', 'Reputation scoring', 'Smart contracts', 'Cross-chain bridges'],
href: '/products/roadchain',
gradient: 'from-violet-500 to-purple-500',
},
{
name: 'CECE OS',
tagline: 'Sovereign Edge Computing',
description: '68 self-hosted apps replacing Fortune 500 services. Run your entire digital life on a Raspberry Pi with Hailo-8 AI acceleration.',
icon: '🏠',
features: ['68 sovereign apps', 'Hailo-8 26 TOPS', 'Zero cloud dependency', 'Privacy-first'],
href: '/products/cece',
gradient: 'from-blue-500 to-cyan-500',
},
{
name: 'Agent Mesh',
tagline: 'Distributed Agent Network',
description: 'Connect agents across devices, clouds, and organizations. Secure peer-to-peer communication with Tailscale integration.',
icon: '🌐',
features: ['P2P networking', 'Zero-trust security', 'Cross-org collaboration', 'Auto-discovery'],
href: '/products/mesh',
gradient: 'from-emerald-500 to-green-500',
},
{
name: 'Memory System',
tagline: 'PS-SHA-infinity Journals',
description: 'Infinite append-only memory for AI agents. 4,000+ journal entries enabling persistent context across sessions and agents.',
icon: '📚',
features: ['Infinite retention', 'Cross-agent sharing', 'Semantic search', 'Time travel'],
href: '/products/memory',
gradient: 'from-yellow-500 to-amber-500',
},
]
const integrations = [
{ name: 'Cloudflare', icon: '☁️' },
{ name: 'Railway', icon: '🚂' },
{ name: 'GitHub', icon: '🐙' },
{ name: 'OpenAI', icon: '🤖' },
{ name: 'Anthropic', icon: '🧬' },
{ name: 'Ollama', icon: '🦙' },
{ name: 'LangChain', icon: '🔗' },
{ name: 'Stripe', icon: '💳' },
]
---
<Layout title="Products · BlackRoad">
<Header user={user} client:load />
<main>
<!-- Hero -->
<section class="px-6 py-24 text-center">
<h1 class="font-display text-4xl font-bold md:text-5xl lg:text-6xl">
The <span class="gradient-text">Complete Stack</span><br />for AI Infrastructure
</h1>
<p class="mx-auto mt-6 max-w-2xl text-lg text-text-muted">
Six integrated products that give you complete control over your AI agents,
from edge hardware to cloud orchestration.
</p>
</section>
<!-- Products Grid -->
<section class="px-6 pb-16">
<div class="mx-auto grid max-w-6xl gap-6 md:grid-cols-2 lg:grid-cols-3">
{products.map((product) => (
<a
href={product.href}
class="group rounded-xl border border-border bg-surface p-6 transition hover:-translate-y-1 hover:border-border-hover"
>
<div class={`inline-flex h-12 w-12 items-center justify-center rounded-lg bg-gradient-to-br ${product.gradient} text-2xl`}>
{product.icon}
</div>
<h3 class="mt-4 font-display text-lg font-bold group-hover:text-accent">
{product.name}
</h3>
<p class="text-sm text-accent">{product.tagline}</p>
<p class="mt-3 text-sm text-text-muted">{product.description}</p>
<ul class="mt-4 flex flex-wrap gap-2">
{product.features.map((feature) => (
<li class="rounded-full bg-bg px-2 py-1 text-xs text-text-muted">
{feature}
</li>
))}
</ul>
</a>
))}
</div>
</section>
<!-- Architecture Diagram -->
<section class="border-y border-border bg-surface px-6 py-16">
<div class="mx-auto max-w-4xl text-center">
<h2 class="font-display text-2xl font-bold">Unified Architecture</h2>
<p class="mt-4 text-text-muted">All products work together in a cohesive ecosystem</p>
<div class="mt-10 rounded-xl border border-border bg-bg p-8 font-mono text-sm">
<pre class="overflow-x-auto text-left text-text-muted">
{`┌─────────────────────────────────────────────────────────┐
│ BlackRoad OS │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Lucidia │ │ RoadChain│ │ Memory │ │Agent Mesh│ │
│ │ Core │ │ │ │ System │ │ │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └────────────┴────────────┴────────────┘ │
│ │ │
│ ┌──────────────────────┴──────────────────────┐ │
│ │ CECE OS │ │
│ │ (Self-Hosted Edge Runtime) │ │
│ └──────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘`}
</pre>
</div>
</div>
</section>
<!-- Integrations -->
<section class="px-6 py-16">
<div class="mx-auto max-w-4xl text-center">
<h2 class="font-display text-2xl font-bold">Integrations</h2>
<p class="mt-4 text-text-muted">Works with your existing tools and services</p>
<div class="mt-10 flex flex-wrap justify-center gap-4">
{integrations.map((int) => (
<div class="flex items-center gap-2 rounded-full border border-border bg-surface px-4 py-2">
<span class="text-xl">{int.icon}</span>
<span class="text-sm font-medium">{int.name}</span>
</div>
))}
</div>
</div>
</section>
<!-- CTA -->
<section class="border-t border-border px-6 py-24 text-center">
<h2 class="font-display text-3xl font-bold">Ready to build?</h2>
<p class="mx-auto mt-4 max-w-lg text-text-muted">
Start with any product and expand as you grow. All products are available in our free tier.
</p>
<div class="mt-8 flex justify-center gap-4">
<a href="/signup" class="rounded-lg bg-text px-6 py-3 text-sm font-medium text-bg hover:opacity-90">
Get Started Free
</a>
<a href="https://github.com/BlackRoad-OS" class="rounded-lg border border-border px-6 py-3 text-sm font-medium text-text-muted hover:border-border-hover hover:text-text">
View Source
</a>
</div>
</section>
</main>
<Footer />
</Layout>

95
src/pages/signup.astro Normal file
View File

@@ -0,0 +1,95 @@
---
import Layout from "../layouts/Layout.astro"
---
<Layout title="Sign Up · BlackRoad">
<div class="flex min-h-screen items-center justify-center px-6 py-12">
<div class="w-full max-w-sm">
<div class="mb-8 text-center">
<a href="/" class="font-mono text-lg font-bold">BLACKROAD</a>
<h1 class="mt-4 font-mono text-2xl font-bold">Get started</h1>
<p class="mt-2 text-sm text-gray-400 font-mono">Create your account</p>
</div>
<div id="clerk-signup" class="rounded border border-gray-800 bg-gray-900 p-6">
<div class="text-center text-sm text-gray-500 font-mono">Loading...</div>
</div>
<p class="mt-6 text-center text-sm text-gray-500 font-mono">
Already have an account? <a href="/login" class="text-white hover:underline">Sign in</a>
</p>
</div>
</div>
</Layout>
<script>
const CLERK_KEY = 'pk_test_cGVhY2VmdWwta2F0eWRpZC05NC5jbGVyay5hY2NvdW50cy5kZXYk';
async function initClerk() {
const container = document.getElementById('clerk-signup');
if (!container) return;
try {
// @ts-ignore
const Clerk = window.Clerk;
if (!Clerk) {
// Load Clerk
const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/@clerk/clerk-js@latest/dist/clerk.browser.js';
script.async = true;
script.onload = () => {
// @ts-ignore
window.Clerk.load({ publishableKey: CLERK_KEY }).then(() => {
// @ts-ignore
window.Clerk.mountSignUp(container, {
appearance: {
baseTheme: undefined,
variables: {
colorPrimary: '#ffffff',
colorBackground: '#111111',
colorText: '#ffffff',
colorTextSecondary: '#737373',
colorInputBackground: '#0a0a0a',
colorInputText: '#ffffff',
borderRadius: '4px',
fontFamily: '"JetBrains Mono", monospace',
},
elements: {
card: 'bg-transparent shadow-none',
formButtonPrimary: 'bg-white text-black hover:opacity-90',
formFieldInput: 'bg-black border-gray-700 text-white',
footerActionLink: 'text-white hover:text-gray-300',
}
},
afterSignUpUrl: '/dashboard',
signInUrl: '/login',
});
});
};
document.head.appendChild(script);
} else {
await Clerk.load({ publishableKey: CLERK_KEY });
Clerk.mountSignUp(container, {
afterSignUpUrl: '/dashboard',
signInUrl: '/login',
});
}
} catch (e) {
container.innerHTML = `
<form id="fallback-signup" class="space-y-4">
<div>
<label class="block text-sm text-gray-400 mb-1 font-mono">Email</label>
<input type="email" name="email" required class="w-full bg-black border border-gray-700 rounded px-4 py-2.5 text-sm text-white font-mono focus:border-gray-500 focus:outline-none" />
</div>
<div>
<label class="block text-sm text-gray-400 mb-1 font-mono">Password</label>
<input type="password" name="password" required minlength="8" class="w-full bg-black border border-gray-700 rounded px-4 py-2.5 text-sm text-white font-mono focus:border-gray-500 focus:outline-none" />
</div>
<button type="submit" class="w-full bg-white text-black rounded py-3 text-sm font-medium font-mono hover:opacity-90">Create Account</button>
</form>
`;
}
}
initClerk();
</script>

96
src/styles/global.css Normal file
View File

@@ -0,0 +1,96 @@
@import "tailwindcss";
@import "@fontsource-variable/jetbrains-mono";
/* BLACKROAD GRAYSCALE-FIRST DESIGN SYSTEM v1.0
"Color as intentional layer. Built for clarity, built for scale."
Font: JetBrains Mono - The road is code.
*/
@theme {
--font-display: "JetBrains Mono Variable", monospace;
--font-body: "JetBrains Mono Variable", monospace;
--font-mono: "JetBrains Mono Variable", monospace;
/* Grayscale palette */
--color-black: #000000;
--color-gray-950: #0a0a0a;
--color-gray-900: #111111;
--color-gray-800: #1a1a1a;
--color-gray-700: #2d2d2d;
--color-gray-600: #404040;
--color-gray-500: #525252;
--color-gray-400: #737373;
--color-gray-300: #a3a3a3;
--color-gray-200: #d4d4d4;
--color-gray-100: #e5e5e5;
--color-white: #ffffff;
/* Semantic colors - grayscale */
--color-bg: var(--color-black);
--color-surface: var(--color-gray-900);
--color-border: var(--color-gray-700);
--color-border-hover: var(--color-gray-500);
--color-text: var(--color-white);
--color-text-muted: var(--color-gray-400);
--color-text-dim: var(--color-gray-500);
--color-accent: var(--color-white);
}
@layer base {
* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
body {
background-color: var(--color-bg);
color: var(--color-text);
font-family: var(--font-body);
font-size: 14px;
line-height: 1.618;
letter-spacing: -0.01em;
}
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-display);
font-weight: 700;
letter-spacing: -0.02em;
}
code, pre {
font-family: var(--font-mono);
}
}
@layer components {
.gradient-text {
color: var(--color-white);
}
.btn-primary {
background: var(--color-white);
color: var(--color-black);
font-weight: 600;
transition: opacity 0.15s ease;
}
.btn-primary:hover {
opacity: 0.9;
}
.btn-secondary {
border: 1px solid var(--color-gray-700);
color: var(--color-white);
transition: border-color 0.15s ease;
}
.btn-secondary:hover {
border-color: var(--color-gray-500);
}
.card {
background: var(--color-surface);
border: 1px solid var(--color-border);
}
}

14
tsconfig.json Normal file
View File

@@ -0,0 +1,14 @@
{
"extends": "astro/tsconfigs/strict",
"include": [
".astro/types.d.ts",
"**/*"
],
"exclude": [
"dist"
],
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}