Skip to main content

Architecture overview

Fusion Analyst is organized around a small number of clear responsibilities: auth (pluggable providers), state (React Context + hooks), persistence (an ArcGIS Portal Item abstraction), widgets (a schema-driven registry), and UI (shadcn/ui + Tailwind primitives).

The core data model

The app is built around a three-level hierarchy:

  • A WorkspaceConfig is the unit of persistence — one ArcGIS Portal Item per workspace. It holds metadata plus an ordered list of views.
  • A ViewConfig is a tab. It owns a list of widget instances and a grid column count (defaults to 12).
  • A WidgetInstance is one placed widget: a widgetType (registry key), its grid layout, optional config, and optional cross-widget actions.

These types are defined in src/workspaces/types.ts and explained in Workspaces & views.

How the pieces fit together

Key flows:

  • Auth wraps everything. WorkspacesProvider is mounted inside the auth provider so all workspace state is scoped to the signed-in user (user.id).
  • State lives in WorkspacesContext. Components read and mutate workspaces, views, and widgets through the useWorkspaces() hook. Mutations mark the workspace dirty; the user saves explicitly, and an unsaved-changes guard protects context switches.
  • The canvas renders from the registry. ViewCanvas reads each WidgetInstance.widgetType, looks it up in the registry, and mounts the matching component inside a WidgetFrame.
  • Persistence is abstracted. State talks to a WorkspacePersistenceProvider. The active implementation stores workspaces as ArcGIS Portal Items; the auth provider injects the live portal into it.

Backend touchpoint

Some widgets (AI Chat, AI Agents) interact with the Python backend's long-running agent runs over Server-Sent Events. The backend owns the run; the browser attaches to monitor it live and can disconnect and reconnect without killing the agent. That contract is summarized in the repository README and will be documented fully when the api/ docs are added.