Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions IDEAS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Drawbridge — Future Ideas & Experiments

**Last Updated:** Feb 26, 2026

Ideas captured from Daily Briefing insights, community research, and experimentation. Not commitments—just directions worth exploring.

---

## Automated Visual Testing (Inspired by vinext)

**Context:** Cloudflare rebuilt Next.js with AI (vinext) and used automated screenshot comparisons to catch visual regressions. Zero-friction performance/visual testing loop.

**Idea for Drawbridge:**
- Capture before/after screenshots when AI tools modify UI
- Diff comparison in side panel (visual regression detection)
- Lightweight Lighthouse integration: "Run audit → JSON → Cursor → deploy"
- Could surface performance impact of AI-generated changes in real-time

**Why it fits:**
- Drawbridge already has DOM access and visual context
- Designers care about visual fidelity—AI code changes can introduce subtle layout shifts
- Closes the feedback loop: generate → test → fix in one interface

**Exploration steps:**
1. Spike: Puppeteer screenshot capture on annotation save
2. Diff algorithm (pixel-diff or structural similarity)
3. UI: Show visual diff in side panel alongside annotations
4. Lighthouse JSON ingestion (how to surface perf insights?)

**Effort:** Medium (2-3 weeks)
**Impact:** High (catches AI mistakes designers would otherwise miss)

---

## Multi-Agent Parallel Development (Emdash Pattern)

**Context:** Emdash (YC W26) lets you run multiple coding agents in parallel using Git worktrees. Each agent works in isolation, then results merge. Pattern: orchestrator delegates tasks to specialist agents.

**Idea for Drawbridge:**
- Architect Drawbridge V3+ as multi-agent system
- Example: One agent per component (sidebar, content script, background.js)
- Orchestrator (Claude Opus?) coordinates, resolves conflicts
- Faster iteration: 3 agents working in parallel vs. sequential

**Why it fits:**
- Chrome extension = naturally modular (content script, background, popup, options)
- Each component has clear boundaries
- Parallel development could 3x velocity for large features

**Exploration steps:**
1. Spike: Claude Opus as orchestrator + 3x Haiku agents for isolated tasks
2. Use Beacon (context sync) to keep agents aligned
3. Test on known refactor (e.g., V2 cleanup task)
4. Measure: time savings, merge conflicts, code quality

**Effort:** High (4-6 weeks to productionize)
**Impact:** Uncertain (depends on merge complexity, could be 2-3x faster or messy)

---

## Agent Spawning from Drawbridge Prompt

**Context:** Daily Briefing methodology = sub-agent does research, main agent synthesizes. Could Drawbridge spawn agents on-demand?

**Idea:**
- User annotates UI issue: "Fix this button alignment"
- Drawbridge spawns Claude Code session with full context (screenshot, DOM, annotations)
- Agent implements fix, reports back to Drawbridge
- User reviews in side panel, approves/rejects

**Why it fits:**
- Drawbridge already captures visual context
- Natural handoff: annotation → agent session → implementation → review
- Keeps user in flow (no context-switch to separate Claude Code window)

**Exploration steps:**
1. Spike: Can Drawbridge invoke Claude Code CLI programmatically?
2. Pass context bundle: screenshot + DOM + annotation text
3. Async workflow: spawn agent, poll for completion, surface result
4. UI: "Fix with AI" button on annotations

**Effort:** Medium-High (3-4 weeks)
**Impact:** High (removes context-switch, keeps designer in Drawbridge UI)

**Blocker:** Requires Claude Code CLI access or API (currently manual workflow)

---

## Implementation Priority (Rough Estimate)

| Idea | Effort | Impact | Priority |
|------|--------|--------|----------|
| **Automated Visual Testing** | Medium | High | **P1** (fits V2 naturally) |
| **Agent Spawning** | Medium-High | High | **P2** (after Claude Code API access) |
| **Multi-Agent Architecture** | High | Uncertain | **P3** (research phase, revisit post-V2) |

---

## Notes

- **Visual testing** aligns with Drawbridge's core value prop (visual context for AI tools)
- **Agent spawning** requires infrastructure (Claude Code CLI/API) but would be killer UX
- **Multi-agent** is speculative—needs validation before committing resources

All ideas sourced from Feb 25-26 Daily Briefing insights. Revisit quarterly or when new capabilities unlock.
252 changes: 252 additions & 0 deletions JOBS-TO-BE-DONE.md

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions STYLEGUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Drawbridge Style Guide

