# How the Dashboard Implements Persona-Adaptive UI for Different User Roles

> Discover how the Egonex-AI/Understand-Anything dashboard uses persona-adaptive UI with Zustand to tailor features, filter graph nodes, and enable educational overlays for distinct user roles.

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

---

**The dashboard implements persona-adaptive UI by storing a global persona state in a Zustand store and using that value to conditionally render features, filter graph nodes, and toggle educational overlays across the application.**

The **Egonex-AI/Understand-Anything** repository contains a sophisticated dashboard that dynamically adjusts its interface based on three distinct user roles: **non-technical**, **junior**, and **experienced**. This role-based adaptation ensures that non-technical stakeholders see simplified abstractions while experienced developers access full implementation details, all driven by a centralized state management system.

## Core Architecture: The Persona State Store

The foundation of the adaptive UI resides in [`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts), which defines a **Zustand** store managing the global persona state. The store declares a strict `Persona` type union of the three roles and provides a `setPersona` function that handles both state updates and cache invalidation.

According to the source code in [`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts) (lines 12–43), the `setPersona` implementation performs two critical operations:

1. Updates the `persona` value in the store state
2. Clears layout caches including `containerLayoutCache` and `expandedContainers` to force recomputation of container sizes and positions

This cache clearing ensures that UI elements dependent on the previous persona's layout constraints are recalculated immediately, preventing visual artifacts during role transitions.

## Role Selection Interface

User role switching occurs through the [`PersonaSelector.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/PersonaSelector.tsx) component (lines 5–38), which renders three distinct buttons corresponding to the available personas. When a user clicks a role button, the component invokes `setPersona` from the dashboard store, triggering a full UI re-render with the new role applied.

The selector component consumes the store using the standard Zustand pattern:

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

function PersonaSelector() {
  const { persona, setPersona } = useDashboardStore((s) => ({
    persona: s.persona,
    setPersona: s.setPersona
  }));
  
  return (
    <div className="persona-controls">
      <button 
        onClick={() => setPersona("non-technical")}
        className={persona === "non-technical" ? "active" : ""}
      >
        Non-Technical
      </button>
      <button onClick={() => setPersona("junior")}>Junior</button>
      <button onClick={() => setPersona("experienced")}>Experienced</button>
    </div>
  );
}

```

## Conditional Rendering Based on User Roles

Throughout the dashboard, components access the current persona via `useDashboardStore((s) => s.persona)` and apply conditional logic to determine feature visibility. This pattern creates a layered interface where complexity scales with user expertise.

### Filtering Graph Complexity for Non-Technical Users

In [`GraphView.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/GraphView.tsx) (lines 372–444), the rendering engine consults the persona value to filter implementation details. When `persona === "non-technical"`, the component returns early for function and class sub-nodes, hiding internal implementation details from stakeholders who only need high-level architectural views.

The filtering logic implements an explicit guard clause:

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

function GraphNode({ node }: { node: GraphNode }) {
  const persona = useDashboardStore((s) => s.persona);
  
  // Non-technical users never see function/class internals
  if (persona === "non-technical" && subFileTypes.has(node.type)) {
    return null;
  }
  
  return <NodeRenderer node={node} />;
}

```

### Enabling Learn Mode for Junior Developers

Both [`MobileLayout.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/MobileLayout.tsx) (lines 42–66) and [`App.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/App.tsx) (lines 234–393) treat the **junior** persona as a specialized "learn mode." When the persona matches `"junior"`, the interface activates educational features including the Learn panel, onboarding overlays, and contextual help tooltips.

This implementation allows junior developers to access guided tours and explanatory content while experienced users work with a streamlined interface free from instructional overhead.

### Persona-Aware Export Functionality

The [`ExportMenu.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ExportMenu.tsx) component (lines 29–189) applies persona-specific filtering when serializing graph data for download. The export logic checks the current persona and applies node filters accordingly:

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

function exportGraph() {
  const { graph, persona } = useDashboardStore.getState();
  let filtered = graph.nodes;
  
  if (persona === "non-technical") {
    filtered = filtered.filter((n) => !subFileTypes.has(n.type));
  }
  
  // Serialize filtered nodes and trigger download
  const exportData = JSON.stringify({ ...graph, nodes: filtered });
  downloadFile(exportData, `graph-${persona}.json`);
}

```

This ensures that exported diagrams match the visual complexity level shown in the dashboard interface, maintaining consistency between the interactive view and static exports.

## Cache Invalidation on Role Switch

The `setPersona` function in [`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts) (lines 34–42) implements aggressive cache invalidation to support clean UI transitions. When the persona changes, the function clears `containerLayoutCache`, `expandedContainers`, and other layout-dependent state objects.

This invalidation guarantees that container sizes, node positions, and expand/collapse states do not persist incorrectly between personas. For example, a graph section expanded by an experienced user will not remain artificially expanded when a non-technical user switches roles, as the layout constraints must be recalculated for the simplified view.

## Summary

- The dashboard uses a **Zustand store** ([`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts)) to manage global persona state across three roles: non-technical, junior, and experienced
- **PersonaSelector.tsx** provides the UI controls for role switching, invoking `setPersona` to trigger global state updates
- **GraphView.tsx** filters implementation details for non-technical users by returning early on sub-file type nodes
- **MobileLayout.tsx** and **App.tsx** activate "learn mode" educational features specifically for the junior persona
- **ExportMenu.tsx** applies persona-specific filters to ensure exported data matches the UI complexity level
- Cache invalidation in `setPersona` clears layout caches to prevent visual artifacts during role transitions

## Frequently Asked Questions

### What are the three user personas defined in the dashboard?

The dashboard defines three personas in [`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts): **non-technical** (for stakeholders needing high-level abstractions), **junior** (for developers requiring educational guidance and learn mode), and **experienced** (for developers needing full implementation details). Each persona is stored as a string literal in the `Persona` type union and drives conditional rendering logic throughout the application.

### How does the dashboard handle state transitions when switching personas?

When switching personas via `setPersona` in [`store.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/store.ts), the dashboard clears cached layout data including `containerLayoutCache` and `expandedContainers` (lines 34–42). This cache invalidation forces the UI to recompute container sizes and positions based on the new role's requirements, ensuring that layout artifacts from the previous persona do not persist.

### Which components are affected by the persona setting?

The persona setting affects [`GraphView.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/GraphView.tsx) (node filtering), [`MobileLayout.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/MobileLayout.tsx) and [`App.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/App.tsx) (learn mode toggles), and [`ExportMenu.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ExportMenu.tsx) (export filtering). Additionally, [`PersonaSelector.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/PersonaSelector.tsx) provides the interface for changing roles, while all components access the shared Zustand store via `useDashboardStore((s) => s.persona)`.

### How does the export functionality adapt to different user roles?

The [`ExportMenu.tsx`](https://github.com/Egonex-AI/Understand-Anything/blob/main/ExportMenu.tsx) component reads the current persona from the store and applies filters before serializing graph data. For non-technical users, it strips out function and class sub-nodes using the same `subFileTypes` filter applied in the visual graph, ensuring that exported diagrams match the simplified UI view rather than exposing implementation details.