jettypod 4.4.120 → 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 (208) hide show
  1. package/.env +2 -1
  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 +54 -49
  8. package/apps/dashboard/app/demo/gates/page.tsx +3 -5
  9. package/apps/dashboard/app/design-system/page.tsx +1 -1
  10. package/apps/dashboard/app/globals.css +74 -2
  11. package/apps/dashboard/app/install-claude/page.tsx +3 -5
  12. package/apps/dashboard/app/login/page.tsx +17 -20
  13. package/apps/dashboard/app/page.tsx +101 -48
  14. package/apps/dashboard/app/settings/page.tsx +60 -12
  15. package/apps/dashboard/app/signup/page.tsx +14 -17
  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 +12 -15
  19. package/apps/dashboard/app/work/[id]/page.tsx +90 -75
  20. package/apps/dashboard/app/work/[id]/proof/page.tsx +1489 -0
  21. package/apps/dashboard/components/AppShell.tsx +70 -61
  22. package/apps/dashboard/components/CardMenu.tsx +0 -1
  23. package/apps/dashboard/components/ClaudePanel.tsx +541 -283
  24. package/apps/dashboard/components/ClaudePanelInput.tsx +23 -4
  25. package/apps/dashboard/components/ConnectClaudeScreen.tsx +1 -5
  26. package/apps/dashboard/components/CopyableId.tsx +1 -2
  27. package/apps/dashboard/components/DetailReviewActions.tsx +11 -20
  28. package/apps/dashboard/components/DragContext.tsx +132 -62
  29. package/apps/dashboard/components/DraggableCard.tsx +3 -5
  30. package/apps/dashboard/components/DropZone.tsx +5 -6
  31. package/apps/dashboard/components/EditableDetailDescription.tsx +6 -12
  32. package/apps/dashboard/components/EditableDetailTitle.tsx +6 -13
  33. package/apps/dashboard/components/EditableTitle.tsx +0 -1
  34. package/apps/dashboard/components/ElapsedTimer.tsx +15 -3
  35. package/apps/dashboard/components/EpicGroup.tsx +100 -70
  36. package/apps/dashboard/components/GateCard.tsx +0 -1
  37. package/apps/dashboard/components/GateChoiceCard.tsx +1 -2
  38. package/apps/dashboard/components/InstallClaudeScreen.tsx +1 -5
  39. package/apps/dashboard/components/JettyLoader.tsx +0 -1
  40. package/apps/dashboard/components/KanbanBoard.tsx +319 -173
  41. package/apps/dashboard/components/KanbanCard.tsx +341 -107
  42. package/apps/dashboard/components/LazyCard.tsx +62 -0
  43. package/apps/dashboard/components/LazyMarkdown.tsx +0 -1
  44. package/apps/dashboard/components/MainNav.tsx +24 -25
  45. package/apps/dashboard/components/MessageBlock.tsx +93 -16
  46. package/apps/dashboard/components/ModeStartCard.tsx +0 -1
  47. package/apps/dashboard/components/OnboardingWelcome.tsx +0 -1
  48. package/apps/dashboard/components/PlaceholderCard.tsx +0 -1
  49. package/apps/dashboard/components/ProjectSwitcher.tsx +20 -20
  50. package/apps/dashboard/components/PrototypeTimeline.tsx +47 -26
  51. package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +308 -223
  52. package/apps/dashboard/components/RealTimeTestsWrapper.tsx +303 -160
  53. package/apps/dashboard/components/ReviewFooter.tsx +12 -14
  54. package/apps/dashboard/components/SessionList.tsx +0 -1
  55. package/apps/dashboard/components/SubscribeContent.tsx +40 -11
  56. package/apps/dashboard/components/TestTree.tsx +1 -2
  57. package/apps/dashboard/components/TipCard.tsx +2 -4
  58. package/apps/dashboard/components/Toast.tsx +0 -1
  59. package/apps/dashboard/components/TypeIcon.tsx +7 -8
  60. package/apps/dashboard/components/ViewModeToolbar.tsx +104 -0
  61. package/apps/dashboard/components/WaveCompletionAnimation.tsx +5 -17
  62. package/apps/dashboard/components/WelcomeScreen.tsx +2 -6
  63. package/apps/dashboard/components/WorkItemHeader.tsx +0 -1
  64. package/apps/dashboard/components/WorkItemTree.tsx +2 -4
  65. package/apps/dashboard/components/settings/AccountSection.tsx +27 -13
  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 +20 -73
  69. package/apps/dashboard/components/settings/GeneralSection.tsx +137 -26
  70. package/apps/dashboard/components/settings/ProjectStackSection.tsx +948 -0
  71. package/apps/dashboard/components/settings/SettingsLayout.tsx +0 -1
  72. package/apps/dashboard/components/ui/Button.tsx +1 -1
  73. package/apps/dashboard/components/ui/Input.tsx +1 -1
  74. package/apps/dashboard/components.json +1 -1
  75. package/apps/dashboard/contexts/ClaudeSessionContext.tsx +611 -358
  76. package/apps/dashboard/contexts/ConnectionStatusContext.tsx +0 -1
  77. package/apps/dashboard/contexts/UsageContext.tsx +62 -31
  78. package/apps/dashboard/dev.sh +35 -0
  79. package/apps/dashboard/eslint.config.mjs +9 -9
  80. package/apps/dashboard/hooks/useWebSocket.ts +138 -83
  81. package/apps/dashboard/index.html +73 -0
  82. package/apps/dashboard/lib/data-bridge.ts +722 -0
  83. package/apps/dashboard/lib/db.ts +69 -1302
  84. package/apps/dashboard/lib/environment-config.ts +173 -0
  85. package/apps/dashboard/lib/environment-verification.ts +119 -0
  86. package/apps/dashboard/lib/kanban-utils.ts +226 -26
  87. package/apps/dashboard/lib/proof-run.ts +495 -0
  88. package/apps/dashboard/lib/proof-scenario-runner.ts +346 -0
  89. package/apps/dashboard/lib/service-recovery.ts +326 -0
  90. package/apps/dashboard/lib/session-state-machine.ts +1 -0
  91. package/apps/dashboard/lib/session-state-utils.ts +0 -164
  92. package/apps/dashboard/lib/session-stream-manager.ts +253 -122
  93. package/apps/dashboard/lib/stream-manager-registry.ts +46 -6
  94. package/apps/dashboard/lib/tauri-bridge.ts +102 -0
  95. package/apps/dashboard/lib/tauri.ts +106 -0
  96. package/apps/dashboard/lib/utils.ts +3 -3
  97. package/apps/dashboard/next-env.d.ts +1 -1
  98. package/apps/dashboard/package.json +21 -33
  99. package/apps/dashboard/public/bug-icon.png +0 -0
  100. package/apps/dashboard/public/buoy-icon.png +0 -0
  101. package/apps/dashboard/public/in-flight-seagull.png +0 -0
  102. package/apps/dashboard/public/pier-icon.png +0 -0
  103. package/apps/dashboard/public/star-icon.png +0 -0
  104. package/apps/dashboard/public/wrench-icon.png +0 -0
  105. package/apps/dashboard/scripts/tauri-build.js +228 -0
  106. package/apps/dashboard/scripts/upload-tauri-to-r2.js +125 -0
  107. package/apps/dashboard/src/main.tsx +12 -0
  108. package/apps/dashboard/src/router.tsx +107 -0
  109. package/apps/dashboard/src/vite-env.d.ts +1 -0
  110. package/apps/dashboard/tsconfig.json +7 -12
  111. package/apps/dashboard/tsconfig.tsbuildinfo +1 -1
  112. package/apps/dashboard/vite.config.ts +33 -0
  113. package/apps/update-server/src/index.ts +167 -30
  114. package/claude-hooks/global-guardrails.js +14 -13
  115. package/crates/jettypod-cli/Cargo.toml +19 -0
  116. package/crates/jettypod-cli/src/commands.rs +1249 -0
  117. package/crates/jettypod-cli/src/main.rs +595 -0
  118. package/crates/jettypod-core/Cargo.toml +26 -0
  119. package/crates/jettypod-core/build.rs +98 -0
  120. package/crates/jettypod-core/migrations/V1__baseline.sql +197 -0
  121. package/crates/jettypod-core/migrations/V2__work_items_indexes.sql +6 -0
  122. package/crates/jettypod-core/migrations/V3__qa_steps.sql +2 -0
  123. package/crates/jettypod-core/src/auth.rs +294 -0
  124. package/crates/jettypod-core/src/config.rs +397 -0
  125. package/crates/jettypod-core/src/db/mod.rs +507 -0
  126. package/crates/jettypod-core/src/db/recovery.rs +114 -0
  127. package/crates/jettypod-core/src/db/startup.rs +101 -0
  128. package/crates/jettypod-core/src/db/validate.rs +149 -0
  129. package/crates/jettypod-core/src/error.rs +76 -0
  130. package/crates/jettypod-core/src/git.rs +458 -0
  131. package/crates/jettypod-core/src/lib.rs +20 -0
  132. package/crates/jettypod-core/src/sessions.rs +625 -0
  133. package/crates/jettypod-core/src/skills.rs +556 -0
  134. package/crates/jettypod-core/src/work.rs +1086 -0
  135. package/crates/jettypod-core/src/worktree.rs +628 -0
  136. package/crates/jettypod-core/src/ws.rs +767 -0
  137. package/cucumber-test.cjs +6 -0
  138. package/jettypod.js +96 -4
  139. package/lib/bdd-preflight.js +96 -0
  140. package/lib/merge-lock.js +111 -253
  141. package/lib/migrations/030-rejection-round-columns.js +54 -0
  142. package/lib/migrations/031-session-isolation-index.js +17 -0
  143. package/lib/work-commands/index.js +58 -16
  144. package/lib/work-tracking/index.js +108 -8
  145. package/package.json +1 -1
  146. package/skills-templates/bug-mode/SKILL.md +43 -1
  147. package/skills-templates/chore-mode/SKILL.md +40 -1
  148. package/skills-templates/design-system-selection/SKILL.md +273 -0
  149. package/skills-templates/epic-planning/SKILL.md +14 -0
  150. package/skills-templates/feature-planning/SKILL.md +90 -1
  151. package/skills-templates/production-mode/SKILL.md +20 -0
  152. package/skills-templates/simple-improvement/SKILL.md +39 -2
  153. package/skills-templates/speed-mode/SKILL.md +10 -15
  154. package/skills-templates/stable-mode/SKILL.md +47 -0
  155. package/apps/dashboard/README.md +0 -36
  156. package/apps/dashboard/app/api/claude/[workItemId]/message/route.ts +0 -446
  157. package/apps/dashboard/app/api/claude/[workItemId]/pin/route.ts +0 -24
  158. package/apps/dashboard/app/api/claude/[workItemId]/route.ts +0 -280
  159. package/apps/dashboard/app/api/claude/sessions/[sessionId]/content/route.ts +0 -52
  160. package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +0 -525
  161. package/apps/dashboard/app/api/claude/sessions/[sessionId]/pin/route.ts +0 -24
  162. package/apps/dashboard/app/api/claude/sessions/cleanup/route.ts +0 -34
  163. package/apps/dashboard/app/api/claude/sessions/route.ts +0 -184
  164. package/apps/dashboard/app/api/decisions/[id]/route.ts +0 -25
  165. package/apps/dashboard/app/api/internal/set-project/route.ts +0 -17
  166. package/apps/dashboard/app/api/kanban/route.ts +0 -15
  167. package/apps/dashboard/app/api/settings/env-vars/route.ts +0 -125
  168. package/apps/dashboard/app/api/settings/general/route.ts +0 -21
  169. package/apps/dashboard/app/api/tests/route.ts +0 -9
  170. package/apps/dashboard/app/api/tests/run/route.ts +0 -82
  171. package/apps/dashboard/app/api/tests/run/stream/route.ts +0 -71
  172. package/apps/dashboard/app/api/tests/undefined/route.ts +0 -9
  173. package/apps/dashboard/app/api/usage/route.ts +0 -17
  174. package/apps/dashboard/app/api/work/[id]/description/route.ts +0 -21
  175. package/apps/dashboard/app/api/work/[id]/epic/route.ts +0 -21
  176. package/apps/dashboard/app/api/work/[id]/order/route.ts +0 -21
  177. package/apps/dashboard/app/api/work/[id]/route.ts +0 -35
  178. package/apps/dashboard/app/api/work/[id]/status/route.ts +0 -63
  179. package/apps/dashboard/app/api/work/[id]/title/route.ts +0 -21
  180. package/apps/dashboard/app/layout.tsx +0 -55
  181. package/apps/dashboard/components/UpgradeBanner.tsx +0 -30
  182. package/apps/dashboard/electron/ipc-handlers.js +0 -1026
  183. package/apps/dashboard/electron/main.js +0 -2306
  184. package/apps/dashboard/electron/preload.js +0 -125
  185. package/apps/dashboard/electron/session-manager.js +0 -163
  186. package/apps/dashboard/electron-builder.config.js +0 -357
  187. package/apps/dashboard/hooks/useClaudeSessions.ts +0 -299
  188. package/apps/dashboard/lib/backlog-parser.ts +0 -50
  189. package/apps/dashboard/lib/claude-process-manager.ts +0 -529
  190. package/apps/dashboard/lib/db-bridge.ts +0 -283
  191. package/apps/dashboard/lib/prototypes.ts +0 -202
  192. package/apps/dashboard/lib/test-results-db.ts +0 -307
  193. package/apps/dashboard/lib/tests.ts +0 -282
  194. package/apps/dashboard/next.config.js +0 -66
  195. package/apps/dashboard/postcss.config.mjs +0 -7
  196. package/apps/dashboard/public/bug-icon.svg +0 -9
  197. package/apps/dashboard/public/buoy-icon.svg +0 -9
  198. package/apps/dashboard/public/file.svg +0 -1
  199. package/apps/dashboard/public/globe.svg +0 -1
  200. package/apps/dashboard/public/in-flight-seagull.svg +0 -9
  201. package/apps/dashboard/public/next.svg +0 -1
  202. package/apps/dashboard/public/pier-icon.svg +0 -14
  203. package/apps/dashboard/public/star-icon.svg +0 -9
  204. package/apps/dashboard/public/vercel.svg +0 -1
  205. package/apps/dashboard/public/window.svg +0 -1
  206. package/apps/dashboard/public/wrench-icon.svg +0 -9
  207. package/apps/dashboard/scripts/download-node.js +0 -104
  208. package/apps/dashboard/scripts/upload-to-r2.js +0 -89