## Typography

### Fonts

| Purpose | Font | Fallbacks |
|---------|------|-----------|
| **UI Text** | `Space Grotesk` | `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif` |
| **Code** | `SF Mono` | `Monaco, Consolas, monospace` |

```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300..700&display=swap" rel="stylesheet">
```

### Type Scale

| Style | Size | Weight |
|-------|------|--------|
| H1 | 20px | 600 |
| H2 | 18px | 600 |
| H3 | 16px | 600 |
| Body | 14px | 400 |
| Small | 12px | 500 |
| Caption | 11px | 500 |
| Code | 13px | 400 |

---

## Colors

### Light Theme

| Token | Value |
|-------|-------|
| **Background** | `#ffffff` |
| **Surface** | `#f9fafb` |
| **Surface Alt** | `#f3f4f6` |
| **Border** | `#e5e7eb` |
| **Text** | `#1f2937` |
| **Text Secondary** | `#4b5563` |
| **Text Muted** | `#9ca3af` |
| **Accent** | `#3b82f6` |
| **Success** | `#059669` |
| **Warning** | `#d97706` |
| **Error** | `#dc2626` |

### Dark Theme

| Token | Value |
|-------|-------|
| **Background** | `#111827` |
| **Surface** | `#1f2937` |
| **Surface Alt** | `#374151` |
| **Border** | `#374151` |
| **Text** | `#f9fafb` |
| **Text Secondary** | `#e5e7eb` |
| **Text Muted** | `#9ca3af` |
| **Accent** | `#60a5fa` |
| **Success** | `#10b981` |
| **Warning** | `#fbbf24` |
| **Error** | `#f87171` |

### Status Colors (Both Themes)

| Status | Color |
|--------|-------|
| To-Do | `#F59E0B` |
| In Progress | `#3B82F6` |
| Done | `#10B981` |
| Error | `#EF4444` |
61 changes: 61 additions & 0 deletions V2_CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Drawbridge v2 Changelog

**Version bump:** 1.1.0 → **2.0.0**

## Architecture: Side Panel Migration

The biggest change is moving from an **injected in-page sidebar** (`moat.js` + `moat.css`) to Chrome's native **Side Panel API** (`chrome.sidePanel`). This is a fundamental UI architecture shift:

| | v1 (main) | v2 |
|---|---|---|
| **UI host** | `moat.js` injected into web pages (~3,900 lines) | `sidepanel/` — dedicated Chrome side panel (3 files) |
| **Styles** | `moat.css` (2,390 lines injected into pages) | `sidepanel.css` (629 lines, scoped) + `content.css` (169 lines, minimal page injection) |
| **Activation** | Extension icon → `toggleMoat` message → in-page sidebar | Extension icon → `chrome.sidePanel.open()` |
| **Communication** | Direct — JS runs in page context | Message relay via `background.js` (content script ↔ side panel) |

## Deleted Files (-6,319 lines)
- **`moat.js`** — entire in-page sidebar UI removed
- **`moat.css`** — all in-page sidebar styles removed

## New Files
- **`sidepanel/sidepanel.html`** — side panel markup with header, tabs (To Do / Doing / Done), tools dropdown, project connection UI
- **`sidepanel/sidepanel.js`** (~730 lines) — full side panel logic: task rendering, project connect/disconnect, thumbnail loading, theme toggle, retry-based content script communication
- **`sidepanel/sidepanel.css`** (~630 lines) — polished styles with light/dark theme support via CSS custom properties
- **`content.css`** (~170 lines) — lightweight styles for overlays, comment boxes, and drawing canvas injected into pages
- **`STYLEGUIDE.md`** — design system documentation (typography, colors, status colors)

## Modified Files

### `manifest.json`
- Added `sidePanel` permission
- Registered `sidepanel/sidepanel.html` as default side panel
- Removed `moat.js` and `moat.css` from content scripts
- Added `content.css` as the only injected stylesheet

### `background.js`
- Replaced `toggleMoat` messaging with `chrome.sidePanel.open()`
- Added message relay system: routes messages between content script and side panel (both directions)
- Handles ~10 message types: `ENTER_COMMENT_MODE`, `SETUP_PROJECT`, `DISCONNECT_PROJECT`, `LOAD_TASKS`, etc.

