# Architecture Overview ## 1. Executive Summary Zui is a node-based visual editor for composing configs, templates, variables, and AI-generated content. The frontend is a React 18 SPA backed by a thin Express API for AI agent calls. All graph data is persisted in `localStorage`; the backend is stateless. --- ## 2. Technology Stack | Layer | Technology | | --- | --- | | Frontend framework | React 18, TypeScript (strict), Vite 7 | | Graph canvas | `@xyflow/react` v12 (React Flow) | | State management | Zustand 5 (command/reducer pattern) | | Styling | Tailwind CSS + Shadcn UI (`@radix-ui/*`) | | Rich text | BlockNote 0.36 with custom blocks | | Templating | Nunjucks | | Graph traversal | `graphology` + `graphology-traversal` | | Routing | React Router v6 | | Backend | Node.js 20+, TypeScript, Express 4 | | AI SDK | Vercel AI SDK v4 + `@ai-sdk/openai` | | Testing | Vitest, React Testing Library | --- ## 3. Project Structure ```text frontend/src/ ├── main.tsx # Entry: registers node types & config types, mounts app ├── app/ │ ├── canvas/ # CanvasPage, canvasStore (Zustand), canvasStore.test.ts │ ├── kosmos/ # KosmosPage, sidebar, AI settings, KosmosContext │ └── recollections/ │ ├── RecollectionsPage # Workspace list │ ├── RecollectionLayout # Shared layout (sidebar + outlet) │ ├── flux/ # Flux view (graph canvas) │ ├── logos/ # Logos view (BlockNote rich text) │ └── katalogos/ # Katalogos view (artifact gallery) ├── components/ │ ├── graph/ # AnimatedEdge, BaseNode, handles, keyboard shortcuts │ ├── nodes/ # One folder per node type │ └── ui/ # Shadcn primitives ├── hooks/ # useGraphStateWithHistory, useResizeHeight, … └── lib/ └── graph/ ├── nodeRegistry.ts # Mutable plugin registry ├── registerBuiltinNodes.tsx ├── nodeTypeBuilder.ts # Fluent builder for node descriptors ├── configTypes.ts # Output type registry (plantuml, markdown, wireframe) ├── rendering.ts # 3-step rendering pipeline contract ├── state.ts # Graph state types └── canvasStore/ # Reducer + selectors backend/src/ ├── index.ts # Express app, CORS, routes, error handler ├── routes/agentRoutes.ts # POST /api/agent, POST /api/agent/stream ├── services/agentService.ts # LLM call logic (Vercel AI SDK) ├── repositories/cacheRepository.ts ├── models/index.ts └── middleware/rateLimiter.ts ``` --- ## 4. Key Architectural Patterns ### 4.1 Command / Reducer Store (canvasStore) The Zustand canvas store uses a pure reducer (`canvasStoreReducer`) with a discriminated union of `CanvasCommand` types. All mutations go through `dispatch(command)`. In dev mode every command is logged to the console. The store has three slices: - **`graph`** — nodes and edges (the React Flow state) - **`path`** — trigger pulse for edge animation - **`ui`** — renaming state, fullscreen node, pending connection ### 4.2 Delta-based Undo / Redo `useGraphStateWithHistory` computes *inverse deltas* (only the nodes/edges that changed) rather than snapshotting the full graph. Maximum 100 history entries. Drag operations commit a pre-drag snapshot on `onNodeDragStop`. ### 4.3 Node Plugin Registry Node types are registered via a mutable registry in `nodeRegistry.ts`. The built-ins are registered at app init from `registerBuiltinNodes.tsx`. Adding a new node type requires: 1. Implement a React component for the node. 2. Create a descriptor using `NodeTypeBuilder`. 3. Call `registerNodeType(descriptor)` — no edits to core code. ### 4.4 Fluent Builder for Node Descriptors `NodeTypeBuilder` provides a type-safe method-chaining API (`idPrefix`, `withInputOutput`, `classification`, `allowedSourceTypes`, `help`, `menu`, `withFullscreen`, `sourceRenderingLogic`, …). Required fields are validated at `.build()`. ### 4.5 Three-Step Rendering Pipeline Defined as an explicit contract in `rendering.ts`: 1. **Resolve** — source node (Config/Agent) produces `{ resolved, outputTypeId, reasoning? }` 2. **Render** — output type handler converts the resolved string (PlantUML → Kroki SVG, Markdown → HTML, Wireframe → SVG) 3. **Display** — the Rendering node shows an image viewport or scrollable HTML ### 4.6 Node Classification System Four metaphorical classes drive the create menu grouping: | Class | Node type | Metaphor | | --- | --- | --- | | `psyche` | Variable | source / input | | `physis` | Data (CSV) | physical data | | `pneuma` | Config / Render | transformation | | `archon` | Agent | AI / LLM | ### 4.7 Recollections (Workspaces) Each workspace (recollection) is stored in `localStorage`: | Key | Content | | --- | --- | | `zui_platform_recollections` | Metadata index (id, name, icon, timestamps) | | `zui_graph_` | Flux graph (nodes + edges) | | `zui_logos_` | BlockNote rich text document | | `zui_render_cache_` | Rendered artifact cache | Legacy key prefix `emanations` is migrated to `recollections` on first load. ### 4.8 User-configurable AI Connection `KosmosContext` persists `aiConnection` (provider, baseURL, model, apiKey) in `localStorage` under `zui_ai_connection`. The Agent node forwards this to the backend with each request, so users can switch between OpenAI and local LLMs (LM Studio, Ollama) from the UI without env variable changes. ### 4.9 Diagram Rendering via Kroki PlantUML diagrams are rendered by proxying to `https://kroki.io` via `/api/kroki/plantuml/svg`. This proxy is configured in both the Vite dev server and Nginx production config. Timeout: 15 seconds. --- ## 5. Data Flow ```text User interaction → dispatch(CanvasCommand) [canvasStore reducer] → Zustand state update [graph / path / ui slices] → React re-render [React Flow nodes/edges] Rendering node triggered → Resolve source node [Config/Agent → resolved string] → Render output type [plantuml/markdown/wireframe] → Kroki proxy (PlantUML) [GET /api/kroki/plantuml/svg] → Agent backend (AI) [POST /api/agent or /api/agent/stream] → Display artifact [image / HTML / SVG viewport] Agent node (streaming) → POST /api/agent/stream [Express → agentService] → Vercel AI SDK streams SSE [backend → frontend] → useStreamingContent hook consumes [updates node data] ``` --- ## 6. Backend Architecture The backend is intentionally thin and stateless. It has three responsibilities: 1. **Proxy AI calls** — forwards prompts to the configured LLM (OpenAI or OpenAI-compatible). 2. **Stream responses** — `POST /api/agent/stream` uses `pipeTextStreamToResponse` from the Vercel AI SDK. 3. **Health check** — `GET /health` for Docker/orchestration readiness probes. The `InMemoryCache` and `rateLimiter` middleware are implemented but not yet wired into the agent routes. --- ## 7. Contribution Workflow 1. Fork the repository and clone locally. 2. Install dependencies: `cd frontend && npm install` and `cd backend && npm install`. 3. Run the dev servers (see README). 4. Create a feature branch: `git checkout -b feat/your-feature`. 5. Follow the Coding Standards (see [CONTRIBUTING.md](CONTRIBUTING.md)). 6. Submit a Pull Request with a descriptive title, linked issue(s), updated tests, and documentation changes if relevant. ### PR Review Checklist - [ ] Readability: clear naming, minimal nesting - [ ] TypeScript: no `any`, strict types throughout - [ ] Performance: no unnecessary re-renders, proper memoization - [ ] Accessibility: semantic HTML, ARIA attributes where needed - [ ] Security: no hardcoded secrets, input validated at boundaries --- ## 8. Coding Standards - **TypeScript**: strict mode (`strict`, `noImplicitAny`, `noUnusedLocals`). - **Naming**: PascalCase for components, camelCase for functions/variables, UPPER_SNAKE_CASE for constants. - **File structure**: domain-grouped under `src/app//` and `src/components//`. - **Formatting**: Prettier via `frontend/prettier.config.cjs`; line length ≤ 120. - **Comments**: JSDoc for public APIs; inline only where logic is non-obvious. --- ## 9. Quick Reference for AI Agents | Topic | Location | | --- | --- | | Entry point | `frontend/src/main.tsx` | | Canvas store | `frontend/src/app/canvas/canvasStore.ts` | | Store reducer | `frontend/src/app/canvas/canvasStoreReducer.ts` | | Node registry | `frontend/src/lib/graph/nodeRegistry.ts` | | Node builder | `frontend/src/lib/graph/nodeTypeBuilder.ts` | | Rendering pipeline | `frontend/src/lib/graph/rendering.ts` | | Built-in node registration | `frontend/src/lib/graph/registerBuiltinNodes.tsx` | | AI settings context | `frontend/src/app/kosmos/KosmosContext.tsx` | | Backend entry | `backend/src/index.ts` | | Agent service | `backend/src/services/agentService.ts` | *This document is a living reference; update it when architectural decisions change.*