@@ -1,95 +1,106 @@
1
- 'use client';
2
-
3
- import { useState, useEffect } from 'react';
4
- import { usePathname, useRouter } from 'next/navigation';
1
+ import { useEffect, useRef, useLayoutEffect } from 'react';
2
+ import { useLocation, useNavigate } from 'react-router-dom';
5
3
  import { ClaudeSessionProvider, useSessionState, useSessionActions } from '../contexts/ClaudeSessionContext';
6
4
  import { ConnectionStatusProvider, useConnectionStatus } from '../contexts/ConnectionStatusContext';
7
5
  import { UsageProvider } from '../contexts/UsageContext';
8
6
  import { ToastProvider } from './Toast';
9
7
  import { MainNav } from './MainNav';
10
8
  import { ClaudePanel } from './ClaudePanel';
11
- import { JettyLoader } from './JettyLoader';
12
- import { LazyMotion, domAnimation, m, AnimatePresence } from 'framer-motion';
9
+ import { LazyMotion, domAnimation, m } from 'framer-motion';
10
+ import { isTauri, auth } from '@/lib/tauri-bridge';
13
11
  import type { ReactNode } from 'react';
14
12
 
13
+ // Module-level auth cache — auth status doesn't change within a session.
14
+ // Prevents redundant IPC calls if AppShell ever remounts.
15
+ let cachedAuthOk: boolean | null = null;
16
+
15
17
  // Pages that should not show the nav header (pre-project screens)
