Observatory Platform
Technical overview of the Observatory visualization system
Observatory is the NeuAIs platform’s 3D visualization engine, providing real-time monitoring and interaction with large-scale agent networks.
Architecture
System Design
┌─────────────────────────────────────────────────────┐
│ User Interface │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Menu Bar │ │ Dock System │ │ Cards │ │
│ │ (Mac-style) │ │ (Auto-hide) │ │ (Floating)│ │
│ └──────────────┘ └──────────────┘ └───────────┘ │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ Visualization Engine │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Three.js │ │ Particle │ │ Camera │ │
│ │ Scene │ │ System │ │ Controls │ │
│ └──────────────┘ └──────────────┘ └───────────┘ │
└─────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────┐
│ Data Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ Static JSON │ │ WebSocket │ │ localStorage││
│ │ (Dev) │ │ API (Prod) │ │ (Config) │ │
│ └──────────────┘ └──────────────┘ └───────────┘ │
└─────────────────────────────────────────────────────┘
Core Components
1. Observatory Core (observatory-core.js)
- Three.js scene, camera, renderer initialization
- WebGL context management
- Animation loop (60 FPS)
- Camera controls (orbit, zoom, pan)
2. Visual Configuration (observatory-visual-config.js)
- Color scheme management
- Shape mappings
- User preferences
- localStorage persistence
3. Data Management (observatory-data.js, observatory-data-live.js)
- Static data definitions
- WebSocket client
- Real-time updates
- Data transformation
4. UI Systems
- Dock (
observatory-dock.js) - Auto-hiding bottom toolbar - Cards (
observatory-cards.js) - Floating information panels - Menu (
observatory-menu.js) - Top menu bar - Context Menu (
observatory-context-menu.js) - Right-click actions
5. Node Rendering
- Geometry creation (spheres, cubes, diamonds, pyramids, tori)
- Material configuration (Phong shading, emissive)
- Clustering algorithm
- LOD (Level of Detail) system
6. Particle System
- Bézier curve path generation
- Particle lifecycle management
- Connection inference
- Flow animation
Data Model
Entity Schema
{
// Required fields
id: string, // Unique identifier
name: string, // Display name
status: enum, // 'active' | 'idle' | 'starting' | 'error'
// Category (determines cluster)
category: enum, // 'agents' | 'services' | 'infrastructure'
// Optional fields
cpu: number, // CPU usage (0-100)
mem: string, // Memory usage ('24MB')
connections: string[], // Array of connected entity IDs
// Metadata
metadata: {
language: string, // 'go', 'rust', 'python', 'typescript'
template: string, // Template type identifier
env: string, // 'production', 'staging', 'development'
version: string, // Semantic version
uptime: number // Seconds since start
}
}
Categories
Agents (AI Workers)
- Position: Left cluster (-20, 0, 0)
- Colors: Green (#22c55e), Yellow (#facc15)
- Shape: Cube
- Count: Typically 9-1000+
Services (Microservices)
- Position: Center cluster (0, 8, 0)
- Colors: Blue (#3b82f6), Purple (#a855f7)
- Shape: Sphere
- Count: Typically 19
Infrastructure (Databases, Caches)
- Position: Right cluster (20, -5, 0)
- Colors: Orange (#f97316), Red (#ef4444)
- Shape: Octahedron (Diamond)
- Count: Typically 3-5
Connections
Connections are defined as arrays of entity IDs:
{
id: 'anomaly-detector',
connections: ['metrics-api', 'redis-cache']
}
Connection Inference:
- Type inferred from target entity category
- Particle color based on connection type
- Speed varies by type (cache: fast, database: slow)
Rendering Pipeline
Initialization
1. Load Data
├─ Fetch from API or load static
├─ Parse and validate
└─ Store in memory
2. Setup Scene
├─ Create THREE.Scene
├─ Add camera (PerspectiveCamera)
├─ Add lights (ambient + directional)
└─ Create renderer (WebGLRenderer)
3. Create Node Groups
├─ Group by category
├─ Calculate cluster positions
└─ Create THREE.Group for each
4. Generate Nodes
├─ For each entity:
│ ├─ Choose geometry (sphere, cube, etc.)
│ ├─ Apply material (color, emissive)
│ ├─ Position within cluster
│ └─ Add to scene
└─ Store node references
5. Create Particles
├─ For each connection:
│ ├─ Calculate Bézier path
│ ├─ Create N particles
│ └─ Set initial positions
└─ Add to scene
6. Initialize UI
├─ Create dock
├─ Setup menu handlers
├─ Initialize cards system
└─ Attach event listeners
7. Start Animation
└─ Begin 60 FPS loop
Animation Loop
Every frame (16.67ms target):
function animate() {
requestAnimationFrame(animate);
// 1. Update camera (orbit controls)
observatoryCore.updateCamera();
// 2. Animate nodes (pulsing effect)
nodes.forEach(node => {
const pulse = Math.sin(time + node.phase);
node.mesh.scale.set(pulse, pulse, pulse);
node.mesh.material.emissiveIntensity = 0.4 + pulse * 0.2;
});
// 3. Move particles along paths
particles.forEach(particle => {
particle.progress += particle.speed;
if (particle.progress > 1) particle.progress = 0;
const position = getBezierPoint(
particle.start,
particle.mid,
particle.end,
particle.progress
);
particle.mesh.position.copy(position);
});
// 4. Render scene
observatoryCore.render();
}
Visual Configuration System
Modes
1. Category Mode (Default)
- All agents same color
- All services same color
- All infrastructure same color
2. Type Mode
- Each type (postgres, redis, auth, etc.) has unique color
- Fine-grained visual differentiation
- Better for large systems
Shape System
Available Geometries:
{
'sphere': new THREE.SphereGeometry(size, 16, 16),
'cube': new THREE.BoxGeometry(size, size, size),
'octahedron': new THREE.OctahedronGeometry(size),
'tetrahedron': new THREE.TetrahedronGeometry(size),
'torus': new THREE.TorusGeometry(size * 0.6, size * 0.3, 8, 16)
}
Performance Characteristics:
| Shape | Vertices | Faces | Performance |
|---|---|---|---|
| Tetrahedron | 12 | 4 | Excellent |
| Octahedron | 24 | 8 | Excellent |
| Cube | 24 | 12 | Excellent |
| Sphere (16) | 289 | 256 | Good |
| Torus | 512+ | 256+ | Fair |
Configuration Persistence
Storage: Browser localStorage
Key: observatory-visual-config
Format: JSON
{
mode: 'type',
types: {
'postgres': {
color: '#3b82f6',
shape: 'octahedron',
label: 'PostgreSQL'
},
// ... more types
},
categories: {
'infrastructure': {
color: '#ef4444',
shape: 'octahedron'
},
// ... more categories
}
}
Performance Optimization
Scaling Strategies
< 100 Nodes:
- Default settings work well
- All effects enabled
- High quality mode
100-500 Nodes:
- Reduce sphere segments to 8
- Limit particles to 3 per connection
- Enable instanced rendering for identical shapes
500-1000 Nodes:
- Use cubes only (simpler geometry)
- Disable particle flows
- Implement frustum culling
- Reduce emissive intensity calculations
1000+ Nodes:
- Static rendering mode (no animation)
- 2D fallback option
- Virtual scrolling for node list
- Aggressive LOD system
Memory Management
Techniques:
- Object pooling for particles
- Geometry instancing
- Texture atlasing
- Dispose unused geometries
Monitoring:
// Memory usage
console.log(renderer.info.memory);
// Render stats
console.log(renderer.info.render);
GPU Optimization
Best Practices:
- Batch draw calls
- Minimize state changes
- Use BufferGeometry
- Enable hardware acceleration
- Avoid transparent materials where possible
WebSocket API
Connection
const ws = new WebSocket('ws://localhost:8080/ws/observatory');
ws.onopen = () => {
// Send authentication
ws.send(JSON.stringify({
type: 'auth',
token: 'your-jwt-token'
}));
};
Message Protocol
Client → Server:
// Subscribe to updates
{
type: 'subscribe',
categories: ['agents', 'services', 'infrastructure']
}
// Unsubscribe
{
type: 'unsubscribe',
categories: ['agents']
}
// Request snapshot
{
type: 'snapshot'
}
Server → Client:
// Initial snapshot
{
type: 'snapshot',
timestamp: 1701234567890,
data: {
agents: [...],
services: [...],
infrastructure: [...]
}
}
// Update event
{
type: 'update',
timestamp: 1701234567890,
entity: {
id: 'anomaly-detector',
status: 'active',
cpu: 15,
mem: '28MB'
}
}
// Delete event
{
type: 'delete',
id: 'old-agent-123'
}
Reconnection Strategy
let reconnectAttempts = 0;
const maxReconnectAttempts = 10;
const reconnectDelay = 1000; // ms
function reconnect() {
if (reconnectAttempts >= maxReconnectAttempts) {
console.error('Max reconnect attempts reached');
return;
}
reconnectAttempts++;
const delay = reconnectDelay * Math.pow(2, reconnectAttempts);
setTimeout(() => {
console.log(`Reconnecting... (attempt ${reconnectAttempts})`);
connectWebSocket();
}, delay);
}
Security
Authentication
JWT Token:
- Passed in WebSocket connection headers
- Validated on server before accepting connection
- Refreshed every 15 minutes
Authorization
Permissions:
observatory:view- View agents/servicesobservatory:control- Start/stop componentsobservatory:admin- Full access
Data Protection
Client-Side:
- No sensitive data in localStorage
- Preferences only (colors, shapes)
- JWT in memory only
Network:
- WSS (WebSocket Secure) in production
- TLS 1.3
- Certificate pinning
Browser Compatibility
Supported Browsers
| Browser | Version | Support | Notes |
|---|---|---|---|
| Chrome | 90+ | ✅ Full | Recommended |
| Firefox | 88+ | ✅ Full | Excellent |
| Edge | 90+ | ✅ Full | Chromium-based |
| Safari | 14+ | ⚠️ Partial | Limited WebGL 2.0 |
| Opera | 76+ | ✅ Full | Chromium-based |
Feature Detection
// Check WebGL support
function checkWebGLSupport() {
try {
const canvas = document.createElement('canvas');
return !!(
window.WebGLRenderingContext &&
(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'))
);
} catch (e) {
return false;
}
}
// Check WebGL 2.0
function checkWebGL2Support() {
try {
const canvas = document.createElement('canvas');
return !!canvas.getContext('webgl2');
} catch (e) {
return false;
}
}
Fallbacks
If WebGL unavailable:
- Show 2D canvas view
- List view with filters
- Table view with search
Testing
Unit Tests
Test Files:
tests/visual-config.test.jstests/data-transform.test.jstests/particle-system.test.js
Run Tests:
cd neuais.com/hub.neuais.com/observatory.neuais.com
npm test
Performance Tests
Benchmarks:
// Measure rendering performance
const stats = new Stats();
document.body.appendChild(stats.dom);
function animate() {
stats.begin();
// ... render code ...
stats.end();
}
Visual Regression Tests
Tools:
- Percy for screenshot comparison
- Backstop.js for visual diffs
Run:
npm run test:visual
Deployment
Build Process
# No build needed - static files
# Just copy to web server
cp -r neuais.com/hub.neuais.com/observatory.neuais.com /var/www/observatory
CDN Deployment
Files to CDN:
3d/skateboard/three.min.js(cached forever)css/*.css(versioned)js/*.js(versioned)assets/(cached forever)
Cache Headers:
Cache-Control: public, max-age=31536000, immutable # JS/CSS/Assets
Cache-Control: no-cache # HTML
Environment Configuration
Development:
const API_URL = 'ws://localhost:8080/ws';
const DEBUG = true;
Production:
const API_URL = 'wss://api.neuais.com/ws';
const DEBUG = false;
Monitoring
Client-Side Metrics
Track:
- FPS (frames per second)
- Memory usage
- WebSocket reconnections
- Error rate
- User interactions
Send to:
- Google Analytics
- Sentry (errors)
- Custom metrics endpoint
Server-Side Metrics
Track:
- WebSocket connections (active)
- Message rate (messages/sec)
- Update latency (ms)
- Connection duration (sec)
Future Development
Roadmap
v2.0 (Q1 2026):
- WebXR/VR support
- Multi-cluster visualization
- Historical playback
- Advanced filtering
v3.0 (Q2 2026):
- Collaborative features
- AI-powered insights
- Custom plugins
- Mobile app
Next: API Reference →