### `content_script.js` (+290 lines)
- Added `relayToSidePanel()` helper for background-mediated communication
- Added handlers for side panel messages: project setup/disconnect, task CRUD, annotation modes, screenshot management
- Added `loadTasksForSidePanel()`, `updateTaskStatusFromSidePanel()`, `deleteTaskFromSidePanel()`
- Added `getThumbnailDataUrl()` — reads screenshots from File System API, converts to data URLs for side panel display
- Added `getScreenshotCount()` and `clearScreenshots()` utilities
- Improved disconnect logic with `chrome.storage.local` flag to persist disconnect across reloads
- Removed `Cmd+Shift+F` toggle sidebar shortcut (no longer needed)
- Relays project connection and task update events to side panel

### Demo Site Updates
- Expanded pricing section from 1 card to 3 cards in a grid
- Replaced emoji icons with inline SVGs
- Fixed typos (Conact → Contact, intergration → integration, etc.)
- Removed typewriter animation and glow effects
- Cleaned up "flashing" class usage from buttons

## Key Architectural Decisions
1. **Content script keeps file system access** — all File System API operations stay in the content script since side panels can't directly access page-scoped handles
2. **Background script as message bus** — all communication between side panel and content script is relayed through background.js
3. **Thumbnail data URLs** — screenshots are read from disk and sent as base64 data URLs to the side panel (since it can't access the file handles directly)
4. **Disconnect persistence** — uses `chrome.storage.local` flags per-origin so disconnects survive page reloads
61 changes: 47 additions & 14 deletions chrome-extension/background.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// chrome-extension/background.js

// Handle extension icon click - toggle Drawbridge sidebar
// Handle extension icon click - open side panel
chrome.action.onClicked.addListener(async (tab) => {
// Check for restricted URL schemes where content scripts cannot run
const restrictedSchemes = [
Expand All @@ -13,30 +13,24 @@ chrome.action.onClicked.addListener(async (tab) => {
];

const isRestricted = restrictedSchemes.some(scheme => tab.url?.startsWith(scheme));

if (isRestricted || !tab.id || !tab.url) {
console.warn('Drawbridge: Cannot open on restricted page:', tab.url);
return;
}

try {
// Send message to content script to toggle the Drawbridge sidebar
// Content scripts are auto-injected via manifest, so this should work
chrome.tabs.sendMessage(tab.id, { action: 'toggleMoat' }, (response) => {
if (chrome.runtime.lastError) {
console.warn('Drawbridge: Content script may not be ready yet:', chrome.runtime.lastError.message);
// This is okay - content script will be injected on next page load
} else {
console.log('Drawbridge: Sidebar toggled successfully');
}
});
// Open the side panel for this tab
await chrome.sidePanel.open({ tabId: tab.id });
console.log('Drawbridge: Side panel opened');
} catch (error) {
console.error('Drawbridge: Failed to toggle sidebar:', error);
console.error('Drawbridge: Failed to open side panel:', error);
}
});

// Handle screenshot capture requests from content scripts
// Handle messages from content scripts and side panel
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// Screenshot capture requests from content scripts
if (message.type === 'CAPTURE_SCREENSHOT') {
chrome.tabs.captureVisibleTab(
sender.tab.windowId,
Expand All @@ -52,4 +46,43 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
);
return true; // Required for async sendResponse
}

// Relay messages from content script to side panel
if (message.type === 'RELAY_TO_SIDEPANEL') {
// Broadcast to all extension pages (including side panel)
chrome.runtime.sendMessage(message.payload).catch(() => {
// Side panel might not be open, that's okay
});
return false;
}

// Messages that need to be relayed to the active tab's content script
const contentScriptMessages = [
'ENTER_COMMENT_MODE',
'ENTER_DRAWING_MODE',
'EXIT_ANNOTATION_MODE',
'SETUP_PROJECT',
'DISCONNECT_PROJECT',
'LOAD_TASKS',
'UPDATE_TASK_STATUS',
'DELETE_TASK',
'GET_CONNECTION_STATUS'
];

if (contentScriptMessages.includes(message.type)) {
// This message came from side panel, relay to active tab
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (tabs[0]?.id) {
chrome.tabs.sendMessage(tabs[0].id, message, (response) => {
if (chrome.runtime.lastError) {
console.warn('Relay to content script failed:', chrome.runtime.lastError.message);
sendResponse({ success: false, error: chrome.runtime.lastError.message });
} else {
sendResponse(response);
}
});
}
});
return true; // Keep channel open for async response
}
});
Loading