jettypod 4.4.118 → 4.4.121

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 (240) hide show
  1. package/.env +4 -3
  2. package/Cargo.lock +6450 -0
  3. package/Cargo.toml +35 -0
  4. package/README.md +5 -1
  5. package/TAURI-MIGRATION-PLAN.md +840 -0
  6. package/apps/dashboard/app/connect-claude/page.tsx +5 -6
  7. package/apps/dashboard/app/decision/[id]/page.tsx +63 -58
  8. package/apps/dashboard/app/demo/gates/page.tsx +43 -45
  9. package/apps/dashboard/app/design-system/page.tsx +868 -0
  10. package/apps/dashboard/app/globals.css +80 -4
  11. package/apps/dashboard/app/install-claude/page.tsx +4 -6
  12. package/apps/dashboard/app/login/page.tsx +72 -54
  13. package/apps/dashboard/app/page.tsx +101 -48
  14. package/apps/dashboard/app/settings/page.tsx +61 -13
  15. package/apps/dashboard/app/signup/page.tsx +242 -0
  16. package/apps/dashboard/app/subscribe/page.tsx +0 -2
  17. package/apps/dashboard/app/tests/page.tsx +37 -4
  18. package/apps/dashboard/app/welcome/page.tsx +13 -16
  19. package/apps/dashboard/app/work/[id]/page.tsx +117 -118
  20. package/apps/dashboard/app/work/[id]/proof/page.tsx +1489 -0
  21. package/apps/dashboard/components/AppShell.tsx +92 -85
  22. package/apps/dashboard/components/CardMenu.tsx +45 -12
  23. package/apps/dashboard/components/ClaudePanel.tsx +771 -850
  24. package/apps/dashboard/components/ClaudePanelInput.tsx +43 -15
  25. package/apps/dashboard/components/ConnectClaudeScreen.tsx +17 -34
  26. package/apps/dashboard/components/CopyableId.tsx +3 -4
  27. package/apps/dashboard/components/DetailReviewActions.tsx +100 -0
  28. package/apps/dashboard/components/DragContext.tsx +134 -63
  29. package/apps/dashboard/components/DraggableCard.tsx +3 -5
  30. package/apps/dashboard/components/DropZone.tsx +6 -7
  31. package/apps/dashboard/components/EditableDetailDescription.tsx +7 -13
  32. package/apps/dashboard/components/EditableDetailTitle.tsx +6 -13
  33. package/apps/dashboard/components/EditableTitle.tsx +26 -7
  34. package/apps/dashboard/components/ElapsedTimer.tsx +66 -0
  35. package/apps/dashboard/components/EpicGroup.tsx +359 -0
  36. package/apps/dashboard/components/GateCard.tsx +79 -17
  37. package/apps/dashboard/components/GateChoiceCard.tsx +15 -18
  38. package/apps/dashboard/components/InstallClaudeScreen.tsx +15 -32
  39. package/apps/dashboard/components/JettyLoader.tsx +37 -0
  40. package/apps/dashboard/components/KanbanBoard.tsx +368 -958
  41. package/apps/dashboard/components/KanbanCard.tsx +740 -0
  42. package/apps/dashboard/components/LazyCard.tsx +62 -0
  43. package/apps/dashboard/components/LazyMarkdown.tsx +11 -0
  44. package/apps/dashboard/components/MainNav.tsx +38 -73
  45. package/apps/dashboard/components/MessageBlock.tsx +468 -0
  46. package/apps/dashboard/components/ModeStartCard.tsx +15 -16
  47. package/apps/dashboard/components/OnboardingWelcome.tsx +213 -0
  48. package/apps/dashboard/components/PlaceholderCard.tsx +3 -4
  49. package/apps/dashboard/components/ProjectSwitcher.tsx +30 -30
  50. package/apps/dashboard/components/PrototypeTimeline.tsx +72 -51
  51. package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +406 -388
  52. package/apps/dashboard/components/RealTimeTestsWrapper.tsx +373 -235
  53. package/apps/dashboard/components/ReviewFooter.tsx +139 -0
  54. package/apps/dashboard/components/SessionList.tsx +19 -19
  55. package/apps/dashboard/components/SubscribeContent.tsx +91 -47
  56. package/apps/dashboard/components/TestTree.tsx +16 -16
  57. package/apps/dashboard/components/TipCard.tsx +16 -17
  58. package/apps/dashboard/components/Toast.tsx +5 -6
  59. package/apps/dashboard/components/TypeIcon.tsx +55 -0
  60. package/apps/dashboard/components/ViewModeToolbar.tsx +104 -0
  61. package/apps/dashboard/components/WaveCompletionAnimation.tsx +52 -65
  62. package/apps/dashboard/components/WelcomeScreen.tsx +19 -35
  63. package/apps/dashboard/components/WorkItemHeader.tsx +4 -5
  64. package/apps/dashboard/components/WorkItemTree.tsx +11 -32
  65. package/apps/dashboard/components/settings/AccountSection.tsx +55 -35
  66. package/apps/dashboard/components/settings/AiContextSection.tsx +89 -0
  67. package/apps/dashboard/components/settings/ContextDocumentsSection.tsx +317 -0
  68. package/apps/dashboard/components/settings/EnvVarsSection.tsx +74 -152
  69. package/apps/dashboard/components/settings/GeneralSection.tsx +162 -56
  70. package/apps/dashboard/components/settings/ProjectStackSection.tsx +948 -0
  71. package/apps/dashboard/components/settings/SettingsLayout.tsx +4 -5
  72. package/apps/dashboard/components/ui/Button.tsx +104 -0
  73. package/apps/dashboard/components/ui/Input.tsx +78 -0
  74. package/apps/dashboard/components.json +1 -1
  75. package/apps/dashboard/contexts/ClaudeSessionContext.tsx +711 -418
  76. package/apps/dashboard/contexts/ConnectionStatusContext.tsx +25 -5
  77. package/apps/dashboard/contexts/UsageContext.tsx +87 -32
  78. package/apps/dashboard/dev.sh +35 -0
  79. package/apps/dashboard/eslint.config.mjs +9 -9
  80. package/apps/dashboard/hooks/useKanbanAnimation.ts +29 -0
  81. package/apps/dashboard/hooks/useKanbanUndo.ts +83 -0
  82. package/apps/dashboard/hooks/useWebSocket.ts +138 -83
  83. package/apps/dashboard/index.html +73 -0
  84. package/apps/dashboard/lib/constants.ts +43 -0
  85. package/apps/dashboard/lib/data-bridge.ts +722 -0
  86. package/apps/dashboard/lib/db.ts +69 -1265
  87. package/apps/dashboard/lib/environment-config.ts +173 -0
  88. package/apps/dashboard/lib/environment-verification.ts +119 -0
  89. package/apps/dashboard/lib/kanban-utils.ts +270 -0
  90. package/apps/dashboard/lib/proof-run.ts +495 -0
  91. package/apps/dashboard/lib/proof-scenario-runner.ts +346 -0
  92. package/apps/dashboard/lib/run-migrations.js +27 -2
  93. package/apps/dashboard/lib/service-recovery.ts +326 -0
  94. package/apps/dashboard/lib/session-state-machine.ts +1 -0
  95. package/apps/dashboard/lib/session-state-utils.ts +0 -164
  96. package/apps/dashboard/lib/session-stream-manager.ts +308 -134
  97. package/apps/dashboard/lib/shadows.ts +7 -0
  98. package/apps/dashboard/lib/stream-manager-registry.ts +46 -6
  99. package/apps/dashboard/lib/tauri-bridge.ts +102 -0
  100. package/apps/dashboard/lib/tauri.ts +106 -0
  101. package/apps/dashboard/lib/utils.ts +6 -0
  102. package/apps/dashboard/next-env.d.ts +1 -1
  103. package/apps/dashboard/package.json +21 -32
  104. package/apps/dashboard/public/bug-icon.png +0 -0
  105. package/apps/dashboard/public/buoy-icon.png +0 -0
  106. package/apps/dashboard/public/fonts/Satoshi-Variable.woff2 +0 -0
  107. package/apps/dashboard/public/fonts/Satoshi-VariableItalic.woff2 +0 -0
  108. package/apps/dashboard/public/in-flight-seagull.png +0 -0
  109. package/apps/dashboard/public/jetty-icon-loading-alt.svg +11 -0
  110. package/apps/dashboard/public/jetty-icon-loading.svg +11 -0
  111. package/apps/dashboard/public/jettypod_logo.png +0 -0
  112. package/apps/dashboard/public/pier-icon.png +0 -0
  113. package/apps/dashboard/public/star-icon.png +0 -0
  114. package/apps/dashboard/public/wrench-icon.png +0 -0
  115. package/apps/dashboard/scripts/tauri-build.js +228 -0
  116. package/apps/dashboard/scripts/upload-tauri-to-r2.js +125 -0
  117. package/apps/dashboard/scripts/ws-server.js +191 -0
  118. package/apps/dashboard/src/main.tsx +12 -0
  119. package/apps/dashboard/src/router.tsx +107 -0
  120. package/apps/dashboard/src/vite-env.d.ts +1 -0
  121. package/apps/dashboard/tsconfig.json +7 -12
  122. package/apps/dashboard/tsconfig.tsbuildinfo +1 -1
  123. package/apps/dashboard/vite.config.ts +33 -0
  124. package/apps/update-server/src/index.ts +228 -80
  125. package/claude-hooks/global-guardrails.js +14 -13
  126. package/crates/jettypod-cli/Cargo.toml +19 -0
  127. package/crates/jettypod-cli/src/commands.rs +1249 -0
  128. package/crates/jettypod-cli/src/main.rs +595 -0
  129. package/crates/jettypod-core/Cargo.toml +26 -0
  130. package/crates/jettypod-core/build.rs +98 -0
  131. package/crates/jettypod-core/migrations/V1__baseline.sql +197 -0
  132. package/crates/jettypod-core/migrations/V2__work_items_indexes.sql +6 -0
  133. package/crates/jettypod-core/migrations/V3__qa_steps.sql +2 -0
  134. package/crates/jettypod-core/src/auth.rs +294 -0
  135. package/crates/jettypod-core/src/config.rs +397 -0
  136. package/crates/jettypod-core/src/db/mod.rs +507 -0
  137. package/crates/jettypod-core/src/db/recovery.rs +114 -0
  138. package/crates/jettypod-core/src/db/startup.rs +101 -0
  139. package/crates/jettypod-core/src/db/validate.rs +149 -0
  140. package/crates/jettypod-core/src/error.rs +76 -0
  141. package/crates/jettypod-core/src/git.rs +458 -0
  142. package/crates/jettypod-core/src/lib.rs +20 -0
  143. package/crates/jettypod-core/src/sessions.rs +625 -0
  144. package/crates/jettypod-core/src/skills.rs +556 -0
  145. package/crates/jettypod-core/src/work.rs +1086 -0
  146. package/crates/jettypod-core/src/worktree.rs +628 -0
  147. package/crates/jettypod-core/src/ws.rs +767 -0
  148. package/cucumber-test.cjs +6 -0
  149. package/cucumber.js +9 -3
  150. package/docs/COMMAND_REFERENCE.md +34 -0
  151. package/hooks/post-checkout +32 -75
  152. package/hooks/post-merge +111 -10
  153. package/jest.setup.js +1 -0
  154. package/jettypod.js +145 -116
  155. package/lib/bdd-preflight.js +96 -0
  156. package/lib/chore-taxonomy.js +33 -10
  157. package/lib/database.js +36 -16
  158. package/lib/db-watcher.js +1 -1
  159. package/lib/git-hooks/pre-commit +1 -1
  160. package/lib/jettypod-backup.js +27 -4
  161. package/lib/merge-lock.js +111 -253
  162. package/lib/migrations/027-plan-at-creation-column.js +3 -1
  163. package/lib/migrations/029-remove-autoincrement.js +307 -0
  164. package/lib/migrations/029-rename-corrupted-to-cleaned.js +149 -0
  165. package/lib/migrations/030-rejection-round-columns.js +54 -0
  166. package/lib/migrations/031-session-isolation-index.js +17 -0
  167. package/lib/migrations/index.js +47 -4
  168. package/lib/schema.js +10 -5
  169. package/lib/seed-onboarding.js +1 -1
  170. package/lib/update-command/index.js +9 -175
  171. package/lib/work-commands/index.js +144 -19
  172. package/lib/work-tracking/index.js +148 -27
  173. package/lib/worktree-diagnostics.js +16 -16
  174. package/lib/worktree-facade.js +1 -1
  175. package/lib/worktree-manager.js +8 -8
  176. package/lib/worktree-reconciler.js +5 -5
  177. package/package.json +9 -2
  178. package/scripts/ndjson-to-cucumber-json.js +152 -0
  179. package/scripts/postinstall.js +25 -0
  180. package/skills-templates/bug-mode/SKILL.md +79 -20
  181. package/skills-templates/bug-planning/SKILL.md +25 -29
  182. package/skills-templates/chore-mode/SKILL.md +171 -69
  183. package/skills-templates/chore-mode/verification.js +51 -10
  184. package/skills-templates/chore-planning/SKILL.md +47 -18
  185. package/skills-templates/design-system-selection/SKILL.md +273 -0
  186. package/skills-templates/epic-planning/SKILL.md +82 -48
  187. package/skills-templates/external-transition/SKILL.md +47 -47
  188. package/skills-templates/feature-planning/SKILL.md +173 -74
  189. package/skills-templates/production-mode/SKILL.md +69 -49
  190. package/skills-templates/request-routing/SKILL.md +4 -4
  191. package/skills-templates/simple-improvement/SKILL.md +74 -29
  192. package/skills-templates/speed-mode/SKILL.md +217 -141
  193. package/skills-templates/stable-mode/SKILL.md +148 -89
  194. package/apps/dashboard/README.md +0 -36
  195. package/apps/dashboard/app/api/claude/[workItemId]/message/route.ts +0 -386
  196. package/apps/dashboard/app/api/claude/[workItemId]/pin/route.ts +0 -24
  197. package/apps/dashboard/app/api/claude/[workItemId]/route.ts +0 -167
  198. package/apps/dashboard/app/api/claude/sessions/[sessionId]/content/route.ts +0 -52
  199. package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +0 -378
  200. package/apps/dashboard/app/api/claude/sessions/[sessionId]/pin/route.ts +0 -24
  201. package/apps/dashboard/app/api/claude/sessions/cleanup/route.ts +0 -34
  202. package/apps/dashboard/app/api/claude/sessions/route.ts +0 -184
  203. package/apps/dashboard/app/api/decisions/[id]/route.ts +0 -25
  204. package/apps/dashboard/app/api/internal/set-project/route.ts +0 -17
  205. package/apps/dashboard/app/api/kanban/route.ts +0 -15
  206. package/apps/dashboard/app/api/settings/env-vars/route.ts +0 -125
  207. package/apps/dashboard/app/api/settings/general/route.ts +0 -21
  208. package/apps/dashboard/app/api/tests/route.ts +0 -9
  209. package/apps/dashboard/app/api/tests/run/route.ts +0 -82
  210. package/apps/dashboard/app/api/tests/run/stream/route.ts +0 -71
  211. package/apps/dashboard/app/api/tests/undefined/route.ts +0 -9
  212. package/apps/dashboard/app/api/usage/route.ts +0 -17
  213. package/apps/dashboard/app/api/work/[id]/description/route.ts +0 -21
  214. package/apps/dashboard/app/api/work/[id]/epic/route.ts +0 -21
  215. package/apps/dashboard/app/api/work/[id]/order/route.ts +0 -21
  216. package/apps/dashboard/app/api/work/[id]/status/route.ts +0 -21
  217. package/apps/dashboard/app/api/work/[id]/title/route.ts +0 -21
  218. package/apps/dashboard/app/layout.tsx +0 -43
  219. package/apps/dashboard/components/UpgradeBanner.tsx +0 -29
  220. package/apps/dashboard/electron/ipc-handlers.js +0 -1028
  221. package/apps/dashboard/electron/main.js +0 -2124
  222. package/apps/dashboard/electron/preload.js +0 -123
  223. package/apps/dashboard/electron/session-manager.js +0 -141
  224. package/apps/dashboard/electron-builder.config.js +0 -357
  225. package/apps/dashboard/hooks/useClaudeSessions.ts +0 -299
  226. package/apps/dashboard/lib/claude-process-manager.ts +0 -492
  227. package/apps/dashboard/lib/db-bridge.ts +0 -282
  228. package/apps/dashboard/lib/prototypes.ts +0 -202
  229. package/apps/dashboard/lib/test-results-db.ts +0 -307
  230. package/apps/dashboard/lib/tests.ts +0 -282
  231. package/apps/dashboard/next.config.js +0 -50
  232. package/apps/dashboard/postcss.config.mjs +0 -7
  233. package/apps/dashboard/public/file.svg +0 -1
  234. package/apps/dashboard/public/globe.svg +0 -1
  235. package/apps/dashboard/public/next.svg +0 -1
  236. package/apps/dashboard/public/vercel.svg +0 -1
  237. package/apps/dashboard/public/window.svg +0 -1
  238. package/apps/dashboard/scripts/download-node.js +0 -104
  239. package/apps/dashboard/scripts/upload-to-r2.js +0 -89
  240. package/docs/bdd-guidance.md +0 -390
