Widget / HUD System (configurable dashboard layout) #41

Closed
opened 2026-01-29 18:22:46 +00:00 by jason.woltje · 0 comments
Owner

Overview

Add a Widget system for configurable HUD dashboard layouts. Single pane of glass with add/remove/move widgets.

Background

The HUD should be:

  • Single pane of glass — All data you need, when you need it
  • Reconfigurable — Add/remove/move widgets
  • Context-aware — Widgets can respond to current context
  • Data available when needed, gone when not

Requirements

Prisma Schema

model WidgetDefinition {
  id            String   @id @default(uuid()) @db.Uuid
  
  name          String   @unique
  displayName   String   @map("display_name")
  description   String?
  component     String   // React component name
  
  // Default size (grid units)
  defaultWidth  Int      @default(1) @map("default_width")
  defaultHeight Int      @default(1) @map("default_height")
  minWidth      Int      @default(1) @map("min_width")
  minHeight     Int      @default(1) @map("min_height")
  maxWidth      Int?     @map("max_width")
  maxHeight     Int?     @map("max_height")
  
  // Configuration schema (JSON Schema)
  configSchema  Json     @default("{}") @map("config_schema")
  
  isActive      Boolean  @default(true) @map("is_active")
  createdAt     DateTime @default(now()) @map("created_at") @db.Timestamptz
  
  @@map("widget_definitions")
}

model UserLayout {
  id          String   @id @default(uuid()) @db.Uuid
  workspaceId String   @map("workspace_id") @db.Uuid
  userId      String   @map("user_id") @db.Uuid
  
  name        String
  isDefault   Boolean  @default(false) @map("is_default")
  
  // Layout configuration (array of widget placements)
  // [{"widget": "critical-tasks", "x": 0, "y": 0, "w": 2, "h": 2, "config": {}}]
  layout      Json     @default("[]")
  
  createdAt   DateTime @default(now()) @map("created_at") @db.Timestamptz
  updatedAt   DateTime @updatedAt @map("updated_at") @db.Timestamptz
  
  // Relations
  workspace   Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
  user        User      @relation(fields: [userId], references: [id], onDelete: Cascade)
  
  @@unique([workspaceId, userId, name])
  @@map("user_layouts")
}

Default Widgets

  1. critical-tasks — Tasks with high/critical priority
  2. today-events — Events for today
  3. quick-capture — Brain dump input
  4. agent-status — Active agents and tasks
  5. upcoming-deadlines — Next 7 days deadlines
  6. domain-switcher — Quick domain filter
  7. project-status — Project progress overview
  8. recent-activity — Recent changes

API Endpoints

  • GET /api/widgets — List available widget definitions
  • GET /api/layouts — Get user layouts
  • GET /api/layouts/default — Get default layout
  • POST /api/layouts — Save layout
  • PATCH /api/layouts/:id — Update layout
  • DELETE /api/layouts/:id — Delete layout

UI

  • Grid-based layout — CSS Grid or react-grid-layout
  • Drag and drop — Move widgets
  • Resize handles — Resize widgets
  • Add widget modal — Browse available widgets
  • Layout presets — Save/load layouts
  • Edit mode toggle — Lock layout when not editing

Widget Props Interface

interface WidgetProps {
  workspaceId: string;
  config: Record<string, unknown>;
  width: number;
  height: number;
  onConfigChange?: (config: Record<string, unknown>) => void;
}

Acceptance Criteria

  • Prisma schema with migration
  • Widget definitions seeded
  • Layout API endpoints with tests
  • Grid-based HUD layout
  • Drag-and-drop widget positioning
  • Add/remove widget functionality
  • Save layout persistence
  • At least 2 working widgets (critical-tasks, quick-capture)
## Overview Add a **Widget** system for configurable HUD dashboard layouts. Single pane of glass with add/remove/move widgets. ## Background The HUD should be: - **Single pane of glass** — All data you need, when you need it - **Reconfigurable** — Add/remove/move widgets - **Context-aware** — Widgets can respond to current context - **Data available when needed, gone when not** ## Requirements ### Prisma Schema ```prisma model WidgetDefinition { id String @id @default(uuid()) @db.Uuid name String @unique displayName String @map("display_name") description String? component String // React component name // Default size (grid units) defaultWidth Int @default(1) @map("default_width") defaultHeight Int @default(1) @map("default_height") minWidth Int @default(1) @map("min_width") minHeight Int @default(1) @map("min_height") maxWidth Int? @map("max_width") maxHeight Int? @map("max_height") // Configuration schema (JSON Schema) configSchema Json @default("{}") @map("config_schema") isActive Boolean @default(true) @map("is_active") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz @@map("widget_definitions") } model UserLayout { id String @id @default(uuid()) @db.Uuid workspaceId String @map("workspace_id") @db.Uuid userId String @map("user_id") @db.Uuid name String isDefault Boolean @default(false) @map("is_default") // Layout configuration (array of widget placements) // [{"widget": "critical-tasks", "x": 0, "y": 0, "w": 2, "h": 2, "config": {}}] layout Json @default("[]") createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamptz // Relations workspace Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@unique([workspaceId, userId, name]) @@map("user_layouts") } ``` ### Default Widgets 1. **critical-tasks** — Tasks with high/critical priority 2. **today-events** — Events for today 3. **quick-capture** — Brain dump input 4. **agent-status** — Active agents and tasks 5. **upcoming-deadlines** — Next 7 days deadlines 6. **domain-switcher** — Quick domain filter 7. **project-status** — Project progress overview 8. **recent-activity** — Recent changes ### API Endpoints - `GET /api/widgets` — List available widget definitions - `GET /api/layouts` — Get user layouts - `GET /api/layouts/default` — Get default layout - `POST /api/layouts` — Save layout - `PATCH /api/layouts/:id` — Update layout - `DELETE /api/layouts/:id` — Delete layout ### UI - **Grid-based layout** — CSS Grid or react-grid-layout - **Drag and drop** — Move widgets - **Resize handles** — Resize widgets - **Add widget modal** — Browse available widgets - **Layout presets** — Save/load layouts - **Edit mode toggle** — Lock layout when not editing ### Widget Props Interface ```typescript interface WidgetProps { workspaceId: string; config: Record<string, unknown>; width: number; height: number; onConfigChange?: (config: Record<string, unknown>) => void; } ``` ## Acceptance Criteria - [ ] Prisma schema with migration - [ ] Widget definitions seeded - [ ] Layout API endpoints with tests - [ ] Grid-based HUD layout - [ ] Drag-and-drop widget positioning - [ ] Add/remove widget functionality - [ ] Save layout persistence - [ ] At least 2 working widgets (critical-tasks, quick-capture)
jason.woltje added this to the M3-Features (0.0.3) milestone 2026-01-29 18:25:33 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaic/stack#41