Skip to content

Frontend Architecture

The frontend is a React 19 single-page application. It does not use React Router — navigation is driven entirely by a Zustand store. All communication with the native backend goes through the Tauri IPC bridge (invoke and listen).

src/App.tsx is the root component. On mount it:

  1. Detects whether the current window is the system tray panel (isTrayPanel()). If so, it renders the lightweight TrayPanelApp instead of the full shell.
  2. Calls is_first_launch() via IPC to detect a fresh install or post-factory-reset state.
  3. Shows either the onboarding flow (FirstLaunch) or the main app shell (AppShell).
  4. Registers all global effect hooks (event listeners, periodic syncs, shortcut interceptors).

The AppShell component wraps the router logic and renders the correct page based on the active route in useAppStore.

Navigation is a Route string union stored in useAppStore:

"dashboard" | "session" | "settings" | "extensions" | "projects" |
"sessions" | "changelog" | "project-settings" | "showcase" |
"workspaces" | "workspace-create" | "workspace-settings" |
"workspace-home" | "workspace-sessions"

AppShell reads the current route and conditionally renders the corresponding page component. There are no URLs, no history API, and no link-based navigation — all transitions happen through useAppStore actions (openSession, goHome, openSettings, etc.).

State is split into focused slices, each in src/store/. Stores that hold large or complex state are further split into sub-slices within their own subdirectory.

StoreDescription
useAppStoreActive route, active session ID, sidebar filters, view mode, command palette state
useMagiaStoreAll discovered sessions (sliced: session CRUD, pin/unpin, title sync, tools/dirs, branch info)
useDiscoveryStoreFilesystem scan state — triggers and coordinates discovery of provider session directories
useDiscoveryCacheStorePersistent cache of previously scanned sessions; avoids rescanning unchanged directories
useWorkspacesStoreNamed workspaces (groups of projects) and active workspace selection
StoreDescription
useAgentEventsStoreLive event stream per provider session ID — events, projections, dedup logic
useSessionTasksStoreTask list extracted from agent events for the active session
useSessionContextStorePer-session context extracted from the codebase (file tree, symbols, etc.)
useSessionHijackStoreDetects when another process has taken over a session
useSessionKeepAliveStoreHeartbeat pings to prevent idle sessions from being cleaned up
StoreDescription
useProvidersStoreDetected provider CLIs, connected accounts, active provider selection
useProviderProfilesStoreUser profile and subscription info fetched from provider APIs
useConnectedProvidersStoreWhich provider accounts are currently connected and authenticated
useAuthStoreAuthentication state (Magia cloud account, tokens)
StoreDescription
useSettingsStoreAll user preferences (sliced by domain: UI, editor, terminal, voice, telemetry, permissions, notifications, observations, provider settings)
useOnboardingStoreOnboarding completion flag and step tracking
useEditorStoreEditor layout: open files, split tree, active pane (sliced: file-slice, layout-slice, split-tree)
useSessionUIStorePer-session UI state: scroll position, input draft, panel layout
useInputDraftStorePersisted input drafts per session
useTerminalPanelStoreTerminal panel open/closed state and active terminal
useTrayPanelStoreTray panel window state
StoreDescription
usePluginsStoreInstalled MCP plugins and their enabled/disabled state
useKeybindingsStore + useShortcutStoreCustom keybinding definitions and the runtime interceptor
useThemesStoreCustom theme definitions loaded from ~/.magia/themes/
useOtelConfigStoreOpenTelemetry collector configuration (port, socket path)
useMetricsStorePer-session token usage and cost metrics from OTel
useProjectStatsStoreAggregated per-project statistics
useDashboardDataStoreCached data for the dashboard view (recent activity, stats)
useClaudeStatusStoreClaude.ai operational status feed
useClaudeUsageStoreClaude API usage counters
useFeedbackStoreIn-app feedback dialog state
useUpdaterStoreAuto-updater state and pending update info
useLicenseStoreLicense / entitlement state for cloud features
useIdeIntegrationStoreIDE integration (Claude Code VS Code extension) connection state
useHookConfigStoreUser-defined hook configurations

Sliced stores. Stores with many fields are split into sub-slices under a dedicated subdirectory (e.g. src/store/magia/, src/store/settings/, src/store/editor/). Each slice exports a partial state and actions, combined into a single create() call in the slice’s index.ts.

Persist middleware. Long-lived client state (settings, onboarding, discovery cache, keybindings, session UI, input drafts) uses Zustand’s persist middleware backed by localStorage. Persisted stores carry a version number and a migrate function to handle schema changes.

No derived state in selectors. Selectors must return stable references. Never return [] or {} literals from a selector — doing so creates a new reference on every render and causes infinite re-render loops. Compute derived values outside the selector or use a separate useMemo.

src/components/
├── app/ AppShell, SplashScreen, WhatsNew, ErrorBoundary
├── auth/ AuthProvider, login/callback screens
├── chat/ Chat input, message list, message renderers
├── dashboard/ Dashboard page and widgets
├── editor/ CodeMirror editor wrapper and panels
├── feedback/ Feedback dialog
├── hub/ Hub/marketplace UI
├── onboarding/ FirstLaunch flow steps
├── session/ Session sidebar, session cards, session header
├── sessions/ Sessions list page
├── settings/ Settings pages (general, editor, terminal, providers, etc.)
├── terminal/ xterm.js wrapper and terminal panel
├── tray/ Tray panel lightweight UI
├── ui/ shadcn/ui primitives (button, dialog, input, etc.)
└── workspace/ Workspace management pages

Page-level components live directly under src/components/<area>/. Shared UI primitives are in src/components/ui/ and are generated/managed by the shadcn CLI.

  • Tailwind v4 — utility-first CSS with JIT.
  • shadcn/ui — component primitives (radix-ui based). The theme uses a Stone base with Rose accent, dark mode, Noto Sans font, and a small border radius.
  • CSS variables — design tokens (colors, radius, spacing) are defined as CSS custom properties in src/styles/globals.css so custom themes can override them.

Every flex child that should not overflow its container needs min-w-0. overflow-hidden alone does not prevent flex items from growing beyond their container.

Unit and integration tests use Vitest. Test files live alongside their source files (e.g. app.test.ts next to app.ts). Store tests typically exercise the store in isolation without a running Tauri backend by mocking invoke.

Run tests:

Terminal window
pnpm test