feat!: web UI, multi-binary split, worktrees, drag-and-drop, e2e tests#23
Merged
feat!: web UI, multi-binary split, worktrees, drag-and-drop, e2e tests#23
Conversation
- Add cmd/serve.go with HTTP server serving GraphQL API - GraphQL endpoint at POST /graphql - GraphQL Playground at GET /graphql for interactive queries - Supports --port/-p flag (default 8080) - Graceful shutdown on SIGINT/SIGTERM - Plan web UI feature with subtasks for future implementation
- Add internal/web/ package with go:embed for frontend assets - Serve embedded SPA from beans serve at / - Handle SPA routing (unknown paths serve index.html) - Add mise tasks: build:frontend, build:embed - Build pipeline now includes frontend compilation
- Use signal.NotifyContext for cleaner signal handling - Properly deregister signal handlers on exit
- Add gin.Logger() middleware to log HTTP requests
- Add Subscription type with beanChanged field to schema
- Add BeanChangeEvent type and ChangeType enum (CREATED/UPDATED/DELETED)
- Implement subscription resolver using beancore.Subscribe()
- Add WebSocket transport to serve command for subscription support
- Start file watcher automatically when server starts
Usage: Subscribe to bean changes via GraphQL:
```graphql
subscription {
beanChanged {
type
beanId
bean { id title status }
}
}
```
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- BeansStore class with $state for reactive beans map - Load all beans via GraphQL query - Helper methods: byStatus, byType, children, blockedBy - Uses SvelteMap for proper reactivity - Singleton export for app-wide usage 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Display all beans in a card layout - Show id, type, status, title, tags, and date - Color-coded status and type badges - Loading and error states 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Add subscribe() method to BeansStore - Handle CREATED/UPDATED/DELETED events from beanChanged subscription - Show "Live" indicator when connected - Clean up subscription on component destroy - Add wonka dependency for urql streams 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
- Configure gqlgen with explicit transports (WebSocket first for upgrade handling) - Add graphql-transport-ws subprotocol for graphql-ws client compatibility - Frontend connects WebSocket directly to backend in dev (bypasses Vite proxy) - Force-close connections if graceful shutdown times out - Add CORS middleware for development
Add includeInitial argument to beanChanged subscription that emits all current beans on connect as INITIAL events, followed by real-time CREATED/UPDATED/DELETED changes. This eliminates race conditions between loading and subscribing. - Add includeInitial argument (default false) to beanChanged subscription - Add INITIAL to ChangeType enum for initial state events - Update resolver to emit all beans with INITIAL type when includeInitial=true - Simplify frontend to use single subscribe() call instead of load()+subscribe()
Display beans in a tree structure matching CLI output: - Top-level beans shown at root - Children indented with visual tree lines - Color-coded left border by type (milestone, epic, feature, bug, task) - Shows child count on parent beans - Recursive BeanItem component for unlimited nesting depth
- Two-pane layout: bean list on left, detail view on right - Draggable separator with localStorage persistence (200-600px range) - Compact bean list items with short ID, title, status badge - Detail view shows: metadata, tags, relationships, body, timestamps - Click bean to select and view details - Selected bean stays in sync with real-time updates
- Add shiki package for syntax highlighting - Create markdown.ts utility with lazy highlighter initialization - Use github-dark theme for code blocks - Add styling for code blocks and inline code - Preload highlighter in layout for faster first render
- Remove header for cleaner layout - Make separator more subtle with gray tones - Fix HTML comment syntax
- Add onSelect callback prop to BeanDetail component - Render parent, children, blocking, and blocked-by as compact card-style buttons matching the left pane's BeanItem style - Wire up selectBean in +page.svelte so clicking navigates to that bean
- Replace hardcoded port 22880 with BEANS_PORT env var (default: 22880) - Replace hardcoded Vite port with VITE_PORT env var (default: 5173) - Update vite.config.ts proxy target to read from BEANS_PORT - Simplify graphqlClient.ts WebSocket URL to use window.location.host, routing through Vite's WS proxy instead of direct backend connection - Update conductor.json to use $CONDUCTOR_PORT for backend and $CONDUCTOR_PORT+1 for frontend via mise dev
- Add tab navigation to main view (Backlog / Board) - Backlog tab: existing tree list + detail pane layout - Board tab: kanban columns for Draft, Todo, In Progress - Drag-and-drop between columns to change bean status via GraphQL mutation - Visual feedback: drop target highlight, grab cursor, opacity on dragged card Refs: beans-d91u
- Add daisyui v5 as a dependency - Replace custom tab bar with DaisyUI tabs (tabs-border) - Use DaisyUI badge variants for status/type/priority indicators - Use DaisyUI card components on board view - Use DaisyUI alert for error messages, btn for buttons, divider - Replace hardcoded colors with semantic tokens (base-100, base-200, base-content) Refs: beans-d91u
…isted selection - Add BeanForm component (modal) for creating and editing beans - Extract shared UI state into uiState.svelte.ts singleton - Split Backlog and Board into separate SvelteKit routes (/ and /board) - Reflect selected bean in URL as ?bean=<id> query param - Preserve bean selection when switching between views - Add Edit button to BeanDetail header - Add "+ New Bean" button in nav bar - Board cards use cursor-pointer - Remove outdated page test Refs: beans-z4ry
- Add internal/worktree package with Manager (List/Create/Remove + pub/sub) - Extend GraphQL schema with Worktree type, query, mutations, subscription - Implement worktree resolvers (createWorktree sets bean to in-progress) - Add frontend WorktreeStore with real-time WebSocket subscription - Add "Start Work" button to BeanDetail component - Add worktree tabs to layout nav bar - Create worktree route page (/worktree/[id]) with detail pane - Configure adapter-static fallback for SPA routing Refs: beans-dtaq
- Add removeWorktree method to WorktreeStore - Add close (x) button on each worktree tab in nav bar - Navigate back to Backlog when closing the active worktree Refs: beans-dtaq
- Add internal/bean/fractional.go with base-62 fractional index generation - Add Order field to Bean struct, frontmatter parsing, and rendering - Update sort to use Order as primary key within each status group - Add order field to GraphQL schema (Bean type + UpdateBeanInput) - Add frontend fractional.ts (TypeScript port of the algorithm) - Update BoardView with drag-and-drop reordering within and across columns - Auto-assign order keys to unordered beans on first drag in a column - Show drop position indicator line between cards Refs: beans-vsfv
- Add optimisticUpdate method to BeansStore for instant UI feedback - Make ensureOrdered/onDrop synchronous with optimistic store updates - Replace drop indicator divs with box-shadow on cards (zero layout space) - Use var(--color-primary) for DaisyUI v5 compatible drop indicator color Refs: beans-vsfv
- Drain all event batches instead of expecting exactly one - Verify final state from core rather than event snapshot - Prevents flaky failures on slow CI where debounce fires between writes
- Remove daisyui dependency from package.json - Define custom design tokens in layout.css via @theme (surface, border, text, accent, danger, warning, success, info) - Replace all DaisyUI component classes (btn, card, badge, modal, tabs, form-control, input, select, textarea, alert, loading, divider) with plain Tailwind utility classes - Replace DaisyUI color tokens (base-100/200/300, base-content, primary) with semantic custom tokens
Replace box-shadow drop indicators with permanent 2px bars between cards that are transparent by default and colored on drop target. Eliminates layout shifts entirely.
…s-tui) - Move cmd/ to internal/commands/ as shared command package - Convert init() auto-registration to explicit Register*Cmd(root) functions - Create cmd/beans/, cmd/beans-serve/, cmd/beans-tui/ entrypoints - Add internal/version/ package for shared version variables - Update mise.toml build tasks and .goreleaser.yaml for three binaries - Delete root main.go in favor of per-binary entrypoints Refs: beans-unmv
- beans serve/tui now prints a message directing users to beans-serve/beans-tui - beans-serve and beans-tui default to their respective subcommands (no need to type beans-serve serve) Refs: beans-unmv
Refs: beans-unmv
- Add sortBeans() to frontend store matching backend's SortByStatusPriorityAndType - Add data-status attribute to board columns for reliable test selectors - Set up Playwright with page objects (BacklogPage, BoardPage) - Add 9 e2e tests: sorting, real-time re-sort, column placement, deletion - Wire e2e tests into mise test via test:e2e task - Fix build warnings: suppress state_referenced_locally in BeanForm, use role="slider" for worktree drag handle, raise chunk size limit Refs: beans-hww2
- Each test spawns its own beans-serve on a unique port with an isolated temp dir - Pre-build binaries once in run.sh instead of compiling per-test - Pass baseURL through fixtures to page objects - Bump workers to 4
beans serve command with web UI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Major evolution of the beans web UI and project architecture. This PR started as a web server command and grew into a comprehensive set of features.
Multi-Binary Architecture
beans,beans-serve,beans-tuibeans-serve serve)beans serveandbeans tuiprint migration messageswgodependencyWeb UI
Git Worktree Support
GraphQL Enhancements
includeInitialparameter andINITIAL_SYNC_COMPLETEeventBeanChangeEventtype:INITIAL,CREATED,UPDATED,DELETED.beans.ymlE2E Testing
beans-servewith a unique port and temp directoryFrontend Sorting Consistency
sortBeans()mirrors backend'sSortByStatusPriorityAndType(status → order → priority → type → title)Test Plan
mise test— all Go tests passmise test:e2e— all 9 Playwright tests pass (parallelized)beans serve/beans tuiprint deprecation messagesbeans-serveandbeans-tuidefault to their primary commands