beads-kanban-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/.designs/beads-kanban-ui-bj0.md +73 -0
  2. package/.designs/beads-kanban-ui-qxq.md +144 -0
  3. package/.designs/epic-support.md +282 -0
  4. package/.env.local.example +2 -0
  5. package/.eslintrc.json +3 -0
  6. package/.gitattributes +3 -0
  7. package/.github/workflows/release.yml +123 -0
  8. package/.history/README_20260121193710.md +227 -0
  9. package/.history/README_20260121193918.md +227 -0
  10. package/.history/README_20260121193921.md +227 -0
  11. package/.history/README_20260121193933.md +227 -0
  12. package/.history/README_20260121193934.md +227 -0
  13. package/.history/README_20260121193944.md +227 -0
  14. package/.history/README_20260121193953.md +227 -0
  15. package/.history/src/app/page_20260121133429.tsx +134 -0
  16. package/.history/src/app/page_20260121133928.tsx +134 -0
  17. package/.history/src/app/page_20260121144850.tsx +138 -0
  18. package/.history/src/app/page_20260121144854.tsx +138 -0
  19. package/.history/src/app/page_20260121144858.tsx +138 -0
  20. package/.history/src/app/page_20260121144902.tsx +138 -0
  21. package/.history/src/app/page_20260121144906.tsx +138 -0
  22. package/.history/src/app/page_20260121144911.tsx +138 -0
  23. package/.history/src/app/page_20260121144928.tsx +138 -0
  24. package/.playwright-mcp/.playwright-mcp/morphing-dialog-wheel-scroll-fix.png +0 -0
  25. package/.playwright-mcp/beams-test.png +0 -0
  26. package/.playwright-mcp/card-verification.png +0 -0
  27. package/.playwright-mcp/design-doc-dialog-fix-verification.png +0 -0
  28. package/.playwright-mcp/dialog-width-test.png +0 -0
  29. package/.playwright-mcp/homepage.png +0 -0
  30. package/.playwright-mcp/morphing-dialog-expanded.png +0 -0
  31. package/.playwright-mcp/morphing-dialog-fixes-final.png +0 -0
  32. package/.playwright-mcp/morphing-dialog-open.png +0 -0
  33. package/.playwright-mcp/page-2026-01-21T14-08-31-529Z.png +0 -0
  34. package/.playwright-mcp/page-2026-01-21T14-09-23-431Z.png +0 -0
  35. package/.playwright-mcp/page-2026-01-21T14-10-28-773Z.png +0 -0
  36. package/.playwright-mcp/page-2026-01-21T14-10-47-432Z.png +0 -0
  37. package/.playwright-mcp/page-2026-01-21T14-11-12-350Z.png +0 -0
  38. package/.playwright-mcp/screenshot-after-click.png +0 -0
  39. package/.playwright-mcp/screenshot-after-dialog-click.png +0 -0
  40. package/.playwright-mcp/sheet-restored-after-dialog-close.png +0 -0
  41. package/.playwright-mcp/test-1-sheet-open-with-overlay.png +0 -0
  42. package/.playwright-mcp/test-2-morphing-dialog-with-overlay.png +0 -0
  43. package/.playwright-mcp/test-3-sheet-open-dark-overlay.png +0 -0
  44. package/.playwright-mcp/test-4-morphing-dialog-with-dark-overlay.png +0 -0
  45. package/.playwright-mcp/test-5-morphing-dialog-scrolled.png +0 -0
  46. package/.playwright-mcp/test-6-sheet-restored-after-dialog-close.png +0 -0
  47. package/.playwright-mcp/wheel-scroll-fixed.png +0 -0
  48. package/README.md +243 -0
  49. package/Screenshots/bead-detail.png +0 -0
  50. package/Screenshots/dashboard.png +0 -0
  51. package/Screenshots/kanban-board.png +0 -0
  52. package/components.json +27 -0
  53. package/logo/logo.svg +1 -0
  54. package/next.config.js +9 -0
  55. package/npm/README.md +37 -0
  56. package/npm/bin/cli.js +107 -0
  57. package/npm/package.json +20 -0
  58. package/npm/scripts/postinstall.js +132 -0
  59. package/package.json +62 -0
  60. package/postcss.config.js +6 -0
  61. package/public/logo.svg +1 -0
  62. package/restart.sh +5 -0
  63. package/server/Cargo.lock +1685 -0
  64. package/server/Cargo.toml +24 -0
  65. package/server/src/db.rs +570 -0
  66. package/server/src/main.rs +141 -0
  67. package/server/src/routes/beads.rs +413 -0
  68. package/server/src/routes/cli.rs +150 -0
  69. package/server/src/routes/fs.rs +360 -0
  70. package/server/src/routes/git.rs +169 -0
  71. package/server/src/routes/mod.rs +107 -0
  72. package/server/src/routes/projects.rs +177 -0
  73. package/server/src/routes/watch.rs +211 -0
  74. package/src/app/globals.css +101 -0
  75. package/src/app/layout.tsx +36 -0
  76. package/src/app/page.tsx +348 -0
  77. package/src/app/project/kanban-board.tsx +356 -0
  78. package/src/app/project/page.tsx +18 -0
  79. package/src/app/settings/page.tsx +224 -0
  80. package/src/components/Beams.css +5 -0
  81. package/src/components/Beams.jsx +307 -0
  82. package/src/components/Galaxy.css +5 -0
  83. package/src/components/Galaxy.jsx +333 -0
  84. package/src/components/activity-timeline.tsx +172 -0
  85. package/src/components/add-project-dialog.tsx +219 -0
  86. package/src/components/bead-card.tsx +196 -0
  87. package/src/components/bead-detail.tsx +306 -0
  88. package/src/components/color-picker.tsx +101 -0
  89. package/src/components/comment-input.tsx +155 -0
  90. package/src/components/comment-list.tsx +147 -0
  91. package/src/components/dependency-badge.tsx +106 -0
  92. package/src/components/design-doc-dialog.tsx +58 -0
  93. package/src/components/design-doc-preview.tsx +97 -0
  94. package/src/components/design-doc-viewer.tsx +199 -0
  95. package/src/components/editable-project-name.tsx +178 -0
  96. package/src/components/epic-card.tsx +263 -0
  97. package/src/components/folder-browser.tsx +273 -0
  98. package/src/components/footer.tsx +27 -0
  99. package/src/components/kanban/default.tsx +184 -0
  100. package/src/components/kanban-column.tsx +167 -0
  101. package/src/components/project-card.tsx +191 -0
  102. package/src/components/quick-filter-bar.tsx +279 -0
  103. package/src/components/scan-directory-dialog.tsx +368 -0
  104. package/src/components/status-donut.tsx +197 -0
  105. package/src/components/subtask-list.tsx +128 -0
  106. package/src/components/tag-picker.tsx +252 -0
  107. package/src/components/ui/.gitkeep +0 -0
  108. package/src/components/ui/alert-dialog.tsx +141 -0
  109. package/src/components/ui/avatar.tsx +67 -0
  110. package/src/components/ui/badge.tsx +230 -0
  111. package/src/components/ui/button.tsx +433 -0
  112. package/src/components/ui/card/index.tsx +24 -0
  113. package/src/components/ui/card/roiui-card.module.css +197 -0
  114. package/src/components/ui/card/roiui-card.tsx +154 -0
  115. package/src/components/ui/card/shadcn-card.tsx +76 -0
  116. package/src/components/ui/chart.tsx +369 -0
  117. package/src/components/ui/dialog.tsx +122 -0
  118. package/src/components/ui/dropdown-menu.tsx +201 -0
  119. package/src/components/ui/input.tsx +22 -0
  120. package/src/components/ui/kanban.tsx +522 -0
  121. package/src/components/ui/morphing-dialog.tsx +457 -0
  122. package/src/components/ui/popover.tsx +33 -0
  123. package/src/components/ui/progress.tsx +28 -0
  124. package/src/components/ui/scroll-area.tsx +48 -0
  125. package/src/components/ui/select.tsx +159 -0
  126. package/src/components/ui/separator.tsx +31 -0
  127. package/src/components/ui/sheet.tsx +142 -0
  128. package/src/components/ui/skeleton.tsx +15 -0
  129. package/src/components/ui/toast.tsx +129 -0
  130. package/src/components/ui/toaster.tsx +35 -0
  131. package/src/components/ui/tooltip.tsx +30 -0
  132. package/src/hooks/.gitkeep +0 -0
  133. package/src/hooks/use-bead-filters.ts +261 -0
  134. package/src/hooks/use-beads.ts +162 -0
  135. package/src/hooks/use-branch-statuses.ts +161 -0
  136. package/src/hooks/use-epics.ts +173 -0
  137. package/src/hooks/use-file-watcher.ts +111 -0
  138. package/src/hooks/use-keyboard-navigation.ts +282 -0
  139. package/src/hooks/use-project.ts +61 -0
  140. package/src/hooks/use-projects.ts +93 -0
  141. package/src/hooks/use-toast.ts +194 -0
  142. package/src/hooks/useClickOutside.tsx +26 -0
  143. package/src/lib/.gitkeep +0 -0
  144. package/src/lib/api.ts +186 -0
  145. package/src/lib/beads-parser.ts +252 -0
  146. package/src/lib/cli.ts +193 -0
  147. package/src/lib/db.ts +145 -0
  148. package/src/lib/design-doc.ts +74 -0
  149. package/src/lib/epic-parser.ts +242 -0
  150. package/src/lib/git.ts +102 -0
  151. package/src/lib/utils.ts +12 -0
  152. package/src/types/index.ts +107 -0
  153. package/tailwind.config.ts +85 -0
  154. package/tsconfig.json +26 -0
