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>
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
# 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/`
|
||||
Reference in New Issue
Block a user