- Add logo.svg as the new brand logo
- Generate logo-192x192.png and logo-512x512.png from SVG for PWA
- Update app-header, manifest, and layout to reference new logo files
- Remove old icon.png, icon-192x192.png, icon-512x512.png
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- desktop layout.tsx: remove connection logic, keep header + tabs + outlet
- web app-header.tsx: remove connection logic, keep logo + theme toggle
Connection lifecycle is now owned by the shared Chat component.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove all props from Chat (showHeader, headerActions) making it a
zero-config pure chat component with only connection input, messages,
and send functionality
- Create AppHeader client component for web app with brand, theme
toggle, disconnect button, and useHubInit
- Add disconnect button to desktop layout header
- Add reset() action to hub store to eliminate duplicated state reset
- Remove unused token field from gateway store
- Remove dead code: connection-bar.tsx
- Guard handleConnect against empty deviceId race condition
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Chat component no longer depends on next-themes, making it safe to use
in the desktop app. Theme toggle is now a fixed button in the web layout.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add connection code parsing (JSON + base64) with localStorage persistence
- Add connectWithCode() to gateway store for code-driven connections
- Replace Sidebar with simple ConnectionBar (paste code / status / disconnect)
- Simplify Chat component by removing header clutter
- Auto-restore connection on page refresh from saved code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Next.js MetadataRoute.Manifest types only accept single-value purpose
fields, not space-separated combinations like "any maskable".
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Enable the web app to be installed as a standalone PWA on mobile and
desktop. Uses Next.js built-in Metadata API for manifest generation,
a lightweight service worker for navigation offline fallback, and
proper Apple Web App metadata for iOS support.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move gatewayUrl into gateway store state with setGatewayUrl action
- layout.tsx uses useGatewayStore.getState().setGatewayUrl() directly
- Remove @multica/fetch from store and web package.json dependencies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Document thin-shell architecture, package responsibilities, Zustand
best practices, import conventions, and new feature checklist.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move setConfig() after imports in layout.tsx
- Add gateway disconnect cleanup in hub-init useEffect
- Replace silent catches with toast error notifications in hub store
- Optimize chat selectors with useMemo and useCallback/getState()
- Remove unused getMessagesByAgent from messages store
- Add clipboard try/catch with error toast
- Add skeleton loading states for hub sidebar and chat header
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create gateway store in @multica/store (WS connection independent of components)
- Gateway auto-connects when hub is ready, messages handled internally
- Move scroll-fade hook to @multica/ui/hooks
- Move Chat component to @multica/ui/components
- Add setConfig() call in web layout for URL injection
- Delete all web-local hooks, components, and lib/config
- Web app is now a pure shell: layout.tsx + page.tsx
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move useMessages from apps/web to packages/store/src/messages.ts
- Convert useState to Zustand store for global message persistence
- Add reserved interfaces: updateMessage, loadMessages, getMessagesByAgent
- Update chat.tsx imports to use @multica/store
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move useDeviceId from apps/web to packages/store/src/device-id.ts
- Update imports in chat.tsx and use-gateway.ts to use @multica/store
- Add uuid dependency to @multica/store
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create @multica/fetch package for HTTP client and URL config
- Migrate hub store and hub-init hook to @multica/store
- Move HubSidebar component to @multica/ui for web/desktop reuse
- Update web app imports to use shared packages
- Remove counter store example and its component-example usage
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Simplified handleSend function in Chat component by removing unnecessary useCallback.
- Refactored useDeviceId hook to utilize useSyncExternalStore for better state management and removed useState and useEffect for device ID retrieval.
- Updated useGateway hook to ensure onMessageRef is set correctly on options change.
- Enhanced useScrollFade hook to properly cancel animation frames on cleanup.
Replace useState-based useHub hook and separate useActiveAgent store
with a single useHubStore (Zustand). This fixes the bug where
HubSidebar and Chat held independent state copies, causing stale data
and duplicate 30s polling. Agent create/delete logic now lives in the
store with automatic activeAgentId management.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Re-add deviceId (full UUID) with copy-to-clipboard button next to the
SidebarTrigger, matching the original behavior from commit 0975510.
Both deviceId and agentId now have independent copy states.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Re-add the copy-to-clipboard button that was lost when chat.tsx was
rewritten for hub/agent support. Clicking copies the full agentId,
shows a checkmark icon for 2s, and triggers a toast confirmation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Align with sidebar component library convention: use Tailwind v4 native
data-active: instead of data-[active]:, and add missing
text-sidebar-accent-foreground for active state.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace SidebarMenuButton with a custom flex row div that handles hover
and active states on the entire item, not just the text area. Delete
button uses stopPropagation to avoid triggering selection.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SidebarMenuButton applies truncate via [&>span:last-child]:truncate,
so the text must be in a <span> rather than a bare text node to get
overflow-hidden + text-ellipsis + whitespace-nowrap.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Drop SidebarMenuAction (absolute positioning) in favor of a flex row:
left side (SidebarMenuButton) gets flex-1 min-w-0 for natural truncation,
right side (delete button) sits as a normal flex child with hover reveal.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add cursor-not-allowed and reduced opacity to ChatInput when disabled
- Show user icon in empty state when no agent is selected
- Pass contextual placeholder text based on agent selection
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use CSS truncation for agent/hub IDs instead of JS slicing, show delete
button only on hover via showOnHover prop, and reduce contrast on status
dots, labels, and placeholder text for a more subtle appearance.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- hub-sidebar: displays Hub connection status, agent list with create/delete
- chat: sends messages via Gateway to Hub, receives agent responses, filters by active agent
- layout: passes HubSidebar as children to AppSidebar, removes static NAV_ITEMS
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- use-gateway: GatewayClient WebSocket lifecycle with auto-connect/disconnect
- use-hub: REST polling for Hub status and agent CRUD operations
- use-active-agent: Zustand store for cross-component selected agent state
- use-messages: replace mock data with real addUser/addAssistant/clear API
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds gateway and console URL configuration in app/lib/config.ts,
centralizing endpoint URLs with env var overrides.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Display Multica icon alongside brand name in sidebar header
- Use Playfair Display serif font for an artistic brand feel
- Expose --font-brand CSS variable from layout
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Copy brand icon from gateway to web app/icon.png and public/icon.png
- Remove default favicon.ico and placeholder SVGs
- Update metadata title and description
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
sonner is a dependency of @multica/ui, not web. Re-export toast from
the ui sonner module and update the import path in chat.tsx.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Display full UUID instead of truncated 8-char slice. Add ghost button
with copy icon that writes deviceId to clipboard, switches to checkmark
for 2s, and shows a sonner toast confirmation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move device ID logic from @multica/store (Zustand persist) into a
simple useDeviceId hook in the web app. SSR returns empty string,
client reads/writes localStorage directly — no hydration mismatch,
no suppressHydrationWarning needed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use CSS mask-image gradients to hint at scrollable overflow in the chat
area. Adds useScrollFade hook that dynamically applies top/bottom fade
based on scroll position via scroll events and ResizeObserver.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Zustand persist generates a new deviceId on the server (no localStorage),
then hydrates a different value from localStorage on the client. Add
suppressHydrationWarning to the deviceId span since this mismatch is expected.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add next-themes integration with a ThemeProvider wrapper and a
ThemeToggle dropdown (Light / Dark / System) in the sidebar footer.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Lift AppSidebar, SidebarInset and SidebarTrigger into the root layout
so page.tsx only contains page-specific content.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create empty Chat component and wire it into the main page,
replacing the previous mock Markdown/ChatInput content.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move sidebar markup from page.tsx into a reusable AppSidebar component
in packages/ui for cross-app reuse.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wrap layout in SidebarProvider, restructure page into left
sidebar navigation + right SidebarInset content area.
Add use-mobile hook via shadcn for responsive behavior.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add CodeBlock, Markdown, StreamingMarkdown components with
Shiki syntax highlighting, GFM support, and linkify utility.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create packages/store with @multica/store package
- Add zustand to pnpm catalog for version consistency
- Add counter store as cross-platform state example
- Integrate counter into ComponentExample for verification
- Add tsconfig path mappings for web and desktop
- Add @multica/store to Next.js transpilePackages
- Add @multica/store dependency to packages/ui
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>