@@ -0,0 +1,138 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import Link from "next/link";
5
+ import dynamic from "next/dynamic";
6
+ import { Settings } from "lucide-react";
7
+ import { ProjectCard } from "@/components/project-card";
8
+ import { AddProjectDialog } from "@/components/add-project-dialog";
9
+ import { useProjects } from "@/hooks/use-projects";
10
+ import { Skeleton } from "@/components/ui/skeleton";
11
+
12
+ // Dynamic import with SSR disabled for WebGL canvas component
13
+ const RippleGrid = dynamic(() => import("@/components/RippleGrid"), { ssr: false });
14
+
15
+ export default function ProjectsPage() {
16
+ const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
17
+ const { projects, isLoading, error, addProject, updateProjectTags } = useProjects();
18
+
19
+ const handleAddProject = async (input: { name: string; path: string }) => {
20
+ await addProject(input);
21
+ };
22
+
23
+ return (
24
+ <div className="dark relative min-h-screen bg-[#0d0b14]">
25
+ {/* RippleGrid Background - fixed, full-screen, z-0 */}
26
+ <div className="fixed inset-0 z-0 overflow-hidden">
27
+ <RippleGrid
28
+ gridColor="#302a4c"
29
+ rippleIntensity={0.02}
30
+ gridSize={15}
31
+ gridThickness={15}
32
+ fadeDistance={1.8}
33
+ vignetteStrength={0.5}
34
+ glowIntensity={0.4}
35
+ opacity={1}
36
+ gridRotation={0}
37
+ mouseInteractionRadius={0.8}
38
+ mouseInteraction={false}
39
+ enableRainbow={false}
40
+ />
41
+ </div>
42
+
43
+ {/* Settings Icon - fixed top-right, z-20 */}
44
+ <Link
45
+ href="/settings"
46
+ aria-label="Settings"
47
+ className="fixed right-6 top-6 z-20 rounded-md p-2 text-zinc-400 hover:bg-zinc-800/50 hover:text-zinc-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
48
+ >
49
+ <Settings className="h-5 w-5" aria-hidden="true" />
50
+ </Link>
51
+
52
+ {/* Main Content */}
53
+ <main className="relative z-10 flex flex-col items-center px-6 py-16">
54
+ {/* Centered Heading with Space Grotesk */}
55
+ <h1 className="mb-12 text-center text-balance font-heading text-4xl font-bold tracking-tight text-white sm:text-5xl">
56
+ Manage Your Beads Projects
57
+ </h1>
58
+
59
+ <div className="w-full max-w-[1200px]">
60
+ {isLoading ? (
61
+ <div role="status" aria-label="Loading projects" className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
62
+ {[1, 2, 3].map((i) => (
63
+ <div key={i} className="rounded-xl border bg-card/70 p-4 backdrop-blur-md">
64
+ <div className="mb-3 flex gap-1.5">
65
+ <Skeleton className="h-5 w-16" />
66
+ <Skeleton className="h-5 w-12" />
67
+ </div>
68
+ <Skeleton className="h-5 w-40" />
69
+ <Skeleton className="mt-2 h-4 w-48" />
70
+ <Skeleton className="mt-4 h-4 w-32" />
71
+ <Skeleton className="mt-2 h-3 w-28" />
72
+ </div>
73
+ ))}
74
+ </div>
75
+ ) : error ? (
76
+ <div className="rounded-lg border border-red-800/50 bg-red-950/70 p-6 text-center backdrop-blur-md">
77
+ <p className="text-red-400">Error loading projects: {error.message}</p>
78
+ <p className="mt-2 text-sm text-red-500">
79
+ Make sure the Tauri backend is running.
80
+ </p>
81
+ </div>
82
+ ) : projects.length === 0 ? (
83
+ <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
84
+ <div className="rounded-lg border border-dashed border-zinc-700 bg-card/70 p-6 text-center text-zinc-400 backdrop-blur-md">
85
+ <p>No projects yet</p>
86
+ <p className="mt-1 text-sm text-zinc-500">Click the button below to add a project</p>
87
+ </div>
88
+ </div>
89
+ ) : (
90
+ <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
91
+ {projects.map((project) => (
92
+ <ProjectCard
93
+ key={project.id}
94
+ id={project.id}
95
+ name={project.name}
96
+ path={project.path}
97
+ tags={project.tags}
98
+ beadCounts={project.beadCounts}
99
+ onTagsChange={(tags) => updateProjectTags(project.id, tags)}
100
+ />
101
+ ))}
102
+ </div>
103
+ )}
104
+ </div>
105
+ </main>
106
+
107
+ {/* FAB - Add Project, z-20 */}
108
+ <button
109
+ onClick={() => setIsAddDialogOpen(true)}
110
+ className="fixed bottom-6 right-6 z-20 flex h-14 w-14 items-center justify-center rounded-full bg-zinc-100 text-zinc-900 shadow-lg hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-100 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
111
+ aria-label="Add Project"
112
+ >
113
+ <svg
114
+ xmlns="http://www.w3.org/2000/svg"
115
+ width="24"
116
+ height="24"
117
+ viewBox="0 0 24 24"
118
+ fill="none"
119
+ stroke="currentColor"
120
+ strokeWidth="2"
121
+ strokeLinecap="round"
122
+ strokeLinejoin="round"
123
+ aria-hidden="true"
124
+ >
125
+ <path d="M5 12h14" />
126
+ <path d="M12 5v14" />
127
+ </svg>
128
+ </button>
129
+
130
+ {/* Add Project Dialog */}
131
+ <AddProjectDialog
132
+ open={isAddDialogOpen}
133
+ onOpenChange={setIsAddDialogOpen}
134
+ onAddProject={handleAddProject}
135
+ />
136
+ </div>
137
+ );
138
+ }
@@ -0,0 +1,138 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import Link from "next/link";
5
+ import dynamic from "next/dynamic";
6
+ import { Settings } from "lucide-react";
7
+ import { ProjectCard } from "@/components/project-card";
8
+ import { AddProjectDialog } from "@/components/add-project-dialog";
9
+ import { useProjects } from "@/hooks/use-projects";
10
+ import { Skeleton } from "@/components/ui/skeleton";
11
+
12
+ // Dynamic import with SSR disabled for WebGL canvas component
13
+ const RippleGrid = dynamic(() => import("@/components/RippleGrid"), { ssr: false });
14
+
15
+ export default function ProjectsPage() {
16
+ const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
17
+ const { projects, isLoading, error, addProject, updateProjectTags } = useProjects();
18
+
19
+ const handleAddProject = async (input: { name: string; path: string }) => {
20
+ await addProject(input);
21
+ };
22
+
23
+ return (
24
+ <div className="dark relative min-h-screen bg-[#0d0b14]">
25
+ {/* RippleGrid Background - fixed, full-screen, z-0 */}
26
+ <div className="fixed inset-0 z-0 overflow-hidden">
27
+ <RippleGrid
28
+ gridColor="#302a4c"
29
+ rippleIntensity={0.02}
30
+ gridSize={15}
31
+ gridThickness={15}
32
+ fadeDistance={1.8}
33
+ vignetteStrength={0.5}
34
+ glowIntensity={0.4}
35
+ opacity={1}
36
+ gridRotation={45}
37
+ mouseInteractionRadius={0.8}
38
+ mouseInteraction={false}
39
+ enableRainbow={false}
40
+ />
41
+ </div>
42
+
43
+ {/* Settings Icon - fixed top-right, z-20 */}
44
+ <Link
45
+ href="/settings"
46
+ aria-label="Settings"
47
+ className="fixed right-6 top-6 z-20 rounded-md p-2 text-zinc-400 hover:bg-zinc-800/50 hover:text-zinc-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-400 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
48
+ >
49
+ <Settings className="h-5 w-5" aria-hidden="true" />
50
+ </Link>
51
+
52
+ {/* Main Content */}
53
+ <main className="relative z-10 flex flex-col items-center px-6 py-16">
54
+ {/* Centered Heading with Space Grotesk */}
55
+ <h1 className="mb-12 text-center text-balance font-heading text-4xl font-bold tracking-tight text-white sm:text-5xl">
56
+ Manage Your Beads Projects
57
+ </h1>
58
+
59
+ <div className="w-full max-w-[1200px]">
60
+ {isLoading ? (
61
+ <div role="status" aria-label="Loading projects" className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
62
+ {[1, 2, 3].map((i) => (
63
+ <div key={i} className="rounded-xl border bg-card/70 p-4 backdrop-blur-md">
64
+ <div className="mb-3 flex gap-1.5">
65
+ <Skeleton className="h-5 w-16" />
66
+ <Skeleton className="h-5 w-12" />
67
+ </div>
68
+ <Skeleton className="h-5 w-40" />
69
+ <Skeleton className="mt-2 h-4 w-48" />
70
+ <Skeleton className="mt-4 h-4 w-32" />
71
+ <Skeleton className="mt-2 h-3 w-28" />
72
+ </div>
73
+ ))}
74
+ </div>
75
+ ) : error ? (
76
+ <div className="rounded-lg border border-red-800/50 bg-red-950/70 p-6 text-center backdrop-blur-md">
77
+ <p className="text-red-400">Error loading projects: {error.message}</p>
78
+ <p className="mt-2 text-sm text-red-500">
79
+ Make sure the Tauri backend is running.
80
+ </p>
81
+ </div>
82
+ ) : projects.length === 0 ? (
83
+ <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
84
+ <div className="rounded-lg border border-dashed border-zinc-700 bg-card/70 p-6 text-center text-zinc-400 backdrop-blur-md">
85
+ <p>No projects yet</p>
86
+ <p className="mt-1 text-sm text-zinc-500">Click the button below to add a project</p>
87
+ </div>
88
+ </div>
89
+ ) : (
90
+ <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
91
+ {projects.map((project) => (
92
+ <ProjectCard
93
+ key={project.id}
94
+ id={project.id}
95
+ name={project.name}
96
+ path={project.path}
97
+ tags={project.tags}
98
+ beadCounts={project.beadCounts}
99
+ onTagsChange={(tags) => updateProjectTags(project.id, tags)}
100
+ />
101
+ ))}
102
+ </div>
103
+ )}
104
+ </div>
105
+ </main>
106
+
107
+ {/* FAB - Add Project, z-20 */}
108
+ <button
109
+ onClick={() => setIsAddDialogOpen(true)}
110
+ className="fixed bottom-6 right-6 z-20 flex h-14 w-14 items-center justify-center rounded-full bg-zinc-100 text-zinc-900 shadow-lg hover:bg-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-zinc-100 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent"
111
+ aria-label="Add Project"
112
+ >
113
+ <svg
114
+ xmlns="http://www.w3.org/2000/svg"
115
+ width="24"
116
+ height="24"
117
+ viewBox="0 0 24 24"
118
+ fill="none"
119
+ stroke="currentColor"
120
+ strokeWidth="2"
121
+ strokeLinecap="round"
122
+ strokeLinejoin="round"
123
+ aria-hidden="true"
124
+ >
125
+ <path d="M5 12h14" />
126
+ <path d="M12 5v14" />
127
+ </svg>
128
+ </button>
129
+
130
+ {/* Add Project Dialog */}
131
+ <AddProjectDialog
132
+ open={isAddDialogOpen}
133
+ onOpenChange={setIsAddDialogOpen}
134
+ onAddProject={handleAddProject}
135
+ />
136
+ </div>
137
+ );
138
+ }
Binary file
Binary file
package/README.md ADDED
@@ -0,0 +1,243 @@
1
+ # Beads Kanban UI
2
+
3
+ **See all your tasks at a glance. Organize, and track progress across projects - no CLI required.**
4
+
5
+ A beautiful visual Kanban board for the [Beads CLI](https://github.com/steveyegge/beads) task tracker. Beads stores tasks as git-native files (`.beads/issues.jsonl`), and this UI gives you the dashboard and board you've been missing.
6
+
7
+ > **Works great with [Beads Orchestration](https://github.com/AvivK5498/Claude-Code-Beads-Orchestration)** — A multi-agent orchestration framework for Claude Code that uses beads for git-native task tracking.
8
+
9
+ ## See It in Action
10
+
11
+ **Dashboard** — All your projects in one place with status at a glance:
12
+ ![Dashboard with multi-project view, status donuts, and tags](Screenshots/dashboard.png)
13
+
14
+ **Kanban Board** — Organize tasks across Open → In Progress → In Review → Closed:
15
+ ![Kanban board showing epic groups and task cards with git branch info](Screenshots/kanban-board.png)
16
+
17
+ **Bead Details** — Dive into epics with full context and subtasks:
18
+ ![Bead detail panel showing epic with progress bar and subtasks](Screenshots/bead-detail.png)
19
+
20
+ ## What You Get
21
+
22
+ - **Multi-project dashboard** — Manage all your beads projects in one place with status donut charts
23
+ - **Kanban board** — Open → In Progress → In Review → Closed
24
+ - **Epic support** — Group related tasks, track progress with bars, view all subtasks
25
+ - **Real-time sync** — File watcher auto-updates when beads files change on disk
26
+ - **Git integration** — See branch status for each task at a glance
27
+ - **Search & filter** — Quick filters for status, priority, owner, and tags
28
+ - **Project tagging** — Organize with colored tags and filter by them
29
+
30
+ ## Quick Start
31
+
32
+ ### Option 1: npm install (Recommended)
33
+
34
+ **Prerequisites:**
35
+ - Beads CLI: `brew install steveyegge/beads/bd`
36
+
37
+ **Install and run:**
38
+ ```bash
39
+ npm install -g beads-ui
40
+ bead-kanban
41
+ ```
42
+
43
+ That's it! The server starts automatically and opens your browser.
44
+
45
+ > On first run, the postinstall script downloads the platform binary (~15MB). This is one-time only.
46
+
47
+ ### Option 2: Build from source
48
+
49
+ **Prerequisites:**
50
+ ```bash
51
+ # Install beads CLI
52
+ brew install steveyegge/beads/bd
53
+
54
+ # You'll also need Node.js 18+ and Rust
55
+ ```
56
+
57
+ **Install and run:**
58
+ ```bash
59
+ git clone https://github.com/AvivK5498/beads-kanban-ui
60
+ cd beads-kanban-ui
61
+ npm install
62
+ npm run dev:full
63
+ ```
64
+
65
+ Then navigate to **`http://localhost:3007`** and add your beads projects.
66
+
67
+ The app watches for file changes and syncs in real-time.
68
+
69
+ ---
70
+
71
+ ## Detailed Setup
72
+
73
+ ### Development Mode
74
+
75
+ Run both frontend and backend together:
76
+ ```bash
77
+ npm run dev:full
78
+ ```
79
+
80
+ Or run separately:
81
+ ```bash
82
+ # Terminal 1: Frontend (http://localhost:3007)
83
+ npm run dev
84
+
85
+ # Terminal 2: Backend (http://localhost:3008)
86
+ npm run server:dev
87
+ ```
88
+
89
+ The Rust backend builds automatically on first run. If you need to rebuild it:
90
+ ```bash
91
+ cd server && cargo build --release && cd ..
92
+ ```
93
+
94
+ ### Production Build
95
+
96
+ For a single binary deployment:
97
+ ```bash
98
+ npm run build
99
+ npm run server:build
100
+ ./server/target/release/beads-server
101
+ ```
102
+
103
+ The production server embeds the frontend and serves everything from a single binary on port 3008.
104
+
105
+ ---
106
+
107
+ ## How It Works
108
+
109
+ ### Dashboard
110
+ 1. Click **+ Add Project** and select a directory with a `.beads/` folder
111
+ 2. See all projects with status donuts showing task distribution
112
+ 3. Click any project to view its Kanban board
113
+
114
+ ### Kanban Board
115
+ 1. Tasks are organized by status: Open, In Progress, In Review, Closed
116
+ 2. Drag cards between columns to update status
117
+ 3. Click any task to see full details, comments, and related subtasks (for epics)
118
+
119
+ ### Features in Detail
120
+
121
+ **Search & Filter**
122
+ - Quick filters for status, priority, and assigned owner
123
+ - Project tags for organization
124
+
125
+ **Real-time Sync**
126
+ - The app watches `.beads/issues.jsonl` and updates automatically
127
+ - No refresh needed—changes appear instantly
128
+
129
+ **Git Integration**
130
+ - Each task shows its git branch status
131
+ - Useful for tracking which branch a task lives on
132
+
133
+ ---
134
+
135
+ ## Architecture
136
+
137
+ ```
138
+ ┌─────────────────────────────────────────────────────────┐
139
+ │ Beads Kanban UI │
140
+ ├─────────────────────────────────────────────────────────┤
141
+ │ Frontend (Next.js 14) │ Backend (Rust/Axum) │
142
+ │ ───────────────────── │ ────────────────────│
143
+ │ • React 18 │ • SQLite (projects) │
144
+ │ • shadcn/ui components │ • beads CLI bridge │
145
+ │ • Tailwind CSS │ • File watcher │
146
+ │ • TypeScript │ • Git integration │
147
+ └─────────────────────────────────────────────────────────┘
148
+
149
+
150
+ ┌─────────────────────────┐
151
+ │ .beads/ directory │
152
+ │ (issues.jsonl, etc.) │
153
+ └─────────────────────────┘
154
+ ```
155
+
156
+ ### Tech Stack
157
+ - **Frontend**: Next.js 14, React 18, Tailwind CSS, shadcn/ui
158
+ - **Backend**: Rust with Axum framework
159
+ - **Database**: SQLite for project metadata
160
+ - **File Sync**: Real-time watcher for `.beads/` changes
161
+
162
+ ### Project Structure
163
+ ```
164
+ beads-kanban-ui/
165
+ ├── src/
166
+ │ ├── app/ # Next.js pages and routes
167
+ │ │ ├── page.tsx # Projects dashboard
168
+ │ │ ├── project/ # Kanban board view
169
+ │ │ └── settings/ # Settings page
170
+ │ ├── components/ # React components
171
+ │ │ ├── ui/ # shadcn/ui components
172
+ │ │ ├── kanban-column.tsx
173
+ │ │ ├── bead-card.tsx
174
+ │ │ └── bead-detail.tsx
175
+ │ ├── hooks/ # Custom React hooks
176
+ │ ├── lib/ # Utilities and API client
177
+ │ └── types/ # TypeScript type definitions
178
+ ├── server/
179
+ │ └── src/
180
+ │ ├── main.rs # Axum server entry point
181
+ │ ├── db.rs # SQLite database layer
182
+ │ └── routes/ # API route handlers
183
+ └── package.json
184
+ ```
185
+
186
+ ---
187
+
188
+ ## API Endpoints
189
+
190
+ | Endpoint | Method | Description |
191
+ |----------|--------|-------------|
192
+ | `/api/health` | GET | Server health check |
193
+ | `/api/projects` | GET/POST | List or create projects |
194
+ | `/api/projects/:id` | GET/PUT/DELETE | Manage individual projects |
195
+ | `/api/beads?path=` | GET | Read beads from a project path |
196
+ | `/api/beads/comment` | POST | Add comment to a bead |
197
+ | `/api/bd/command` | POST | Execute beads CLI commands |
198
+ | `/api/git/branch-status` | GET | Get git branch status for a bead |
199
+ | `/api/fs/list` | GET | List directory contents |
200
+ | `/api/fs/exists` | GET | Check if a path exists |
201
+ | `/api/watch/beads` | GET | Server-sent events for file changes |
202
+
203
+ ### Environment Variables
204
+
205
+ | Variable | Default | Description |
206
+ |----------|---------|-------------|
207
+ | `PORT` | `3008` | Backend server port |
208
+ | `NEXT_PUBLIC_BACKEND_URL` | `http://localhost:3008` | Backend URL for frontend API calls |
209
+
210
+ ---
211
+
212
+ ## Development Commands
213
+
214
+ ```bash
215
+ # Run both frontend and backend
216
+ npm run dev:full
217
+
218
+ # Run frontend only
219
+ npm run dev
220
+
221
+ # Run backend only
222
+ npm run server:dev
223
+
224
+ # Build for production
225
+ npm run build
226
+ npm run server:build
227
+
228
+ # Linting
229
+ npm run lint
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Related Projects
235
+
236
+ - **[Beads CLI](https://github.com/steveyegge/beads)** — Git-native issue tracker (the core tool this UI wraps)
237
+ - **[Beads Orchestration](https://github.com/AvivK5498/Claude-Code-Beads-Orchestration)** — Multi-agent orchestration framework for Claude Code using beads
238
+
239
+ ---
240
+
241
+ ## License
242
+
243
+ MIT
Binary file
Binary file
Binary file
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": true,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "tailwind.config.ts",
8
+ "css": "src/app/globals.css",
9
+ "baseColor": "neutral",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "iconLibrary": "lucide",
14
+ "aliases": {
15
+ "components": "@/components",
16
+ "utils": "@/lib/utils",
17
+ "ui": "@/components/ui",
18
+ "lib": "@/lib",
19
+ "hooks": "@/hooks"
20
+ },
21
+ "registries": {
22
+ "@motion-primitives": "https://motion-primitives.com/c/{name}.json",
23
+ "@reui": "https://reui.io/r/{name}.json",
24
+ "@roiui": "https://roiui.com/r/{name}.json",
25
+ "@react-bits": "https://reactbits.dev/r/{name}.json"
26
+ }
27
+ }