# VIEW-001-REVISION: Project Topology Map Redesign **Status:** πŸ”΄ REVISION REQUIRED **Original Task:** VIEW-001-topology-map **Priority:** HIGH **Estimate:** 2-3 days --- ## Summary The initial VIEW-001 implementation does not meet the design goals. It renders all 123 components as individual nodes in a flat horizontal layout, creating an unreadable mess of spaghetti connections. This revision changes the fundamental approach from "show every component" to "show folder-level architecture with drill-down." ### Screenshots of Current (Broken) Implementation The current implementation shows: - All components spread horizontally across 3-4 rows - Names truncated to uselessness ("/#Directus/Di...") - No semantic grouping (pages vs shared vs utilities) - No visual differentiation between component types - Connections that obscure rather than clarify relationships - Essentially unusable at scale (123 components, 68 orphans) --- ## The Problem The original spec envisioned a layered architectural diagram: ``` πŸ“„ PAGES (top) ↓ 🧩 SHARED (middle) ↓ πŸ”§ UTILITIES (bottom) ``` What was built instead: a flat force-directed/dagre graph treating all components identically, which breaks down completely at scale. **Root cause:** The implementation tried to show component-level detail at the overview level. A project with 5-10 components might work, but real projects have 100+ components organized into folders. --- ## The Solution: Folder-First Architecture ### Level 1: Folder Overview (Default View) Show **folders** as nodes, not components: ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ πŸ“„ Pages │──────────────┬──────────────┐ β”‚ β”‚ β”‚ (5) β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β–Ό β–Ό β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ #Directus β”‚ β”‚ #Swapcard β”‚ β”‚ β”‚ β”‚ β”‚ (45) β”‚ β”‚ (8) β”‚ β”‚ β”‚ β–Ό β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ #Forms │────────────── β”‚ β”‚ β”‚ β”‚ (15) β”‚ β–Ό β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ #UI β”‚β—„β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ └───────────►│ (32) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œ ─ ─ ─ ─ ─ ─ ┐ β”‚ β”‚ β”‚ #Global β”‚ β”‚ ⚠️ Orphans β”‚ β”‚ β”‚ β”‚ (18) β”‚ β”‚ (68) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”” ─ ─ ─ ─ ─ ─ β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` This transforms 123 unreadable nodes into ~6 readable nodes. ### Level 2: Expanded Folder View (Drill-Down) Double-click a folder to see its components: ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ← Back to Overview #Directus (45) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Auth │◄────│ Query │────►│ List β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Γ—12 β”‚ β”‚ Γ—28 β”‚ β”‚ Γ—15 β”‚ β”‚#Globalβ”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚(mini) β”‚ β”‚ β”‚ β–² β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β–Ό β–² β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ Error │◄────│Mutation │────►│ Item β”‚β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ Γ—3 β”‚ β”‚ Γ—18 β”‚ β”‚ Γ—22 β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ ─────────────────────────────────────────── β”‚ β”‚ External connections from: β”‚ β”‚ [Pages 34Γ—] [Forms 22Γ—] β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ### Level 3: Handoff to X-Ray Double-click a component β†’ Opens X-Ray view for that component's internals. **Topology shows relationships. X-Ray shows internals. They complement each other.** --- ## Visual Design Requirements ### Color Palette by Folder Type | Folder Type | Background | Border | Use Case | |-------------|------------|--------|----------| | Pages | `#1E3A8A` | `#3B82F6` | Entry points, routes | | Feature | `#581C87` | `#A855F7` | Feature-specific folders (#Forms, etc.) | | Integration | `#064E3B` | `#10B981` | External services (#Directus, #Swapcard) | | UI | `#164E63` | `#06B6D4` | Shared UI components | | Utility | `#374151` | `#6B7280` | Foundation (#Global) | | Orphan | `#422006` | `#CA8A04` | Unused components (dashed border) | ### Node Styling ```scss // Folder node (Level 1) .folder-node { min-width: 100px; padding: 12px 16px; border-radius: 8px; border-width: 2px; &.selected { border-width: 3px; box-shadow: 0 0 20px rgba(color, 0.3); } .folder-name { font-weight: 600; font-size: 14px; } .component-count { font-size: 12px; opacity: 0.7; } } // Component node (Level 2) .component-node { min-width: 80px; padding: 8px 12px; border-radius: 6px; border-width: 1px; .component-name { font-size: 12px; font-weight: 500; } .usage-count { font-size: 10px; color: #6EE7B7; // green for "used by X" } } ``` ### Connection Styling ```scss .connection-line { stroke: #4B5563; stroke-width: 1px; opacity: 0.5; // Thickness based on connection count &.connections-10 { stroke-width: 2px; } &.connections-20 { stroke-width: 3px; } &.connections-30 { stroke-width: 4px; } // Opacity based on connection count &.high-traffic { opacity: 0.7; } } ``` --- ## Implementation Phases ### Phase 1: Data Restructuring (0.5 days) Convert component-level graph to folder-level graph. **Tasks:** 1. Create `buildFolderGraph()` function that aggregates components by folder 2. Calculate inter-folder connection counts 3. Identify folder types (page, integration, ui, utility) from naming conventions 4. Keep component-level data available for drill-down **New Types:** ```typescript interface FolderNode { id: string; name: string; path: string; type: 'page' | 'feature' | 'integration' | 'ui' | 'utility' | 'orphan'; componentCount: number; components: ComponentModel[]; } interface FolderConnection { from: string; // folder id to: string; // folder id count: number; // number of component-to-component connections componentPairs: Array<{ from: string; to: string }>; } interface FolderGraph { folders: FolderNode[]; connections: FolderConnection[]; orphanComponents: ComponentModel[]; } ``` **Verification:** - [ ] Folders correctly identified from component paths - [ ] Connection counts accurate - [ ] Orphans isolated correctly ### Phase 2: Level 1 - Folder Overview (1 day) Replace current implementation with folder-level view. **Tasks:** 1. Render folder nodes with correct colors/styling 2. Use simple hierarchical layout (pages top, utilities bottom) 3. Draw connections with thickness based on count 4. Implement click-to-select (shows detail panel) 5. Implement double-click-to-expand 6. Add orphan indicator (dashed box, separate from main graph) **Layout Strategy:** Instead of dagre's automatic layout, use a **tiered layout**: - Tier 1 (y=0): Pages - Tier 2 (y=1): Features that pages use - Tier 3 (y=2): Shared libraries (Directus, UI) - Tier 4 (y=3): Utilities (Global) - Separate: Orphans (bottom-left, disconnected) ```typescript function assignTier(folder: FolderNode, connections: FolderConnection[]): number { if (folder.type === 'page') return 0; if (folder.type === 'orphan') return -1; // special handling // Calculate based on what uses this folder const usedBy = connections.filter(c => c.to === folder.id); const usesPages = usedBy.some(c => getFolderById(c.from).type === 'page'); if (usesPages && folder.type === 'feature') return 1; if (folder.type === 'utility') return 3; return 2; // default: shared layer } ``` **Verification:** - [ ] Folders display with correct colors - [ ] Layout is tiered (pages at top) - [ ] Connection thickness reflects count - [ ] Orphans shown separately - [ ] Click shows detail panel - [ ] Double-click triggers drill-down ### Phase 3: Level 2 - Expanded Folder (1 day) Implement drill-down into folder. **Tasks:** 1. Create expanded view showing folder's components 2. Show internal connections between components 3. Show external connections from other folders (collapsed, at edges) 4. Click component β†’ detail panel with "Open in X-Ray" button 5. Double-click component β†’ navigate to X-Ray 6. "Back" button returns to folder overview 7. Breadcrumb trail (App > #Directus > ComponentName) **Verification:** - [ ] Components render within expanded folder boundary - [ ] Internal connections visible - [ ] External folders shown as mini-nodes at edges - [ ] External connections drawn from mini-nodes - [ ] "Open in X-Ray" button works - [ ] Back navigation works - [ ] Breadcrumb updates correctly ### Phase 4: Detail Panels (0.5 days) Side panel showing details of selected item. **Folder Detail Panel:** - Folder name and type - Component count - Incoming connections (which folders use this, with counts) - Outgoing connections (which folders this uses, with counts) - "Expand" button **Component Detail Panel:** - Component name - Usage count (how many places use this) - Dependencies (what this uses) - "Open in X-Ray" button - "Go to Canvas" button **Verification:** - [ ] Panels appear on selection - [ ] Data is accurate - [ ] Buttons navigate correctly ### Phase 5: Polish & Edge Cases (0.5 days) **Tasks:** 1. Handle projects with no folder structure (flat component list) 2. Handle very large folders (>50 components) - consider sub-grouping or pagination 3. Add zoom controls that actually work 4. Add "Fit to view" that frames the content properly 5. Smooth animations for expand/collapse transitions 6. Keyboard navigation (Escape to go back, Enter to expand) **Verification:** - [ ] Flat projects handled gracefully - [ ] Large folders don't overwhelm - [ ] Zoom/pan works smoothly - [ ] Animations feel polished --- ## Files to Modify ### Refactor Existing ``` packages/noodl-editor/src/editor/src/views/AnalysisPanel/TopologyMapView/ β”œβ”€β”€ TopologyMapView.tsx # Complete rewrite for folder-first approach β”œβ”€β”€ TopologyMapView.module.scss # New color system, node styles β”œβ”€β”€ useTopologyGraph.ts # Replace with useFolderGraph.ts β”œβ”€β”€ TopologyNode.tsx # Rename to FolderNode.tsx, new styling └── TopologyEdge.tsx # Update for variable thickness ``` ### Create New ``` packages/noodl-editor/src/editor/src/views/AnalysisPanel/TopologyMapView/ β”œβ”€β”€ useFolderGraph.ts # New hook for folder-level data β”œβ”€β”€ FolderNode.tsx # Folder node component β”œβ”€β”€ ComponentNode.tsx # Component node (for drill-down) β”œβ”€β”€ FolderDetailPanel.tsx # Side panel for folder details β”œβ”€β”€ ComponentDetailPanel.tsx # Side panel for component details β”œβ”€β”€ ExpandedFolderView.tsx # Level 2 drill-down view β”œβ”€β”€ Breadcrumb.tsx # Navigation breadcrumb └── layoutUtils.ts # Tiered layout calculation ``` ### Delete ``` # Remove dagre dependency if no longer needed elsewhere # Or keep but don't use for topology layout ``` --- ## Success Criteria - [ ] Default view shows ~6 folder nodes (not 123 component nodes) - [ ] Folders are color-coded by type - [ ] Connection thickness indicates traffic - [ ] Double-click expands folder to show components - [ ] Components link to X-Ray view - [ ] Orphans clearly indicated but not cluttering main view - [ ] Works smoothly on projects with 100+ components - [ ] Layout is deterministic (same project = same layout) - [ ] Visually polished (matches mockup color scheme) --- ## Reference Mockups See artifact files created during design review: - `topology-drilldown.jsx` - Interactive prototype with both levels - `architecture-views.jsx` - Alternative visualization concepts (for reference) Key visual elements from mockups: - Dark background (#111827 / gray-900) - Colored borders on nodes, semi-transparent fills - White text for names, muted text for counts - Connection lines in gray with variable opacity/thickness - Selection state: brighter border, subtle glow --- ## Notes for Cline 1. **Don't try to show everything at once.** The key insight is aggregation: 123 components β†’ 6 folders β†’ readable. 2. **The layout should be semantic, not algorithmic.** Pages at top, utilities at bottom. Don't let dagre decide - it optimizes for edge crossing, not comprehension. 3. **Colors matter.** The current gray-on-gray is impossible to parse. Use the color palette defined above. 4. **This view complements X-Ray, doesn't replace it.** Topology = relationships between things. X-Ray = what's inside a thing. Link them together. 5. **Test with the real project** that has 123 components and 68 orphans. If it doesn't look good on that, it's not done.