mirror of
https://github.com/blackboxprogramming/blackroad-ai-dashboard.git
synced 2026-03-18 04:34:00 -05:00
Initial commit: BlackRoad AI Dashboard with 9 agents
This commit is contained in:
44
README.md
Normal file
44
README.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# BlackRoad AI Dashboard
|
||||||
|
|
||||||
|
**Live at:** ai.blackroad.io
|
||||||
|
|
||||||
|
## 🤖 Features
|
||||||
|
|
||||||
|
- View all 9 AI agents across 3 devices
|
||||||
|
- Real-time agent status
|
||||||
|
- Chat interface with each agent
|
||||||
|
- Team organization (Infrastructure, Creative, Coding)
|
||||||
|
- Beautiful dark mode UI
|
||||||
|
|
||||||
|
## 🚀 Agents
|
||||||
|
|
||||||
|
### Infrastructure Team (Lucidia)
|
||||||
|
- Lucidia 🖤 - Systems Lead
|
||||||
|
- Marcus 👔 - Product Manager
|
||||||
|
- Viktor 💪 - Senior Developer
|
||||||
|
- Sophia 📊 - Data Analyst
|
||||||
|
|
||||||
|
### Creative Team (Cecilia)
|
||||||
|
- CECE 💜 - Creative Lead
|
||||||
|
- Luna 🌙 - UX Designer
|
||||||
|
- Dante ⚡ - Backend Engineer
|
||||||
|
|
||||||
|
### Coding Team (Aria)
|
||||||
|
- Aria-Prime 🎯 - Code Specialist
|
||||||
|
- Aria-Tiny ⚡ - Quick Responder
|
||||||
|
|
||||||
|
## 🛠️ Development
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## 📦 Deployment
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
npm run build
|
||||||
|
# Deploy to Cloudflare Pages
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
Built with Next.js 14 + TypeScript
|
||||||
19
app/globals.css
Normal file
19
app/globals.css
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
||||||
|
background: linear-gradient(135deg, #000000 0%, #1a1a1a 100%);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
18
app/layout.tsx
Normal file
18
app/layout.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import './globals.css'
|
||||||
|
|
||||||
|
export const metadata = {
|
||||||
|
title: 'BlackRoad AI - Agent Network',
|
||||||
|
description: '9 AI agents working together across distributed Raspberry Pi devices',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<html lang="en">
|
||||||
|
<body style={{margin: 0, padding: 0, background: '#000', color: '#fff'}}>{children}</body>
|
||||||
|
</html>
|
||||||
|
)
|
||||||
|
}
|
||||||
177
app/page.tsx
Normal file
177
app/page.tsx
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
const agents = [
|
||||||
|
{ name: 'Lucidia', emoji: '🖤', role: 'Systems Lead', device: 'lucidia', model: 'tinyllama', team: 'Infrastructure' },
|
||||||
|
{ name: 'Marcus', emoji: '👔', role: 'Product Manager', device: 'lucidia', model: 'llama3.2:3b', team: 'Infrastructure' },
|
||||||
|
{ name: 'Viktor', emoji: '💪', role: 'Senior Developer', device: 'lucidia', model: 'codellama:7b', team: 'Infrastructure' },
|
||||||
|
{ name: 'Sophia', emoji: '📊', role: 'Data Analyst', device: 'lucidia', model: 'gemma2:2b', team: 'Infrastructure' },
|
||||||
|
{ name: 'CECE', emoji: '💜', role: 'Creative Lead', device: 'cecilia', model: 'cece', team: 'Creative' },
|
||||||
|
{ name: 'Luna', emoji: '🌙', role: 'UX Designer', device: 'cecilia', model: 'llama3.2:3b', team: 'Creative' },
|
||||||
|
{ name: 'Dante', emoji: '⚡', role: 'Backend Engineer', device: 'cecilia', model: 'codellama:7b', team: 'Creative' },
|
||||||
|
{ name: 'Aria-Prime', emoji: '🎯', role: 'Code Specialist', device: 'aria', model: 'qwen2.5-coder:3b', team: 'Coding' },
|
||||||
|
{ name: 'Aria-Tiny', emoji: '⚡', role: 'Quick Responder', device: 'aria', model: 'tinyllama', team: 'Coding' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
const [selectedAgent, setSelectedAgent] = useState(agents[0])
|
||||||
|
const [message, setMessage] = useState('')
|
||||||
|
const [messages, setMessages] = useState<Array<{agent: string, content: string}>>([])
|
||||||
|
|
||||||
|
const handleSend = async () => {
|
||||||
|
if (!message.trim()) return
|
||||||
|
|
||||||
|
// Add user message
|
||||||
|
const newMessages = [...messages, { agent: 'You', content: message }]
|
||||||
|
setMessages(newMessages)
|
||||||
|
|
||||||
|
// Simulate agent response (in production, this would call your backend API)
|
||||||
|
setTimeout(() => {
|
||||||
|
setMessages([...newMessages, {
|
||||||
|
agent: selectedAgent.name,
|
||||||
|
content: `Hello! I'm ${selectedAgent.name}, your ${selectedAgent.role}. I'm running on ${selected Agent.device} using ${selectedAgent.model}. How can I help with BlackRoad today?`
|
||||||
|
}])
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
|
setMessage('')
|
||||||
|
}
|
||||||
|
|
||||||
|
const teamAgents = {
|
||||||
|
Infrastructure: agents.filter(a => a.team === 'Infrastructure'),
|
||||||
|
Creative: agents.filter(a => a.team === 'Creative'),
|
||||||
|
Coding: agents.filter(a => a.team === 'Coding'),
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{padding: '2rem', maxWidth: '1400px', margin: '0 auto'}}>
|
||||||
|
<div style={{textAlign: 'center', marginBottom: '3rem'}}>
|
||||||
|
<h1 style={{fontSize: '3rem', marginBottom: '1rem', background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent'}}>
|
||||||
|
BlackRoad AI Network
|
||||||
|
</h1>
|
||||||
|
<p style={{color: '#888', fontSize: '1.2rem'}}>9 AI Agents • 3 Devices • Fully Operational</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1.5rem', marginBottom: '3rem'}}>
|
||||||
|
<div style={{background: '#1a1a1a', border: '1px solid #333', borderRadius: '12px', padding: '1.5rem', textAlign: 'center'}}>
|
||||||
|
<div style={{fontSize: '2.5rem', fontWeight: 'bold', color: '#667eea'}}>9</div>
|
||||||
|
<div style={{color: '#888', fontSize: '0.9rem'}}>AGENTS</div>
|
||||||
|
</div>
|
||||||
|
<div style={{background: '#1a1a1a', border: '1px solid #333', borderRadius: '12px', padding: '1.5rem', textAlign: 'center'}}>
|
||||||
|
<div style={{fontSize: '2.5rem', fontWeight: 'bold', color: '#667eea'}}>3</div>
|
||||||
|
<div style={{color: '#888', fontSize: '0.9rem'}}>DEVICES</div>
|
||||||
|
</div>
|
||||||
|
<div style={{background: '#1a1a1a', border: '1px solid #333', borderRadius: '12px', padding: '1.5rem', textAlign: 'center'}}>
|
||||||
|
<div style={{fontSize: '2.5rem', fontWeight: 'bold', color: '#00ff00'}}>100%</div>
|
||||||
|
<div style={{color: '#888', fontSize: '0.9rem'}}>OPERATIONAL</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(350px, 1fr))', gap: '2rem', marginBottom: '3rem'}}>
|
||||||
|
{Object.entries(teamAgents).map(([teamName, teamMembers]) => (
|
||||||
|
<div key={teamName} style={{background: '#1a1a1a', border: '1px solid #333', borderRadius: '12px', padding: '2rem'}}>
|
||||||
|
<h2 style={{fontSize: '1.5rem', color: '#667eea', marginBottom: '1.5rem'}}>
|
||||||
|
{teamName === 'Infrastructure' && '🏢'} {teamName === 'Creative' && '🎨'} {teamName === 'Coding' && '💻'} {teamName} Team
|
||||||
|
</h2>
|
||||||
|
{teamMembers.map(agent => (
|
||||||
|
<div
|
||||||
|
key={agent.name}
|
||||||
|
onClick={() => setSelectedAgent(agent)}
|
||||||
|
style={{
|
||||||
|
background: selectedAgent.name === agent.name ? '#667eea20' : '#0a0a0a',
|
||||||
|
border: selectedAgent.name === agent.name ? '1px solid #667eea' : '1px solid #222',
|
||||||
|
borderRadius: '8px',
|
||||||
|
padding: '1rem',
|
||||||
|
marginBottom: '1rem',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'all 0.3s ease'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{display: 'flex', alignItems: 'center', gap: '1rem'}}>
|
||||||
|
<span style={{fontSize: '1.5rem'}}>{agent.emoji}</span>
|
||||||
|
<div style={{flex: 1}}>
|
||||||
|
<div style={{fontWeight: 'bold', marginBottom: '0.25rem'}}>{agent.name}</div>
|
||||||
|
<div style={{color: '#888', fontSize: '0.9rem'}}>{agent.role}</div>
|
||||||
|
<div style={{color: '#666', fontSize: '0.75rem', marginTop: '0.25rem'}}>{agent.model}</div>
|
||||||
|
</div>
|
||||||
|
<div style={{width: '8px', height: '8px', borderRadius: '50%', background: '#00ff00'}}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{background: '#1a1a1a', border: '1px solid #333', borderRadius: '12px', padding: '2rem'}}>
|
||||||
|
<h2 style={{fontSize: '1.5rem', marginBottom: '1.5rem', color: '#667eea'}}>
|
||||||
|
Chat with {selectedAgent.emoji} {selectedAgent.name}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div style={{marginBottom: '1.5rem', padding: '1rem', background: '#0a0a0a', borderRadius: '8px'}}>
|
||||||
|
<div style={{color: '#888', marginBottom: '0.5rem'}}>Currently selected:</div>
|
||||||
|
<div style={{display: 'flex', alignItems: 'center', gap: '0.5rem'}}>
|
||||||
|
<span style={{fontSize: '1.5rem'}}>{selectedAgent.emoji}</span>
|
||||||
|
<span style={{fontWeight: 'bold'}}>{selectedAgent.name}</span>
|
||||||
|
<span style={{color: '#666'}}>•</span>
|
||||||
|
<span style={{color: '#888'}}>{selectedAgent.role}</span>
|
||||||
|
<span style={{color: '#666'}}>•</span>
|
||||||
|
<span style={{color: '#666', fontSize: '0.9rem'}}>{selectedAgent.device}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{maxHeight: '300px', overflowY: 'auto', padding: '1rem', background: '#0a0a0a', border: '1px solid #222', borderRadius: '8px', marginBottom: '1.5rem'}}>
|
||||||
|
{messages.length === 0 ? (
|
||||||
|
<div style={{color: '#666', textAlign: 'center', padding: '2rem'}}>
|
||||||
|
Send a message to start chatting with {selectedAgent.name}!
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
messages.map((msg, i) => (
|
||||||
|
<div key={i} style={{marginBottom: '1rem', padding: '1rem', borderRadius: '8px', background: '#1a1a1a'}}>
|
||||||
|
<div style={{color: '#667eea', fontWeight: 'bold', marginBottom: '0.5rem'}}>{msg.agent}</div>
|
||||||
|
<div style={{color: '#ddd'}}>{msg.content}</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{display: 'flex', gap: '1rem'}}>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={message}
|
||||||
|
onChange={(e) => setMessage(e.target.value)}
|
||||||
|
onKeyPress={(e) => e.key === 'Enter' && handleSend()}
|
||||||
|
placeholder="Type your message..."
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
background: '#0a0a0a',
|
||||||
|
border: '1px solid #333',
|
||||||
|
borderRadius: '8px',
|
||||||
|
padding: '1rem',
|
||||||
|
color: 'white',
|
||||||
|
fontSize: '1rem'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleSend}
|
||||||
|
style={{
|
||||||
|
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '8px',
|
||||||
|
padding: '1rem 2rem',
|
||||||
|
color: 'white',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
cursor: 'pointer'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Send
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{textAlign: 'center', marginTop: '4rem', paddingTop: '2rem', borderTop: '1px solid #333', color: '#666'}}>
|
||||||
|
<p>BlackRoad AI Network • Powered by Raspberry Pi Mesh</p>
|
||||||
|
<p style={{fontSize: '0.9rem', marginTop: '0.5rem'}}>Lucidia • Cecilia • Aria</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
9
next.config.js
Normal file
9
next.config.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
output: 'export',
|
||||||
|
images: {
|
||||||
|
unoptimized: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = nextConfig
|
||||||
21
package.json
Normal file
21
package.json
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"name": "blackroad-ai-dashboard",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "BlackRoad AI Agent Network Dashboard - Interact with 9 AI agents",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev -p 3030",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"deploy": "wrangler pages deploy .next"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "^14.2.0",
|
||||||
|
"react": "^18.3.0",
|
||||||
|
"react-dom": "^18.3.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^20.0.0",
|
||||||
|
"@types/react": "^18.3.0",
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
22
tsconfig.json
Normal file
22
tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [{"name": "next"}],
|
||||||
|
"paths": {"@/*": ["./*"]}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user