# How the Egonex-AI Dashboard Implements Persona-Adaptive UI: A Technical Deep Dive

> Explore the technical implementation of Egonex-AI's persona-adaptive UI. Learn how its Zustand state machine dynamically adjusts complexity for non-technical, junior, and experienced users.

- Repository: [Egonex/Understand-Anything](https://github.com/Egonex-AI/Understand-Anything)
- Tags: deep-dive
- Published: 2026-06-09

---

**The Egonex-AI dashboard implements persona-adaptive UI through a centralized Zustand state machine that supports three distinct user personas—non-technical, junior, and experienced—dynamically adjusting graph complexity, export granularity, and interface density based on the selected expertise level.**

The Egonex-AI/Understand-Anything repository uses a persona-driven architecture to tailor its visualization dashboard to different technical audiences. Rather than maintaining separate applications for beginners versus advanced users, the codebase employs a single adaptive interface that filters data and adjusts layouts through a shared state management layer.

## Core Architecture: The Persona State Machine

The foundation of the persona-adaptive UI lives 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), where a Zustand store defines the allowed persona values and manages state transitions.

### Persona Type Definition

The system recognizes three strict persona types enforced through TypeScript:

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

```

The store initializes with a default persona of `"junior"` (line 10), positioning the dashboard in "learn mode" for new users while allowing escalation to advanced views.

### State Management and Cache Invalidation

The `setPersona` action (lines 34-41) performs more than a simple state update. It clears multiple layout caches to ensure the UI redraws correctly when node visibility changes:

```typescript
setPersona: (persona) =>
  set({
    persona,
    // Reset caches that depend on node-type visibility
    containerLayoutCache: new Map(),
    containerSizeMemory: new Map(),
    expandedContainers: new Set(),
    pendingFocusContainer: null,
  }),

```

This cache invalidation prevents stale positioning data from leaking between personas, as each mode displays different subsets of graph nodes.

## The Persona Selector Component

User-facing persona switching occurs through the **PersonaSelector** component in [`src/components/PersonaSelector.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/src/components/PersonaSelector.tsx). This widget renders three toggle buttons mapping to the defined personas, each with localized labels and tooltips.

```tsx
export default function PersonaSelector() {
  const persona = useDashboardStore((s) => s.persona);
  const setPersona = useDashboardStore((s) => s.setPersona);
  const { t } = useI18n();

  const personas = [
    { id: "non-technical", label: t.personaSelector.overview, description: t.personaSelector.overviewDesc },
    { id: "junior",       label: t.personaSelector.learn,    description: t.personaSelector.learnDesc },
    { id: "experienced",  label: t.personaSelector.deepDive, description: t.personaSelector.deepDiveDesc },
  ];

  return (
    <div className="flex items-center gap-1 bg-elevated rounded-lg p-0.5">
      {personas.map((p) => (
        <button
          key={p.id}
          onClick={() => setPersona(p.id)}
          title={p.description}
          className={`px-2.5 py-1 rounded text-[11px] font-medium transition-colors ${
            persona === p.id ? "bg-accent/20 text-accent" : "text-text-muted hover:text-text-secondary hover:bg-surface"
          }`}
        >
          {p.label}
        </button>
      ))}
    </div>
  );
}

```

The selector embeds across multiple layout surfaces including [`App.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/App.tsx), the mobile drawer ([`MobileDrawer.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/MobileDrawer.tsx)), and various sidebars, ensuring persistent access regardless of viewport size.

## Persona-Driven Rendering Logic

Components throughout the dashboard consume the `persona` state to conditionally render interface elements and filter data. This creates distinct user experiences without duplicating component logic.

### Graph Filtering by Expertise Level

In [`src/components/GraphView.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/src/components/GraphView.tsx) (line 439), the **non-technical** persona triggers aggressive node filtering to hide implementation details:

```tsx
const persona = useDashboardStore((s) => s.persona);
...
if (persona === "non-technical" && subFileTypes.has(n.type)) return false;

```

This conditional removes functions, classes, and other sub-file entities from the visualization, presenting high-level architectural overviews rather than implementation minutiae.

### Export Behavior Adaptation

The **ExportMenu** component ([`src/components/ExportMenu.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/src/components/ExportMenu.tsx), lines 186-190) applies similar filtering when generating exportable data. When a non-technical user exports the graph, the system strips function and class nodes to produce stakeholder-friendly documentation.

### Layout Mode Detection

Higher-level layout components reference the persona to determine global UI behavior. In [`src/App.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/src/App.tsx) (lines 232-393), the dashboard computes an `isLearnMode` boolean true for `junior` personas or when guided tours are active. Meanwhile, [`MobileLayout.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/MobileLayout.tsx) (line 66) specifically treats the `junior` persona as a distinct learning mode for mobile interfaces.

## Programmatic Persona Control

While the toggle UI serves standard interactions, the store architecture supports imperative persona changes for automated workflows or deep-linking:

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

// Immediately switch to experienced view
useDashboardStore.getState().setPersona("experienced");

```

Conditional rendering based on persona follows standard React patterns with Zustand selectors:

```tsx
const persona = useDashboardStore((s) => s.persona);

return (
  <>
    {persona === "non-technical" && <NonTechnicalHelpBanner />}
    {persona !== "non-technical" && <AdvancedControls />}
  </>
);

```

Manual node filtering outside the standard graph view requires checking both the node type and current persona:

```ts
const nodes = useDashboardStore((s) => s.graph?.nodes ?? []);
const persona = useDashboardStore((s) => s.persona);
const visibleNodes = nodes.filter((n) => {
  if (persona === "non-technical" && ["function", "class"].includes(n.type)) {
    return false;
  }
  return true;
});

```

## Summary

- **Centralized state**: The `Persona` type and `setPersona` action in [`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts) provide the single source of truth for user expertise levels.
- **Three distinct modes**: Non-technical (overview), junior (learn), and experienced (deep dive) personas control feature visibility throughout the application.
- **Automatic cache clearing**: Switching personas triggers cache invalidation for layout and container states, ensuring accurate visual positioning.
- **Component-level filtering**: GraphView and ExportMenu filter nodes differently per persona, while App.tsx and MobileLayout.tsx adjust macro-level UI modes.
- **Persistent controls**: The PersonaSelector component surfaces these options consistently across desktop and mobile layouts.

## Frequently Asked Questions

### What are the three user personas supported by the Egonex-AI dashboard?

The dashboard supports **non-technical**, **junior**, and **experienced** personas. The non-technical mode hides implementation details like functions and classes, junior mode enables learning features and guided tours, and experienced mode reveals the full graph complexity and advanced export options.

### How does the dashboard prevent layout bugs when switching personas?

The `setPersona` action in [`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts) clears four critical caches (`containerLayoutCache`, `containerSizeMemory`, `expandedContainers`, and `pendingFocusContainer`) during the state transition. This ensures layout calculations recompute based on the visible node set for the new persona rather than recycling positions from the previous view.

### Can applications switch personas programmatically without user interaction?

Yes. The Zustand store exposes `setPersona` directly on the store state, allowing imperative updates via `useDashboardStore.getState().setPersona("experienced")`. This enables deep-linking to specific personas or automated context switching based on user authentication or project requirements.

### Which components implement persona-specific filtering logic?

The primary filtering occurs in [`GraphView.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/GraphView.tsx) for visual node hiding and [`ExportMenu.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ExportMenu.tsx) for data export filtering. Additionally, [`App.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/App.tsx) uses the persona to determine `isLearnMode` status, while [`MobileLayout.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/MobileLayout.tsx) applies persona-aware responsive behaviors for mobile learning modes.