@@ -0,0 +1,62 @@
1
+ import { useRef, useState, useEffect, memo } from 'react';
2
+
3
+ /**
4
+ * Finds the nearest scrollable ancestor for IntersectionObserver root.
5
+ */
6
+ function getScrollParent(el: HTMLElement): HTMLElement | null {
7
+ let parent = el.parentElement;
8
+ while (parent) {
9
+ const { overflowY } = getComputedStyle(parent);
10
+ if (overflowY === 'auto' || overflowY === 'scroll') return parent;
11
+ parent = parent.parentElement;
12
+ }
13
+ return null;
14
+ }
15
+
16
+ interface LazyCardProps {
17
+ children: React.ReactNode;
18
+ /** Estimated card height used before first measurement */
19
+ estimatedHeight?: number;
20
+ }
21
+
22
+ /**
23
+ * Renders children only when visible in the scroll container.
24
+ * Offscreen cards are replaced with a height-matched placeholder,
25
+ * dramatically reducing DOM node count for large lists.
26
+ */
27
+ export const LazyCard = memo(function LazyCard({
28
+ children,
29
+ estimatedHeight = 82,
30
+ }: LazyCardProps) {
31
+ const ref = useRef<HTMLDivElement>(null);
32
+ const [visible, setVisible] = useState(false);
33
+ const measuredHeight = useRef(estimatedHeight);
34
+
35
+ useEffect(() => {
36
+ const el = ref.current;
37
+ if (!el) return;
38
+
39
+ const root = getScrollParent(el);
40
+ const io = new IntersectionObserver(
41
+ ([entry]) => {
42
+ if (entry.isIntersecting) {
43
+ setVisible(true);
44
+ } else {
45
+ // Capture height before replacing children with placeholder
46
+ const h = el.offsetHeight;
47
+ if (h > 0) measuredHeight.current = h;
48
+ setVisible(false);
49
+ }
50
+ },
51
+ { root, rootMargin: '300px 0px' }
52
+ );
53
+ io.observe(el);
54
+ return () => io.disconnect();
55
+ }, []);
56
+
57
+ return (
58
+ <div ref={ref} style={visible ? undefined : { height: measuredHeight.current }}>
59
+ {visible ? children : null}
60
+ </div>
61
+ );
62
+ });
@@ -0,0 +1,11 @@
1
+
2
+ import ReactMarkdown, { type Components } from 'react-markdown';
3
+ import remarkGfm from 'remark-gfm';
4
+
5
+ export default function LazyMarkdown({ children, components }: { children: string; components?: Components }) {
6
+ return (
7
+ <ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>
8
+ {children}
9
+ </ReactMarkdown>
10
+ );
11
+ }
@@ -1,130 +1,95 @@
1
- 'use client';
2
-
3
- import Image from 'next/image';
4
- import Link from 'next/link';
5
- import { usePathname } from 'next/navigation';
6
- import { useClaudeSession } from '../contexts/ClaudeSessionContext';
7
- import { useConnectionStatus } from '../contexts/ConnectionStatusContext';
1
+ import { useCallback } from 'react';
2
+ import { Link, useLocation } from 'react-router-dom';
8
3
  import { ProjectSwitcher } from './ProjectSwitcher';
