# How the Persona-Adaptive UI Adjusts Detail Levels for Different User Roles in Understand-Anything

> Learn how Understand-Anything's persona-adaptive UI tailors detail levels for diverse user roles. Discover how it optimizes information display for stakeholders, junior developers, and engineers.

- Repository: [Egonex/Understand-Anything](https://github.com/Egonex-AI/Understand-Anything)
- Tags: how-to-guide
- Published: 2026-06-23

---

**The Understand-Anything dashboard uses a Zustand store to track the current user persona and automatically invalidates layout caches when switching roles, triggering a re-render that filters code graph nodes to show only the detail level appropriate for non-technical stakeholders, junior developers, or experienced engineers.**

The Egonex-AI/Understand-Anything repository implements a sophisticated persona-adaptive UI that dynamically adjusts the complexity of code visualization based on the user's technical expertise. This system leverages a global Zustand state management pattern to ensure that switching between non-technical, junior, and experienced user roles immediately reflects the appropriate level of abstraction in the graph view. Understanding how this detail-level adaptation works is essential for developers extending the dashboard or integrating similar adaptive interfaces.

## The Core Mechanism: Zustand Store and Persona States

The adaptation logic centers on a global Zustand store defined in [`understand-anything-plugin/packages/dashboard/src/store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/understand-anything-plugin/packages/dashboard/src/store.ts).

### Defining the Three Personas

At line 12, the store declares a strict TypeScript union type that constrains the supported roles:

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

```

### State Initialization

The store initializes the `persona` field to `"junior"` by default at line 110:

```typescript
persona: "junior",

```

## How setPersona Triggers UI Adaptation

When a user selects a different role via the persona selector UI, the `setPersona` setter (lines 334-342) performs more than a simple state update. It clears cached layout data to force a complete recalculation of the graph structure:

```typescript
setPersona: (persona) =>
  set({
    persona,
    // Flush caches – layout & container positions depend on which node
    // types are visible for the selected persona.
    containerLayoutCache: new Map(),
    containerSizeMemory: new Map(),
    expandedContainers: new Set(),
    pendingFocusContainer: null,
  }),

```

This cache invalidation ensures that container positions and expanded states are recalculated for the specific node set visible to the chosen persona.

## Detail Level Filtering by User Role

Rendering components consume the `persona` value via the `useDashboardStore` hook and apply distinct filter sets to determine node visibility.

### Non-Technical View

The **non-technical** persona displays only high-level file nodes, hiding classes and functions to provide stakeholders with an architectural overview.

### Junior Developer View

The **junior** persona reveals file and class-level nodes while concealing individual functions, offering intermediate detail suitable for developers learning the codebase.

### Experienced Developer View

The **experienced** persona exposes the complete graph, including functions and lower-level edges, providing full visibility into implementation details.

## Implementing Persona-Aware Components

To switch personas programmatically, components access the store:

```tsx
import { useDashboardStore } from "./store";

function SwitchPersona() {
  const setPersona = useDashboardStore((s) => s.setPersona);
  const current = useDashboardStore((s) => s.persona);

  return (
    <div>
      <p>Current persona: {current}</p>
      <button onClick={() => setPersona("non-technical")}>Non‑Technical</button>
      <button onClick={() => setPersona("junior")}>Junior</button>
      <button onClick={() => setPersona("experienced")}>Experienced</button>
    </div>
  );
}

```

Graph view components filter nodes based on the current persona:

```tsx
import { useDashboardStore } from "./store";

function GraphView() {
  const { persona, nodesById } = useDashboardStore((s) => ({
    persona: s.persona,
    nodesById: s.nodesById,
  }));

  const visibleNodeIds = Object.values(nodesById)
    .filter((node) => {
      if (persona === "non-technical") return node.type === "file";
      if (persona === "junior") return node.type !== "function";
      return true; // experienced
    })
    .map((n) => n.id);

  // Render graph with filtered nodes...
}

```

### Localization Configuration

The UI labels for the persona selector are defined in localization files such as [`understand-anything-plugin/packages/dashboard/src/locales/en.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/understand-anything-plugin/packages/dashboard/src/locales/en.ts):

```typescript
export const en = {
  personaSelector: {
    label: "Persona",
    options: {
      "non-technical": "Non‑technical",
      junior: "Junior",
      experienced: "Experienced",
    },
  },
};

```

## Summary

- The `Persona` type in [`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts) defines three roles: "non-technical", "junior", and "experienced".
- The `setPersona` method invalidates `containerLayoutCache`, `containerSizeMemory`, and `expandedContainers` to ensure clean transitions.
- Rendering logic filters nodes by type based on the current persona value from `useDashboardStore`.
- Locale definitions in [`en.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/en.ts) provide the UI text for the persona selector.

## Frequently Asked Questions

### What are the three user personas supported?

The Understand-Anything dashboard supports "non-technical" for stakeholders, "junior" for early-career developers, and "experienced" for senior engineers who need full code graph visibility.

### How does the UI prevent visual glitches when switching personas?

The `setPersona` implementation resets `containerLayoutCache`, `containerSizeMemory`, and `expandedContainers`, forcing a fresh layout calculation that aligns container positions with the newly filtered node set.

### Where is the persona state stored?

The current persona resides in the global Zustand store defined in [`understand-anything-plugin/packages/dashboard/src/store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/understand-anything-plugin/packages/dashboard/src/store.ts), accessible via the `useDashboardStore` hook.

### Can I extend the persona system to add more roles?

Yes, you can extend the `Persona` type definition in [`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts) and update the filtering logic in graph components to handle additional custom roles, though you must also provide locale entries in files like [`en.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/en.ts) for the UI labels.