- Add design doc for Vercel-style deployment dashboard - Add wave-based implementation plan (4 waves, 11 agents) - Add implementation summary artifact - Update CLAUDE.md with CloudBeaver credentials Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.6 KiB
5.6 KiB
Deployment Dashboard Implementation
Date: 2026-02-06 19:30 Project: nuc-portal Context: Implemented Vercel-style deployment detail pages with parallel wave-based execution
Overview
Added a comprehensive deployment dashboard to nuc-portal that displays detailed information about individual deployments, including real-time container health, stats, build logs, and quick action buttons.
Architecture
User Flow:
Deployments Tab → Click Row → /deployments/[uuid] (Dashboard)
→ Click Chevron → Expand Logs Inline (preserved)
API Flow:
Dashboard Page
├── /api/deployments/[uuid] → Deployment details
├── /api/deployments/[uuid]/health → Container health (SWR 10s)
├── /api/deployments/[uuid]/stats → Container stats (SWR 10s)
└── /api/deployments/[uuid]/redeploy → Trigger new deployment
Files Created
| File | Purpose | Lines |
|---|---|---|
src/app/deployments/[uuid]/page.tsx |
Dynamic route for deployment details | ~150 |
src/components/DeploymentDashboard.tsx |
Main dashboard component with tabs | ~800 |
src/components/DeploymentSkeleton.tsx |
Loading, error, empty state components | ~200 |
src/lib/docker.ts |
Docker API helpers via SSH | ~150 |
src/app/api/deployments/[uuid]/health/route.ts |
Container health endpoint | ~50 |
src/app/api/deployments/[uuid]/stats/route.ts |
Container stats endpoint | ~60 |
src/app/api/deployments/[uuid]/redeploy/route.ts |
Redeploy trigger endpoint | ~50 |
Files Modified
| File | Changes |
|---|---|
src/components/DeploymentsTable.tsx |
Added expand button, row click navigation |
src/components/Icons.tsx |
Added missing icons (user, clock, share, etc.) |
src/components/index.ts |
Exported new components |
Features
Dashboard Tabs
- Deployment - Main view with metadata, preview, and collapsible sections
- Logs - Build logs with warning highlighting
- Resources - CPU, Memory, Network I/O, Block I/O
- Source - Git branch, commit, message
Real-Time Data (SWR)
- Health status polling every 10 seconds
- Container stats polling every 10 seconds
- Auto-refresh with loading states
Action Cards
| Card | Action | URL |
|---|---|---|
| Runtime Logs | Opens Dozzle | http://192.168.1.3:9999/container/{name} |
| Coolify | Opens Coolify deployment | http://coolify.nuc.lan:8000/... |
| Visit Site | Opens app FQDN | {deployment.fqdn} |
| Redeploy | Triggers new deployment | POST /api/.../redeploy |
Edge Cases Handled
in_progress- Shows "Building..." with amber bannererror- Shows error banner, auto-expands logscancelled- Shows grey cancelled state- Missing container - Graceful degradation with messages
- Missing git info - Shows "—" instead of crashing
- Null duration - Shows "In progress..."
Loading & Error States
DeploymentSkeleton- Animated loading skeletonDeploymentError- Error with retry buttonDeploymentEmpty- Empty state for edge cases
Docker API Helpers
src/lib/docker.ts provides:
// Execute command via SSH to NUC
sshExec(command: string): Promise<string | null>
// Get container health status
getContainerHealth(containerName: string): Promise<'healthy' | 'unhealthy' | 'starting' | 'none' | null>
// Get container resource stats
getContainerStats(containerName: string): Promise<{
cpuPercent: number;
memoryUsage: string;
memoryLimit: string;
memoryPercent: number;
netIO: { rx: string; tx: string };
blockIO: { read: string; write: string };
} | null>
// Get container uptime
getContainerUptime(containerName: string): Promise<{
startedAt: string;
seconds: number;
formatted: string;
} | null>
// Find container by app name or UUID
findContainerByAppName(appName: string): Promise<string | null>
findContainerByUuid(appUuid: string): Promise<string | null>
Implementation Method
Used parallel wave-based execution with 11 total agents:
| Wave | Tasks | Agents | Duration |
|---|---|---|---|
| Wave 1 | Route, Docker helpers, Table UI | 3 parallel | ~3.5 min |
| Wave 2 | Dashboard, Health API, Stats API, Navigation | 4 parallel | ~4.5 min |
| Wave 3 | Data integration, Links, Redeploy | 3 parallel | ~5 min |
| Wave 4 | Loading states, Edge cases | 2 parallel | ~3 min |
Total implementation time: ~16 minutes
Testing
# Start dev server
cd /Users/agutierrez/Desktop/nuc/nuc-portal
npm run dev
# Get a deployment UUID
curl http://localhost:3000/api/deployments | jq '.[0].deployment_uuid'
# Test dashboard page
open http://localhost:3000/deployments/<uuid>
# Test API endpoints
curl http://localhost:3000/api/deployments/<uuid>/health | jq
curl http://localhost:3000/api/deployments/<uuid>/stats | jq
curl -X POST http://localhost:3000/api/deployments/<uuid>/redeploy | jq
Dependencies Added
{
"swr": "^2.x" // For data fetching with auto-refresh
}
URLs Configuration
Per user request, Coolify URLs use domain name:
- ✅
http://coolify.nuc.lan:8000(not IP) - Dozzle still uses IP (no domain configured):
http://192.168.1.3:9999
Screenshots
Dashboard follows Vercel's deployment page design:
- Header with app icon, metadata grid
- Collapsible sections (Settings, Build Logs, Container Stats, Summary)
- Action cards grid at bottom
- Tab navigation (Deployment, Logs, Resources, Source)
Related
- Design doc:
.artifacts/2026-02-06_17-30_deployment-dashboard-design.md - Implementation plan:
.artifacts/2026-02-06_18-00_deployment-dashboard-implementation-plan.md - nuc-portal repo:
/Users/agutierrez/Desktop/nuc/nuc-portal/