4
+ import { prefetch } from '@/lib/data-bridge';
9
5
 
10
6
  interface MainNavProps {
11
7
  projectName: string;
12
8
  }
13
9
 
14
10
  export function MainNav({ projectName }: MainNavProps) {
15
- const pathname = usePathname();
16
- const { openSessionPanel } = useClaudeSession();
17
- const { status: connectionStatus } = useConnectionStatus();
18
-
11
+ const { pathname } = useLocation();
19
12
  const isBacklogActive = pathname === '/';
20
13
  const isTestsActive = pathname === '/tests';
21
14
  const isPrototypesActive = pathname === '/prototypes';
22
15
  const isSettingsActive = pathname === '/settings';
23
16
 
17
+ // Prefetch page data on hover — by the time the click fires and the component
18
+ // mounts, data is already cached and ready.
19
+ const prefetchBacklog = useCallback(() => { prefetch.backlog(); }, []);
20
+ const prefetchTests = useCallback(() => { prefetch.tests(); }, []);
21
+ const prefetchPrototypes = useCallback(() => { prefetch.prototypes(); }, []);
22
+ const prefetchSettings = useCallback(() => { prefetch.settings(); }, []);
23
+
24
24
  return (
25
25
  <header className="sticky top-0 z-10 border-b border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 flex-shrink-0">
26
- <div className="max-w-6xl mx-auto px-4 py-4">
26
+ <div className="px-5 py-5">
27
27
  <div className="flex items-center justify-between">
28
- <div className="flex items-center gap-3">
29
- <Image
30
- src="/jettypod_wordmark.png"
28
+ <div className="flex items-center gap-4">
29
+ <img
30
+ src="/jettypod_logo.png"
31
31
  alt="JettyPod"
32
- width={100}
33
- height={24}
34
- priority
32
+ width={36}
33
+ height={36}
34
+ className="rounded-full"
35
35
  />
36
36
  <ProjectSwitcher projectName={projectName} />
37
37
  {isBacklogActive ? (
38
- <span className="px-2.5 py-1 text-sm text-zinc-900 dark:text-zinc-100 font-medium">
38
+ <span className="px-3 py-1.5 text-base text-zinc-900 dark:text-zinc-100 font-medium">
39
39
  Backlog
40
40
  </span>
41
41
  ) : (
42
42
  <Link
43
- href="/"
44
- className="px-2.5 py-1 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
43
+ to="/"
44
+ viewTransition
45
+ onMouseEnter={prefetchBacklog}
46
+ className="px-3 py-1.5 text-base text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors duration-200 ease-out"
45
47
  >
46
48
  Backlog
47
49
  </Link>
48
50
  )}
49
51
  {isTestsActive ? (
50
- <span className="px-2.5 py-1 text-sm text-zinc-900 dark:text-zinc-100 font-medium">
52
+ <span className="px-3 py-1.5 text-base text-zinc-900 dark:text-zinc-100 font-medium">
51
53
  Tests
52
54
  </span>
53
55
  ) : (
54
56
  <Link
55
- href="/tests"
56
- className="px-2.5 py-1 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
57
+ to="/tests"
58
+ viewTransition
59
+ onMouseEnter={prefetchTests}
60
+ className="px-3 py-1.5 text-base text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors duration-200 ease-out"
57
61
  >
58
62
  Tests
59
63
  </Link>
60
64
  )}
61
65
  {isPrototypesActive ? (
62
- <span className="px-2.5 py-1 text-sm text-zinc-900 dark:text-zinc-100 font-medium">
66
+ <span className="px-3 py-1.5 text-base text-zinc-900 dark:text-zinc-100 font-medium">
63
67
  Prototypes
64
68
  </span>
65
69
  ) : (
66
70
  <Link
67
- href="/prototypes"
68
- className="px-2.5 py-1 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
71
+ to="/prototypes"
72
+ viewTransition
73
+ onMouseEnter={prefetchPrototypes}
74
+ className="px-3 py-1.5 text-base text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors duration-200 ease-out"
69
75
  >
70
76
  Prototypes
71
77
  </Link>
72
78
  )}
73
79
  {isSettingsActive ? (
74
- <span className="px-2.5 py-1 text-sm text-zinc-900 dark:text-zinc-100 font-medium">
80
+ <span className="px-3 py-1.5 text-base text-zinc-900 dark:text-zinc-100 font-medium">
75
81
  Settings
76
82
  </span>
77
83
  ) : (
78
84
  <Link
79
- href="/settings"
80
- className="px-2.5 py-1 text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
85
+ to="/settings"
86
+ viewTransition
87
+ onMouseEnter={prefetchSettings}
88
+ className="px-3 py-1.5 text-base text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors duration-200 ease-out"
81
89
  >
82
90
  Settings
83
91
  </Link>
84
92
  )}
85
- {/* Connection Status Indicator */}
86
- <div className="flex items-center gap-2" data-testid="connection-status">
87
- <span
88
- className={`w-2 h-2 rounded-full ${
89
- connectionStatus === 'connected'
90
- ? 'bg-green-500'
91
- : connectionStatus === 'reconnecting'
92
- ? 'bg-yellow-500 animate-pulse'
93
- : 'bg-red-500'
94
- }`}
95
- />
96
- <span className="text-xs text-zinc-500 dark:text-zinc-400">
97
- {connectionStatus === 'connected'
98
- ? 'Live updates active'
99
- : connectionStatus === 'reconnecting'
100
- ? 'Reconnecting...'
101
- : 'Disconnected'}
102
- </span>
103
- </div>
104
- </div>
105
- <div className="flex items-center">
106
- <button
107
- onClick={openSessionPanel}
108
- className="px-4 py-2 text-xs font-medium rounded-xl transition-all duration-200 hover:-translate-y-1 hover:scale-[1.01] active:translate-y-0 active:scale-100"
109
- style={{
110
- cursor: 'pointer',
111
- background: 'linear-gradient(145deg, #ffffff 0%, #faf9f7 10%, #f0f4f4 35%, #c8d9da 55%, #819D9F 90%)',
112
- color: '#3d4d4e',
113
- boxShadow: `
114
- 0 1px 1px rgba(0, 0, 0, 0.02),
115
- 0 2px 4px rgba(0, 0, 0, 0.03),
116
- 0 6px 12px rgba(0, 0, 0, 0.05),
117
- 0 12px 24px rgba(0, 0, 0, 0.06),
118
- 0 20px 40px rgba(129, 157, 159, 0.2),
119
- 0 32px 64px rgba(129, 157, 159, 0.18),
120
- inset 0 2px 4px rgba(255, 255, 255, 1),
121
- inset 0 -2px 4px rgba(129, 157, 159, 0.05)
122
- `,
123
- }}
124
- data-testid="nav-claude-sessions-button"
125
- >
126
- Claude Sessions
127
- </button>
128
93
  </div>
129
94
  </div>
130
95
  </div>