How the Persona-Adaptive UI Adjusts Detail Levels in Understand-Anything

The Understand-Anything dashboard adapts its information density by storing the active persona in a global Zustand store and using that state to drive both sidebar layout decisions and graph node filtering, instantly re-rendering when the persona changes.

The Understand-Anything repository implements a sophisticated persona-adaptive UI that dynamically adjusts detail levels to match three distinct user types: non-technical stakeholders, junior developers, and experienced engineers. This system ensures that each user sees only the complexity relevant to their expertise, from high-level overviews to deep technical inspections.

Global State Management with Zustand

The foundation of the persona-adaptive system lives in packages/dashboard/src/store.ts, which defines the Persona type and manages the global state.

export type Persona = "non-technical" | "junior" | "experienced";

The store initializes with "junior" as the default value and exposes a setPersona method that performs critical cache cleanup:

persona: "junior",
setPersona: (persona) => set({
  persona,
  // persona changes filter node types → clear caches
  containerLayoutCache: new Map(),
  containerSizeMemory: new Map(),
  expandedContainers: new Set(),
  pendingFocusContainer: null,
}),

When setPersona is invoked, it updates the persona value and simultaneously clears the containerLayoutCache, containerSizeMemory, and expandedContainers collections. This ensures that layout calculations are recomputed for the new information density rather than recycled from cached positions.

Persona Selection Interface

Users switch personas through packages/dashboard/src/components/PersonaSelector.tsx, which renders three toggle buttons mapped to the persona types:

const personas = [
  { id: "non-technical", label: t.personaSelector.overview, … },
  { id: "junior",        label: t.personaSelector.learn,   … },
  { id: "experienced",   label: t.personaSelector.deepDive, … },
];
…
<button onClick={() => setPersona(p.id)} …>{p.label}</button>

Clicking a button calls setPersona with the corresponding ID, triggering the global state update and subsequent UI reconfiguration.

Layout Adaptations Based on Persona

The main App component in packages/dashboard/src/App.tsx reads the current persona to determine which sidebar panels to render. It calculates a boolean flag that controls the educational interface:

const isLearnMode = tourActive || persona === "junior";
…
{isLearnMode && <LearnPanel />}
{!selectedNodeId && !isLearnMode && <ProjectOverview />}

When the persona is junior, the LearnPanel appears to provide explanatory context and guided learning. For non-technical and experienced users, the interface omits this educational layer and displays only the ProjectOverview, streamlining the workspace for direct data consumption.

Dynamic Graph Filtering

The graph visualization adapts its complexity in packages/dashboard/src/components/GraphView.tsx by filtering node types before rendering. The filtering logic specifically targets sub-file granularities for non-technical users:

let filteredGraphNodes = graph.nodes.filter((n) => {
  if (!expandedLayerNodeIds.has(n.id)) return false;
  if (!allVisibleTypes.has(n.type)) return false;
  if (persona === "non-technical" && subFileTypes.has(n.type)) return false;
  return true;
});

This implementation removes function and class nodes from the visualization when the non-technical persona is active, displaying only high-level file and module nodes. The junior and experienced personas retain full graph visibility, allowing inspection of all node types including low-level implementation details.

Instant UI Reactions and Cache Invalidation

The persona-adaptive UI reacts instantly because components subscribe to the Zustand store via useDashboardStore. When setPersona executes:

  • The persona value updates in the global store
  • Layout caches are cleared (containerLayoutCache, containerSizeMemory)
  • App.tsx re-renders to swap sidebar panels based on the isLearnMode calculation
  • GraphView.tsx re-runs its filtering memo with the new persona value
  • The graph layout recomputes due to cleared caches, ensuring nodes position correctly for the new filtered set

This coordinated invalidation prevents stale layout data from persisting across persona switches, maintaining visual consistency as the detail level changes.

Programmatic Persona Control

Developers can interact with the persona system directly through the store API:

import { useDashboardStore } from "./store";

// Switch to the non-technical overview
useDashboardStore.getState().setPersona("non-technical");

To extend the system with a new persona (for example, "admin"), modify three locations:

  1. Extend the type in store.ts:

    export type Persona = "non-technical" | "junior" | "experienced" | "admin";
  2. Add the selector button in PersonaSelector.tsx with the new ID and localized label.

  3. Implement filtering rules in GraphView.tsx to define which node types are visible for the new persona.

Because all components read from the same centralized store, the UI automatically propagates the new persona state without additional wiring.

Summary

  • The persona-adaptive UI uses a Zustand store in store.ts to maintain the active persona state across the Understand-Anything dashboard.
  • Three personas—non-technical, junior, and experienced—control both sidebar content and graph complexity.
  • The setPersona method clears layout caches to force re-rendering and prevent stale positioning when detail levels change.
  • Non-technical users see filtered graphs hiding function and class nodes, while junior users receive the LearnPanel educational interface.
  • Experienced users view the full unfiltered graph with minimal UI chrome for maximum data density.

Frequently Asked Questions

What are the three personas available in Understand-Anything?

The system supports three personas defined in store.ts: non-technical for stakeholders needing high-level overviews, junior for developers learning the codebase who need educational context, and experienced for senior engineers requiring full technical detail without instructional overlays.

How does changing the persona affect the graph visualization?

When the persona changes to non-technical, GraphView.tsx filters out sub-file node types including function and class nodes, showing only files and modules. The junior and experienced personas display the complete node hierarchy, with the difference being that junior mode includes the LearnPanel sidebar while experienced mode prioritizes screen real estate for the graph itself.

Where is the persona state stored and how is it accessed?

The persona state resides in the global Zustand store defined in packages/dashboard/src/store.ts. Components access it through the useDashboardStore hook, reading the persona property and invoking setPersona to trigger updates. This centralized approach ensures all UI elements react synchronously to persona changes.

Can I add custom personas to the Understand-Anything dashboard?

Yes, you can extend the system by adding new values to the Persona type in store.ts, creating corresponding buttons in PersonaSelector.tsx, and implementing custom filtering logic in GraphView.tsx. The modular architecture allows new personas to integrate seamlessly without modifying existing component logic beyond these three files.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →