Files
nuc/.artifacts/2026-02-06_19-30_deployment-dashboard-implementation.md
Alejandro Gutiérrez 36698dbc79 Add deployment dashboard docs and artifacts
- 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>
2026-02-06 18:00:27 +01:00

174 lines
5.6 KiB
Markdown

# 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
1. **Deployment** - Main view with metadata, preview, and collapsible sections
2. **Logs** - Build logs with warning highlighting
3. **Resources** - CPU, Memory, Network I/O, Block I/O
4. **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 banner
- `error` - Shows error banner, auto-expands logs
- `cancelled` - 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 skeleton
- `DeploymentError` - Error with retry button
- `DeploymentEmpty` - Empty state for edge cases
## Docker API Helpers
`src/lib/docker.ts` provides:
```typescript
// 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
```bash
# 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
```json
{
"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/`