# Gadget Code IDE Style Guide Gadget Code is an Agentic Integrated Development Environment (AIDE). It is a tool for professional software developers and project managers to use in the creation of software applications and solutions, to include: code, documentation, configuration, etc. The brand color is #c20600, a rich red. It is to be used when printing Gadget Code. The Gadget Code IDE (hereafter: IDE) is an HTML5 web app building using the latest stable ReactJS 19 and Tailwind CSS 4. The IDE delivers only industrial and purposeful dark theme that uses mostly blacks, near-black, and dark gray with light gray and brand color highlights. Information-dense status and property panels. Tight margins and padding. This is NOT a consumer news blog with giant bloated hero sections, etc. We prefer flat material design with thoughtful borders that help the eye find the information and focus on it - not distract from it. ## Theme Colors The IDE uses the following color palette (CSS custom properties): ``` --color-brand: #c20600 --color-bg-primary: #0a0a0a (main background - pure black) --color-bg-secondary: #121212 (panels, sidebars) --color-bg-tertiary: #1a1a1a (cards, dropdowns) --color-bg-elevated: #202020 (hover states) --color-text-primary: #d4d4d4 (main text) --color-text-secondary: #a3a3a3 (muted text) --color-text-muted: #737373 (disabled, hints) --color-border-subtle: #1a1a1a (subtle dividers) --color-border-default: #2a2a2a (default borders) --color-border-highlight: #3a3a3a (emphasis borders) ``` Font stack: - Primary: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif - Code/Retro: Courier New, Courier, monospace ## View Layout (Whole Application) The root element is given fixed positioning to fill the browser view entirely, and presents a full-width/full-height Flex column that spans the entire view. ``` #root { height: 100vh; display: flex; flex-direction: column; overflow: hidden; } ``` The top row is the header bar (48px). The 2nd row is the content area (flex-1). The 3rd/bottom row is the status bar (32px). ### Header Bar The header bar is basically our "window title bar" like for a desktop application: ``` GADGET CODE v1.0.0 [Username ▼] ``` - Left: Application title + version using Courier New font - Right: User dropdown menu (display name, click to open) - Settings (placeholder) - Logout Implementation: `frontend/src/components/Header.tsx` ### Status Bar The status bar displays: ``` Ready. my-project | BUILD | ● ``` - Left: Status message ("Ready." default) - Center-right: Active project slug (when selected), Session mode (PLAN/BUILD/TEST/SHIP/DEV) - Right: Connection indicator (● = connected, animates when healthy) Implementation: `frontend/src/components/StatusBar.tsx` ### Content Area Between the header and status bars is the Content Area. It uses React Router for URL-based navigation: | Route | View | | ----------------- | ------------------------------------------------- | | `/` | Home (authenticated dashboard or unauthenticated) | | `/projects` | Project Manager (list view) | | `/projects/:slug` | Project Manager (project selected) | | `/projects/new` | New project form | | `/sign-in` | Sign in page | | `/sign-out` | Signs out and redirects to `/` | ## Unauthenticated Home View The logged-out home view displays a "System Ready" prompt dialog. - Font: Courier New (monospace) - Background: #0a0a0a (pure black) - Boxed with 2px border using border-default color - Sign In button Users do not "sign up" for Gadget Code - accounts are administered via CLI (`pnpm cli`). Implementation: `frontend/src/pages/Home.tsx` - SystemReady component ## Authenticated Home View (Dashboard) The authenticated home view presents: ``` [Welcome, Username!] Your dashboard is under construction. Select a project or chat session from the sidebar to get started. [Open Project Manager] +---------------------------+-----------------------+ | | Clock (AM/PM) | | Reserved for future | Date | | dashboard content +-----------------------+ | | Projects [+] | | | - project-1 | | | - project-2 | | +-----------------------+ | | Drones | | | - drone-alpha ● | | | - drone-beta ○ | | +-----------------------+ | | Recent Chats | | | (loading...) | +---------------------------+-----------------------+ ``` Components: 1. Clock - local time in AM/PM format, current date 2. Projects list - links to `/projects/:slug`, [+]/link navigates to `/projects` 3. Drones list - status indicator (green=available, yellow=busy, gray=offline) 4. Recent Chats - loading placeholder (stubbed, requires ChatSession API) Implementation: `frontend/src/pages/Home.tsx` - DashboardSidebar component ### Drone Inspector (Dashboard Inline) When a user clicks a drone in the sidebar's Drones list, the main content area switches to the **Drone Inspector**: ``` +-----------------------------------------------------+ | Drone Inspector ← Back to | | Dashboard | +-----------------------------------------------------+ | +-------------------------------------------------+ | | | Hostname | | | | drone-alpha (mono) | | | +-------------------------------------------------+ | | | Workspace | | | | /path/to/workspace (mono) | | | +-------------------------------------------------+ | | | Status | | | | ● available (or ● busy, ● offline) | | | +-------------------------------------------------+ | | | Registered | | | | 5/14/2026, 10:00:00 AM | | | +-------------------------------------------------+ | +-----------------------------------------------------+ ``` Implementation: `frontend/src/pages/Home.tsx` - DroneInspector component (lines 36-93) The Drone Inspector is a simple read-only card view. For full drone operations (terminate, logs, monitoring), users navigate to the Drone Manager at `/drones` via the gear icon in the Drones sidebar header. ## Drone Manager View Route: `/drones` The Drone Manager is a full-page view for detailed drone inspection and operations. It replaces the main content area entirely. Layout: ``` +----------------------------------+----------------------------------------+ | Drone Manager | Drone Details [Terminate] | +----------------------------------+----------------------------------------+ | Online Drones (N) | +-----------+ +-----------+ | | | | Hostname | | Status | | | +----------------------------+ | | drone-1 | | ● busy | | | | ● drone-1 available | | +-----------+ +-----------+ | | | /path/to/workspace | | +-----------+ +-----------+ | | +----------------------------+ | | Workspace | | Registered| | | +----------------------------+ | | /path/... | | 5/14/2026 | | | | ● drone-2 busy | | +-----------+ +-----------+ | | | /path/to/workspace | | | | +----------------------------+ | Drone Monitor | | | +--------------------------------------+ | | Offline Drones (N) | | Monitor charts coming soon. | | | | | Memory usage, AI operations, and log | | | +----------------------------+ | | production metrics will be displayed | | | | ○ drone-3 offline | | | here. | | | | /path/to/workspace | | +--------------------------------------+ | | +----------------------------+ | | | | Drone Log (Live) | | | +--------------------------------------+ | | | | [10:00:01] [PLACEHOLDER] Log entry 1 | | | | | [10:00:02] [PLACEHOLDER] Log entry 2 | | | | | [10:00:03] [PLACEHOLDER] Log entry 3 | | | | | ... | | | | +--------------------------------------+ | +----------------------------------+----------------------------------------+ ``` Current features (Phase 1): - **Drone list** (left sidebar): Split into Online and Offline sections. Each list item shows status dot, hostname, and workspace path. Click to inspect. - **Drone details** (right panel, top): 2x2 grid showing hostname, status with dot, workspace, registration date. Terminate button (red) for non-offline drones. - **Drone Monitor** (right panel, middle): Placeholder for future monitoring charts. - **Drone Log** (right panel, bottom): Collapsible panel with auto-scrolling log viewer. Log entries show timestamp and message. Auto-scroll pauses when user scrolls up, resumes when scrolled to bottom. Max 200 entries shown. Placeholder entries currently used, awaiting live log streaming. Implementation: `frontend/src/pages/DroneManager.tsx` ### Phase 2: SubProcess Monitor (Complete) Phase 2 was implemented on the `feature/process-management` branch. The Drone Manager and Drone Inspector now show live SubProcess data and drone logs via Socket.IO. #### Socket Protocol Three new socket events added (defined in `packages/api/src/messages/subprocess.ts`): | Event | Direction | Purpose | Mechanism | |-------|-----------|---------|-----------| | `requestProcessStats` | IDE → Backend → Drone | Request typed subprocess list | Callback-chain (like `fileTreeRequest`) | | `subscribeDrone` | IDE → Backend | Subscribe to live drone events (log, status) | Registers socket in monitor index | | `unsubscribeDrone` | IDE → Backend | Unsubscribe from live drone events | Removes socket from monitor index | Broadcast events (backend → IDE, no request needed): | Event | Payload | When | |-------|---------|------| | `drone:log` | `{ timestamp, level, component, message, metadata? }` | On every drone `log` emission | | `drone:status` | `{ timestamp, message }` | On every drone `status` emission | #### SubProcess Table Rendered by `frontend/src/components/SubProcessTable.tsx`. Features: - Monospace table: PID, CMD, PROJECT, STATUS, UPDATED - Status dots: green for running, yellow for halted, red for error - Clickable rows with selection highlight - Header shows running count: "SubProcess Monitor (3 running)" - Empty state: "No managed subprocesses. The agent has not spawned any processes for this session." #### Resource Gauges (Canvas) Rendered by `frontend/src/components/DroneMonitor.tsx` + `DroneMonitorGauge.tsx`: ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ CPU │ │ NETWORK │ │ FILE I/O │ │ ▁▂▃▄▅▆▇█▇▆ │ │ ▁▂▃▄▅▆▇█▇▆ │ │ ▁▂▃▄▅▆▇█▇▆ │ │ 42% │ │ 27% │ │ 15% │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` - Canvas-based waveform with glow effect (studio/scientific equipment aesthetic) - Brand red for CPU, cyan for NETWORK, green for FILE I/O - Grid lines, numeric readout, gradient fill under trace - Data is currently simulated (random walk) — placeholder for real metrics #### Live Log Streaming The Drone Log viewer now receives real log events via socket instead of placeholders: - Log events flow: `drone` → `DroneSession.onLog()` → broadcast to monitor sessions via `drone:log` event - Uses the same `LogRenderer` component as the ChatSession `LogPanel` (refactored in Phase 2) - Auto-scroll with pause-on-scroll-up behavior preserved - Max 200 entries maintained #### DroneInspector (Dashboard) The inline Drone Inspector in the Home page (`frontend/src/pages/Home.tsx`): - Shows SubProcess count summary ("3 running" or "No managed processes") - Contains a compact `LogRenderer` (last 50 entries, max-h-48) - "Open in Drone Manager →" link navigates to `/drones` with route state for auto-selection #### Polling Behavior - `requestProcessStats` polled every **1 second** while a drone is selected (both DroneManager and DroneInspector) - Subscribe/unsubscribe lifecycle tied to component mount/unmount - All timers and socket listeners cleaned up on unmount or drone deselection #### Supporting Components | Component | File | Purpose | |-----------|------|---------| | `SubProcessTable` | `frontend/src/components/SubProcessTable.tsx` | Process list table | | `DroneMonitor` | `frontend/src/components/DroneMonitor.tsx` | 3-gauge resource monitor container | | `DroneMonitorGauge` | `frontend/src/components/DroneMonitorGauge.tsx` | Canvas waveform gauge | | `LogRenderer` | `frontend/src/components/LogRenderer.tsx` | Reusable log rendering core | #### Backend Routing - `SocketService.addDroneMonitor()` / `removeDroneMonitor()` — manages monitor index (`Map>`) - `SocketService.broadcastToMonitors()` — broadcasts events to all monitoring sockets - `SocketService.getDroneSessionByRegistrationId()` — lookup for non-chat-session drone routing - `DroneSession.onLog()` / `onStatus()` — extended to broadcast to monitors after chat-session routing - `CodeSession.onRequestProcessStats()` — proxies to drone with callback - `CodeSession.onSubscribeDrone()` / `onUnsubscribeDrone()` — registers/unregisters monitor ## Project Manager View The Project Manager presents: ``` +---------------------------+----------------------------------+ | [New Project] | Project Inspector | |---------------------------| | | Projects (2) | Select a project to view details | | [project-one ] | or create a new project | | [project-two ] | | | | | +---------------------------+----------------------------------+ ``` When a project is selected: ``` +---------------------------+---------------------------------+ | [New Project] | Project Inspector | |---------------------------| | | Projects (2) | Name: project-one | | [project-one ●] | Slug: project-one | | [project-two ] | Git URL: https://github.com/... | | | Status: active | | | Created: 2026-04-28 | | | | | | [Delete Project] | | +---------------------------------+ | | Chat Sessions | | | (loading...) | +---------------------------+---------------------------------+ ``` Features: - Left sidebar: Project list with [+ New Project] button - Project Inspector: Shows name, slug, gitUrl, status, createdAt - Delete: Confirmation before deletion - Chat Sessions placeholder (requires ChatSession API) URL-based: `/projects` (list), `/projects/:slug` (selected) Implementation: `frontend/src/pages/ProjectManager.tsx` ### New Project Form Triggered by [New Project] button or `/projects/new` route: - Fields: Project Name*, Project Slug*, Git Repository URL - Slug tip: "Unique identifier for the project directory" - Submit: "Create Project" button (brand color) - Cancel: Returns to project list ## Authentication ### Frontend Token Management - Token stored in localStorage: `dtp_auth_token` - User stored in localStorage: `dtp_user` - Project stored in localStorage: `dtp_current_project` ### API Requests All API requests include the JWT in the Authorization header: ```typescript headers["Authorization"] = `Bearer ${token}`; ``` ### Backend Session Restoration The backend restores user sessions from: 1. `Authorization: Bearer ` header (JWT) 2. Express session (fallback) The `requireUser()` middleware ensures endpoints are authenticated. ## Security ### Password Field Handling Password credentials are NEVER exposed: - Mongoose `select: false` on password fields in models - Population uses `select: "-passwordSalt -password"` to exclude from queries - Frontend User interface only includes: `_id`, `email`, `displayName`, `flags` ## Chat Session View (Planned) The Chat Session View presents: ``` Work Area | Session Status ----------------------------------------------|--------------- Chat Messages | Chat: name | ID: ... | Model: ... ----------------------------------------------|--------------- [Prompt input ][Expand][Send]| TC | FO | SA ----------------------------------------------|--------------- Log | Files | ``` Implemented components: - Chat Messages (stubbed) - Prompt Input (stubbed) - Session Status sidebar (stubbed) - File Browser (stubbed) ## Mobile Devices and Responsive Design Nope. Gadget Code is a desktop workstation experience with one or more high-resolution displays, keyboard, mouse, webcam, microphone, and ample networking. There is no planned support for mobile devices. Buttons are normal-sized, not bloated for finger use. ## Accessibility The IDE wants to be as accessible as possible, providing aria tags as much as possible. Build first with an eye toward accessibility, then take a 2nd pass after the build is accepted to add accessibility enhancements. ## Tests ### Unit Tests Location: `tests/**/*.test.ts` (excluding `tests/e2e/`) Run: `pnpm test` ### E2E Tests Location: `tests/e2e/**/*.test.ts` Run: `npx playwright test` Prerequisites: Running `pnpm dev:backend` and `pnpm dev:frontend` Target: `https://code-dev.g4dge7.com:5174` ## Build Commands ```bash cd gadget-code pnpm dev:backend # Backend on https://localhost:3443 pnpm dev:frontend # Frontend on https://localhost:5174 pnpm build # Build all (backend -> dist/, frontend -> frontend/dist/) pnpm test # Unit tests npx playwright test # E2E tests ```