16
- const NO_NAV_PATHS = ['/login', '/signup', '/subscribe', '/install-claude', '/connect-claude', '/welcome'];
18
+ const NO_NAV_PATHS = ['/login', '/signup', '/subscribe', '/install-claude', '/connect-claude', '/welcome', '/prototypes/onboarding'];
17
19
 
18
20
  // Pages accessible without authentication
19
- const PUBLIC_PATHS = ['/login', '/signup', '/subscribe', '/install-claude', '/connect-claude', '/welcome', '/design-system'];
21
+ const PUBLIC_PATHS = ['/login', '/signup', '/subscribe', '/install-claude', '/connect-claude', '/welcome', '/design-system', '/prototypes/onboarding'];
20
22
 
21
23
  interface AppShellProps {
22
- projectName: string;
24
+ projectName?: string;
23
25
  children: ReactNode;
24
26
  }
25
27
 
26
- function AppShellContent({ projectName, children }: AppShellProps) {
27
- const pathname = usePathname();
28
- const router = useRouter();
28
+ function AppShellContent({ projectName = 'JettyPod', children }: AppShellProps) {
29
+ const { pathname } = useLocation();
30
+ const navigate = useNavigate();
29
31
  const showNav = !NO_NAV_PATHS.includes(pathname);
30
- const [authChecked, setAuthChecked] = useState(false);
31
- const [minLoadingDone, setMinLoadingDone] = useState(false);
32
+ const isPublicPath = PUBLIC_PATHS.includes(pathname);
32
33
  const { showDisconnected, status: connectionStatus } = useConnectionStatus();
33
34
 
34
- // Ensure the loading screen shows for at least 3 seconds
35
- useEffect(() => {
36
- const timer = setTimeout(() => setMinLoadingDone(true), 3000);
37
- return () => clearTimeout(timer);
38
- }, []);
39
-
40
- // Auth enforcement gate: redirect unauthenticated users to /signup (first-time) or /login (returning)
35
+ // Optimistic auth: render content immediately, check auth in the background.
36
+ // Redirects to login only if the async check fails — authenticated users
37
+ // (the common case) never see a loader or blank screen.
41
38
  useEffect(() => {
42
- if (PUBLIC_PATHS.includes(pathname)) {
43
- setAuthChecked(true);
44
- return;
45
- }
39
+ if (isPublicPath || cachedAuthOk) return;
46
40
 
47
41
  async function checkAuth() {
48
- if (typeof window !== 'undefined' && window.electronAPI?.isElectron) {
42
+ if (isTauri()) {
49
43
  try {
50
- const status = await window.electronAPI.auth.getStatus();
44
+ const status = await auth.getStatus();
51
45
  if (!status.authenticated) {
52
- const hasLoggedIn = await window.electronAPI.auth.hasLoggedInBefore?.();
53
- router.push(hasLoggedIn ? '/login' : '/signup');
46
+ const hasLoggedIn = await auth.hasLoggedInBefore();
47
+ navigate(hasLoggedIn ? '/login' : '/signup', { replace: true });
54
48
  return;
55
49
  }
50
+ cachedAuthOk = true;
56
51
  } catch {
57
- // Corrupted auth file, IPC error, etc. — treat as unauthenticated
58
- router.push('/login');
59
- return;
52
+ navigate('/login', { replace: true });
60
53
  }
61
54
  }
62
- setAuthChecked(true);
63
55
  }
64
56
  checkAuth();
65
- }, [pathname, router]);
57
+ // eslint-disable-next-line react-hooks/exhaustive-deps
58
+ }, []);
66
59
 
67
60
  const { claudePanelOpen } = useSessionState();
68
- const { setClaudePanelOpen } = useSessionActions();
61
+ const { setClaudePanelOpen, openSessionPanel } = useSessionActions();
69
62
 
70
- const showLoading = !authChecked || !minLoadingDone;
63
+ // Single source of truth for available content height.
64
+ // Sets --main-h CSS custom property on <main> so any descendant can use it
65
+ // without nested ResizeObservers or fragile flex-1 chains (which break in WKWebView).
66
+ const mainRef = useRef<HTMLElement>(null);
67
+ useLayoutEffect(() => {
68
+ const el = mainRef.current;
69
+ if (!el) return;
70
+ const ro = new ResizeObserver(([entry]) => {
71
+ el.style.setProperty('--main-h', `${entry.contentRect.height}px`);
72
+ });
73
+ ro.observe(el);
74
+ return () => ro.disconnect();
75
+ }, []);
71
76
 
72
77
  return (
73
- <AnimatePresence mode="wait">
74
- {showLoading ? (
75
- <m.div
76
- key="loader"
77
- initial={{ opacity: 0 }}
78
- animate={{ opacity: 1 }}
79
- exit={{ opacity: 0 }}
80
- transition={{ duration: 0.3 }}
81
- className="h-screen flex items-center justify-center bg-background"
82
- >
83
- <JettyLoader size={80} />
84
- </m.div>
85
- ) : (
86
- <m.div
87
- key="content"
88
- initial={{ opacity: 0 }}
89
- animate={{ opacity: 1 }}
90
- transition={{ duration: 0.3 }}
91
- className="h-screen flex flex-col overflow-hidden">
92
- {showNav && <MainNav projectName={projectName} />}
78
+ <div className="h-screen flex flex-col overflow-hidden">
79
+ {showNav && (
80
+ <div className="relative flex-shrink-0">
81
+ <MainNav projectName={projectName} />
82
+ <m.button
83
+ onClick={() => claudePanelOpen ? setClaudePanelOpen(false) : openSessionPanel()}
84
+ className="absolute px-3 py-1.5 text-sm font-medium text-white hover:brightness-105 active:scale-[0.98] cursor-pointer"
85
+ animate={{ right: claudePanelOpen ? 480 : 0 }}
86
+ transition={{ type: 'spring', damping: 25, stiffness: 200 }}
87
+ style={{
88
+ zIndex: 51,
89
+ top: '50%',
90
+ transform: 'translateY(-50%)',
91
+ backgroundColor: '#819D9F',
92
+ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.06), 0 4px 12px rgba(129, 157, 159, 0.2)',
93
+ borderRadius: '12px 0 0 12px',
94
+ textAlign: 'center' as const,
95
+ lineHeight: 1.3,
96
+ }}
97
+ aria-label={claudePanelOpen ? 'Hide Claudes panel' : 'Show Claudes panel'}
98
+ data-testid="claudes-toggle-tab"
99
+ >
100
+ {claudePanelOpen ? <><span>Hide</span><br /><span>Claudes</span></> : <><span>Show</span><br /><span>Claudes</span></>}
101
+ </m.button>
102
+ </div>
103
+ )}
93
104
  {showNav && showDisconnected && (
94
105
  <div className="bg-amber-50 dark:bg-amber-950 border-b border-amber-200 dark:border-amber-800 px-4 py-2 text-center text-base text-amber-800 dark:text-amber-200" data-testid="disconnect-banner">
95
106
  {connectionStatus === 'reconnecting'
@@ -97,7 +108,7 @@ function AppShellContent({ projectName, children }: AppShellProps) {
97
108
  : 'Live updates disconnected. Changes may not appear automatically.'}
98
109
  </div>
99
110
  )}
100
- <main className={`flex-1 flex flex-col min-h-0 overflow-y-auto transition-[margin] duration-200 ease-out ${showNav && claudePanelOpen ? 'mr-[480px]' : ''}`}>
111
+ <main ref={mainRef} className={`flex-1 flex flex-col min-h-0 overflow-hidden transition-[margin] duration-200 ease-out ${showNav && claudePanelOpen ? 'mr-[480px]' : ''}`}>
101
112
  {children}
102
113
  </main>
103
114
  {showNav && (
@@ -106,13 +117,11 @@ function AppShellContent({ projectName, children }: AppShellProps) {
106
117
  onClose={() => setClaudePanelOpen(false)}
107
118
  />
108
119
  )}
109
- </m.div>
110
- )}
111
- </AnimatePresence>
120
+ </div>
112
121
  );
113
122
  }
114
123
 
115
- export function AppShell({ projectName, children }: AppShellProps) {
124
+ export function AppShell({ projectName = 'JettyPod', children }: AppShellProps) {
116
125
  return (
117
126
  <LazyMotion features={domAnimation} strict>
118
127
  <ConnectionStatusProvider>
@@ -1,4 +1,3 @@
1
- 'use client';
2
1
 
3
2
  import { useState, useRef, useEffect } from 'react';
4
3
  import { createPortal } from 'react-dom';