15 KiB
15 KiB
Homelab Topology Visualizer - Specification
1. Project Overview
Project Name: Homelab Topology Visualizer (HomelabTV) Type: Interactive Web Application Core Functionality: A visual, interactive graph-based UI that displays the complete topology of a homelab - from network infrastructure (UniFi gateway, VLANs) through hosts, Docker containers/services, to filesystem paths and files. Target Users: Homelab administrators, DevOps engineers, home network enthusiasts
2. UI/UX Specification
Layout Structure
┌─────────────────────────────────────────────────────────────────────────────────┐
│ HEADER: Logo + Title + View Mode Selector + Refresh Button │
├─────────────┬───────────────────────────────────────────────────┬───────────────┤
│ │ │ │
│ LEFT │ MAIN GRAPH CANVAS │ RIGHT │
│ PANEL │ (React Flow / D3.js) │ PANEL │
│ │ │ │
│ Subnodes │ Nodes connected by edges showing │ Details │
│ of │ relationships: │ Tabs: │
│ selected │ Gateway → VLAN → Host → Service → Volume │ │
│ node │ │ - Details │
│ │ [Interactive: click to select, │ - Config │
│ - List │ drag to pan, scroll to zoom] │ - Files │
│ - Click │ │ - Usage │
│ to │ │ - Importance │
│ select │ │ │
│ │ │ │
├─────────────┴───────────────────────────────────────────────────┴───────────────┤
│ FOOTER: Status bar (last refresh, node count, connection status) │
└─────────────────────────────────────────────────────────────────────────────────┘
- Header: Fixed, 56px height
- Left Panel: 280px width, collapsible
- Right Panel: 360px width, collapsible
- Graph Canvas: Flexible, fills remaining space
- Footer: Fixed, 32px height
Responsive Breakpoints
- Desktop (≥1200px): Full 3-column layout
- Tablet (768px-1199px): Left panel hidden, right panel 300px
- Mobile (<768px): Panels as overlays/drawers
Visual Design
Color Palette
/* Network Layer */
--network-gateway: #6366F1; /* Indigo - UniFi gateway */
--network-vlan: #8B5CF6; /* Purple - VLANs */
--network-wifi: #EC4899; /* Pink - Access points */
/* Host Layer */
--host-physical: #10B981; /* Emerald - Physical servers */
--host-vm: #14B8A6; /* Teal - Virtual machines */
--host-container: #F59E0B; /* Amber - LXC containers */
/* Service Layer */
--service-media: #EF4444; /* Red - Jellyfin, Radarr, etc */
--service-infra: #3B82F6; /* Blue - Traefik, Authentik */
--service-monitoring: #22C55E; /* Green - Prometheus, Grafana */
--service-ai: #F97316; /* Orange - Ollama, Litellm */
--service-storage: #06B6D4; /* Cyan - Storage services */
/* Filesystem Layer */
--filesystem-nfs: #84CC16; /* Lime - NFS mounts */
--filesystem-volume: #A855F7; /* Purple - Docker volumes */
--filesystem-path: #EAB308; /* Yellow - File paths */
/* UI Colors */
--bg-primary: #0F172A; /* Slate 900 */
--bg-secondary: #1E293B; /* Slate 800 */
--bg-tertiary: #334155; /* Slate 700 */
--text-primary: #F8FAFC; /* Slate 50 */
--text-secondary: #94A3B8; /* Slate 400 */
--border: #475569; /* Slate 600 */
--accent: #38BDF8; /* Sky 400 */
--success: #22C55E;
--warning: #F59E0B;
--error: #EF4444;
Typography
- Font Family:
"JetBrains Mono", "Fira Code", monospacefor data;"Inter", system-uifor UI - Sizes:
- H1 (Title): 24px, weight 700
- H2 (Section): 18px, weight 600
- H3 (Node name): 14px, weight 600
- Body: 13px, weight 400
- Caption: 11px, weight 400
Spacing System
- Base unit: 4px
- Padding: 8px (sm), 12px (md), 16px (lg), 24px (xl)
- Margins: 4px (xs), 8px (sm), 16px (md), 24px (lg)
- Border radius: 4px (sm), 8px (md), 12px (lg)
Visual Effects
- Node shadows:
0 2px 8px rgba(0,0,0,0.3) - Panel shadows:
0 4px 24px rgba(0,0,0,0.4) - Glow on hover:
0 0 12px var(--node-color) - Transitions: 200ms ease-out for all interactive elements
- Graph edges: Animated dashed lines for active connections
Components
Node Component
- Shape: Rounded rectangle (120x48px) or circle (48x48px) for endpoints
- Content: Icon + Label + Status indicator
- States:
- Default: bg-secondary, border solid
- Hover: Glow effect, scale 1.02
- Selected: Border 2px accent, elevated shadow
- Running: Green status dot
- Stopped: Red status dot
- Warning: Yellow status dot
Edge Component
- Style: Curved bezier lines with arrows
- States:
- Default: border 1px text-secondary
- Active/Selected: border 2px accent, animated dash
Left Panel - Subnodes
- Header: "CHILD NODES" with count badge
- List Items: Icon + Name + Type badge
- Interaction: Click to focus/select in graph
- Empty state: "No child nodes"
Right Panel - Details Tabs
- Tab Bar: Details | Config | Files | Usage | Importance
- Details Tab: IP, MAC, Status, Uptime, Type, Description
- Config Tab: YAML/JSON view of configuration
- Files Tab: Tree view of relevant file paths
- Usage Tab: CPU, Memory, Network graphs
- Importance Tab: Critical / High / Medium / Low with reasoning
View Mode Selector
- Options:
- 🌐 Network: Shows gateway, VLANs, WiFi, hosts
- 🖥️ Hosts: Shows hosts and their services
- 📦 Services: Shows all services and their dependencies
- 💾 Filesystem: Shows volumes, mounts, paths
- 🔗 Full: Complete topology (default)
3. Functionality Specification
Core Features
F1: Interactive Graph Visualization
- Render infrastructure as directed graph
- Pan, zoom, fit-to-view controls
- Click node to select (shows details)
- Double-click to focus/center
- Drag nodes to rearrange
- Minimap for navigation
F2: Node Selection & Navigation
- Single click: Select node, show details in right panel
- Double click: Zoom to node, expand children
- Right click: Context menu (copy IP, open URL, etc.)
- Keyboard: Arrow keys to navigate, Enter to select
F3: Multi-View Modes
- Network View: UniFi → VLANs → Subnets → Hosts
- Host View: Hosts → VMs/LXCs → Containers
- Service View: Services → Dependencies → Volumes
- Filesystem View: TrueNAS → NFS → Volumes → Paths
- Full View: Everything connected
F4: Detail Panels
Left Panel (Subnodes):
- Shows children of selected node
- Click to select in graph
- Shows node count per type
Right Panel (Details):
- 5 tabs with content
- Details: Basic info (IP, type, status)
- Config: Docker compose, YAML configs
- Files: Related file paths (clickable)
- Usage: Resource consumption
- Importance: 1-5 stars with why
F5: Data Discovery (Hybrid Approach)
Static Config (JSON/YAML):
{
"network": {
"gateway": { "model": "UniFi Dream Machine Pro", "ip": "192.168.1.1" },
"vlans": [
{ "id": 10, "name": "Family", "subnet": "192.168.10.0/24" },
{ "id": 30, "name": "IoT", "subnet": "192.168.30.0/24" },
{ "id": 50, "name": "Production", "subnet": "192.168.50.0/24" }
],
"wifi": [
{ "ssid": "Will of D.", "vlan": "default" },
{ "ssid": "Will of D. IoT", "vlan": 30 }
]
},
"hosts": [
{
"name": "ubuntu",
"ip": "192.168.50.61",
"type": "vm",
"role": "Primary Docker Host",
"containers": ["traefik", "jellyfin", "authentik", ...]
},
{
"name": "grizzley",
"ip": "192.168.50.84",
"type": "rpi5",
"role": "Edge Services",
"containers": ["frigate", "traefik"]
}
]
}
Auto-Discovery (SSH):
- SSH to hosts and run commands
docker ps --format jsonfor containersdocker network inspectfor network topologyls /mnt/truenas/for NFS mountscat /proc/cpuinfofor hardware info
F6: Search & Filter
- Search bar: Filter nodes by name
- Type filter: Show/hide node types
- Status filter: Running/Stopped/All
- Quick jump: Cmd+K to open command palette
F7: Real-time Updates
- Poll intervals: 30s (configurable)
- WebSocket option for live updates
- Visual indicator for stale data
User Interactions & Flows
-
Initial Load:
- Load static config
- Run auto-discovery in background
- Render graph with all nodes
- Fit to view
-
Select Node:
- Click node → Highlight path to root
- Left panel shows children
- Right panel shows details (Details tab)
-
Change View:
- Click view mode → Re-render graph with filter
- Preserve selected node if visible
-
View Service Config:
- Select service node
- Click "Config" tab
- Shows docker-compose.yml content
- Clickable file paths
-
Refresh Data:
- Click refresh → Show loading state
- Run discovery commands
- Update graph
- Show "Last updated: X seconds ago"
Data Handling
- State Management: React Context + useReducer
- Persistence: LocalStorage for user preferences (view mode, panel states)
- Caching: In-memory cache with 30s TTL
- Error Handling: Show stale data with warning banner if discovery fails
Edge Cases
- Host unreachable: Show node with "Offline" status, gray out
- Container stopped: Show with red indicator, allow config view
- Empty discovery: Use static config as fallback
- Large graphs (100+ nodes): Enable clustering, lazy render
- Mobile: Simplified single-panel view with drawer navigation
4. Technical Architecture
Tech Stack
- Framework: React 18 + TypeScript
- Build Tool: Vite
- Graph Library: React Flow (@xyflow/react)
- Styling: Tailwind CSS
- State: Zustand (lightweight)
- HTTP Client: Axios
- SSH: Node-SSH (backend) or jsch (frontend via proxy)
- Icons: Lucide React
- Charts: Recharts (for usage graphs)
Project Structure
homelab-topology/
├── src/
│ ├── components/
│ │ ├── Graph/
│ │ │ ├── TopologyGraph.tsx
│ │ │ ├── NodeComponent.tsx
│ │ │ ├── EdgeComponent.tsx
│ │ │ └── controls.tsx
│ │ ├── Panels/
│ │ │ ├── LeftPanel.tsx
│ │ │ ├── RightPanel.tsx
│ │ │ └── DetailTabs/
│ │ ├── Header/
│ │ │ └── Header.tsx
│ │ └── common/
│ │ ├── Button.tsx
│ │ ├── Badge.tsx
│ │ └── Tabs.tsx
│ ├── hooks/
│ │ ├── useTopology.ts
│ │ ├── useDiscovery.ts
│ │ └── useSelection.ts
│ ├── store/
│ │ └── topologyStore.ts
│ ├── types/
│ │ └── index.ts
│ ├── utils/
│ │ ├── graphLayout.ts
│ │ └── formatters.ts
│ ├── data/
│ │ └── staticConfig.ts
│ ├── services/
│ │ └── discovery.ts
│ ├── App.tsx
│ ├── main.tsx
│ └── index.css
├── public/
├── docker/
│ └── Dockerfile
├── package.json
├── tsconfig.json
├── vite.config.ts
├── tailwind.config.js
└── README.md
Backend/API (Optional)
If running auto-discovery, need a small backend:
- Technology: Node.js + Express
- Purpose: Proxy SSH commands to homelab hosts
- Endpoints:
GET /api/discover/:host- Run discovery on specific hostGET /api/containers- Get all containers across hostsGET /api/volumes- Get all Docker volumes
5. Acceptance Criteria
Visual Checkpoints
- Graph renders with nodes and edges
- Nodes are color-coded by type
- Clicking a node highlights it and shows details
- Left panel shows child nodes of selected
- Right panel shows 5 tabs with content
- View mode selector changes graph content
- Panels can be collapsed/expanded
- Search filters nodes in real-time
Functional Checkpoints
- Initial data loads from static config
- Auto-discovery populates missing data
- Graph is pannable and zoomable
- Node selection is persistent across view changes
- Config tab shows Docker compose content
- Files tab shows relevant file paths
- Refresh button updates data
Performance Checkpoints
- Initial load < 2 seconds
- Graph renders 100+ nodes smoothly
- Interactions feel responsive (< 100ms)
Deployment Checkpoints
- Builds successfully with
npm run build - Docker image builds and runs
- Accessible at localhost:3000
- Works in browser via local network
6. Data Model
Node Types
type NodeType =
| 'gateway'
| 'vlan'
| 'wifi'
| 'host_physical'
| 'host_vm'
| 'host_container'
| 'service'
| 'volume'
| 'mount'
| 'path';
interface TopologyNode {
id: string;
type: NodeType;
name: string;
data: {
ip?: string;
mac?: string;
status: 'running' | 'stopped' | 'unknown';
metadata: Record<string, any>;
config?: string;
files?: string[];
importance: 1 | 2 | 3 | 4 | 5;
};
position?: { x: number; y: number };
}
interface TopologyEdge {
id: string;
source: string;
target: string;
type?: string;
label?: string;
}
7. Implementation Priority
Phase 1 (MVP - Week 1)
- Set up React + React Flow project
- Create static config with hardcoded topology
- Render basic graph with nodes and edges
- Implement node selection
- Build right panel with Details tab
- Add view mode selector
Phase 2 (Week 2)
- Complete right panel tabs (Config, Files, Usage, Importance)
- Build left panel with child nodes
- Add search and filters
- Implement basic auto-discovery (Docker)
Phase 3 (Week 3)
- Add SSH-based discovery
- Implement real-time updates
- Add animations and polish
- Create Docker build
Phase 4 (Ongoing)
- Add more node types
- Improve auto-discovery coverage
- Add mobile optimizations
- Add saved layouts