diff --git a/skills/react-flow-architect/SKILL.md b/skills/react-flow-architect/SKILL.md
new file mode 100644
index 0000000..4db9537
--- /dev/null
+++ b/skills/react-flow-architect/SKILL.md
@@ -0,0 +1,602 @@
+---
+name: react-flow-architect
+description: Expert ReactFlow architect for building interactive graph applications with hierarchical node-edge systems, performance optimization, and auto-layout integration. Use when Claude needs to create or optimize ReactFlow applications for: (1) Interactive process graphs with expand/collapse navigation, (2) Hierarchical tree structures with drag & drop, (3) Performance-optimized large datasets with incremental rendering, (4) Auto-layout integration with Dagre, (5) Complex state management for nodes and edges, or any advanced ReactFlow visualization requirements.
+---
+
+# ReactFlow Architect
+
+Build production-ready ReactFlow applications with hierarchical navigation, performance optimization, and advanced state management.
+
+## Quick Start
+
+Create basic interactive graph:
+
+```tsx
+import ReactFlow, { Node, Edge } from 'reactflow';
+
+const nodes: Node[] = [
+ { id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } },
+ { id: '2', position: { x: 100, y: 100 }, data: { label: 'Node 2' } }
+];
+
+const edges: Edge[] = [
+ { id: 'e1-2', source: '1', target: '2' }
+];
+
+export default function Graph() {
+ return (
+
+ );
+}
+```
+
+## Core Patterns
+
+### Hierarchical Tree Navigation
+
+Build expandable/collapsible tree structures with parent-child relationships.
+
+#### Node Schema
+```typescript
+interface TreeNode extends Node {
+ data: {
+ label: string;
+ level: number;
+ hasChildren: boolean;
+ isExpanded: boolean;
+ childCount: number;
+ category: 'root' | 'category' | 'process' | 'detail';
+ };
+}
+```
+
+#### Incremental Node Building
+```typescript
+const buildVisibleNodes = useCallback((
+ allNodes: TreeNode[],
+ expandedIds: Set,
+ otherDeps: any[]
+) => {
+ const visibleNodes = new Map();
+ const visibleEdges = new Map();
+
+ // Start with root nodes
+ const rootNodes = allNodes.filter(n => n.data.level === 0);
+
+ // Recursively add visible nodes
+ const addVisibleChildren = (node: TreeNode) => {
+ visibleNodes.set(node.id, node);
+
+ if (expandedIds.has(node.id)) {
+ const children = allNodes.filter(n => n.parentNode === node.id);
+ children.forEach(child => addVisibleChildren(child));
+ }
+ };
+
+ rootNodes.forEach(root => addVisibleChildren(root));
+
+ return { nodes: Array.from(visibleNodes.values()), edges: Array.from(visibleEdges.values()) };
+}, []);
+```
+
+### Performance Optimization
+
+Handle large datasets with incremental rendering and memoization.
+
+#### Incremental Rendering
+```typescript
+const useIncrementalGraph = (allNodes: Node[], allEdges: Edge[], expandedList: string[]) => {
+ const prevExpandedListRef = useRef>(new Set());
+ const prevOtherDepsRef = useRef([]);
+
+ const { visibleNodes, visibleEdges } = useMemo(() => {
+ const currentExpandedSet = new Set(expandedList);
+ const prevExpandedSet = prevExpandedListRef.current;
+
+ // Check if expanded list changed
+ const expandedChanged = !areSetsEqual(currentExpandedSet, prevExpandedSet);
+
+ // Check if other dependencies changed
+ const otherDepsChanged = !arraysEqual(otherDeps, prevOtherDepsRef.current);
+
+ if (expandedChanged && !otherDepsChanged) {
+ // Only expanded list changed - incremental update
+ return buildIncrementalUpdate(
+ cachedVisibleNodesRef.current,
+ cachedVisibleEdgesRef.current,
+ allNodes,
+ allEdges,
+ currentExpandedSet,
+ prevExpandedSet
+ );
+ } else {
+ // Full rebuild needed
+ return buildFullGraph(allNodes, allEdges, currentExpandedSet);
+ }
+ }, [allNodes, allEdges, expandedList, ...otherDeps]);
+
+ return { visibleNodes, visibleEdges };
+};
+```
+
+#### Memoization Patterns
+```typescript
+// Memoize node components to prevent unnecessary re-renders
+const ProcessNode = memo(({ data, selected }: NodeProps) => {
+ return (
+
+ {data.label}
+
+ );
+}, (prevProps, nextProps) => {
+ // Custom comparison function
+ return (
+ prevProps.data.label === nextProps.data.label &&
+ prevProps.selected === nextProps.selected &&
+ prevProps.data.isExpanded === nextProps.data.isExpanded
+ );
+});
+
+// Memoize edge calculations
+const styledEdges = useMemo(() => {
+ return edges.map(edge => ({
+ ...edge,
+ style: {
+ ...edge.style,
+ strokeWidth: selectedEdgeId === edge.id ? 3 : 2,
+ stroke: selectedEdgeId === edge.id ? '#3b82f6' : '#94a3b8',
+ },
+ animated: selectedEdgeId === edge.id,
+ }));
+}, [edges, selectedEdgeId]);
+```
+
+### State Management
+
+Complex node/edge state patterns with undo/redo and persistence.
+
+#### Reducer Pattern
+```typescript
+type GraphAction =
+ | { type: 'SELECT_NODE'; payload: string }
+ | { type: 'SELECT_EDGE'; payload: string }
+ | { type: 'TOGGLE_EXPAND'; payload: string }
+ | { type: 'UPDATE_NODES'; payload: Node[] }
+ | { type: 'UPDATE_EDGES'; payload: Edge[] }
+ | { type: 'UNDO' }
+ | { type: 'REDO' };
+
+const graphReducer = (state: GraphState, action: GraphAction): GraphState => {
+ switch (action.type) {
+ case 'SELECT_NODE':
+ return {
+ ...state,
+ selectedNodeId: action.payload,
+ selectedEdgeId: null,
+ };
+
+ case 'TOGGLE_EXPAND':
+ const newExpanded = new Set(state.expandedNodeIds);
+ if (newExpanded.has(action.payload)) {
+ newExpanded.delete(action.payload);
+ } else {
+ newExpanded.add(action.payload);
+ }
+ return {
+ ...state,
+ expandedNodeIds: newExpanded,
+ isDirty: true,
+ };
+
+ default:
+ return state;
+ }
+};
+```
+
+#### History Management
+```typescript
+const useHistoryManager = (state: GraphState, dispatch: Dispatch) => {
+ const canUndo = state.historyIndex > 0;
+ const canRedo = state.historyIndex < state.history.length - 1;
+
+ const undo = useCallback(() => {
+ if (canUndo) {
+ const newIndex = state.historyIndex - 1;
+ const historyEntry = state.history[newIndex];
+
+ dispatch({
+ type: 'RESTORE_FROM_HISTORY',
+ payload: {
+ ...historyEntry,
+ historyIndex: newIndex,
+ },
+ });
+ }
+ }, [canUndo, state.historyIndex, state.history]);
+
+ const saveToHistory = useCallback(() => {
+ dispatch({ type: 'SAVE_TO_HISTORY' });
+ }, [dispatch]);
+
+ return { canUndo, canRedo, undo, redo, saveToHistory };
+};
+```
+
+## Advanced Features
+
+### Auto-Layout Integration
+
+Integrate Dagre for automatic graph layout:
+
+```typescript
+import dagre from 'dagre';
+
+const layoutOptions = {
+ rankdir: 'TB', // Top to Bottom
+ nodesep: 100, // Node separation
+ ranksep: 150, // Rank separation
+ marginx: 50,
+ marginy: 50,
+ edgesep: 10,
+};
+
+const applyLayout = (nodes: Node[], edges: Edge[]) => {
+ const g = new dagre.graphlib.Graph();
+ g.setGraph(layoutOptions);
+ g.setDefaultEdgeLabel(() => ({}));
+
+ // Add nodes to graph
+ nodes.forEach(node => {
+ g.setNode(node.id, { width: 200, height: 100 });
+ });
+
+ // Add edges to graph
+ edges.forEach(edge => {
+ g.setEdge(edge.source, edge.target);
+ });
+
+ // Calculate layout
+ dagre.layout(g);
+
+ // Apply positions
+ return nodes.map(node => ({
+ ...node,
+ position: {
+ x: g.node(node.id).x - 100,
+ y: g.node(node.id).y - 50,
+ },
+ }));
+};
+
+// Debounce layout calculations
+const debouncedLayout = useMemo(
+ () => debounce(applyLayout, 150),
+ []
+);
+```
+
+### Focus Mode
+
+Isolate selected nodes and their direct connections:
+
+```typescript
+const useFocusMode = (selectedNodeId: string, allNodes: Node[], allEdges: Edge[]) => {
+ return useMemo(() => {
+ if (!selectedNodeId) return { nodes: allNodes, edges: allEdges };
+
+ // Get direct connections
+ const connectedNodeIds = new Set([selectedNodeId]);
+ const focusedEdges: Edge[] = [];
+
+ allEdges.forEach(edge => {
+ if (edge.source === selectedNodeId || edge.target === selectedNodeId) {
+ focusedEdges.push(edge);
+ connectedNodeIds.add(edge.source);
+ connectedNodeIds.add(edge.target);
+ }
+ });
+
+ // Get connected nodes
+ const focusedNodes = allNodes.filter(n => connectedNodeIds.has(n.id));
+
+ return { nodes: focusedNodes, edges: focusedEdges };
+ }, [selectedNodeId, allNodes, allEdges]);
+};
+
+// Smooth transitions for focus mode
+const focusModeStyles = {
+ transition: 'all 0.3s ease-in-out',
+ opacity: isInFocus ? 1 : 0.3,
+ filter: isInFocus ? 'none' : 'blur(2px)',
+};
+```
+
+### Search Integration
+
+Search and navigate to specific nodes:
+
+```typescript
+const searchNodes = useCallback((
+ nodes: Node[],
+ query: string
+) => {
+ if (!query.trim()) return [];
+
+ const lowerQuery = query.toLowerCase();
+ return nodes.filter(node =>
+ node.data.label.toLowerCase().includes(lowerQuery) ||
+ node.data.description?.toLowerCase().includes(lowerQuery)
+ );
+}, []);
+
+const navigateToSearchResult = (nodeId: string) => {
+ // Expand parent nodes
+ const nodePath = calculateBreadcrumbPath(nodeId, allNodes);
+ const parentIds = nodePath.slice(0, -1).map(n => n.id);
+
+ setExpandedIds(prev => new Set([...prev, ...parentIds]));
+ setSelectedNodeId(nodeId);
+
+ // Fit view to node
+ fitView({ nodes: [{ id: nodeId }], duration: 800 });
+};
+```
+
+## Performance Tools
+
+### Graph Performance Analyzer
+
+Create a performance analysis script:
+
+```javascript
+// scripts/graph-analyzer.js
+class GraphAnalyzer {
+ analyzeCode(content, filePath) {
+ const analysis = {
+ metrics: {
+ nodeCount: this.countNodes(content),
+ edgeCount: this.countEdges(content),
+ renderTime: this.estimateRenderTime(content),
+ memoryUsage: this.estimateMemoryUsage(content),
+ complexity: this.calculateComplexity(content)
+ },
+ issues: [],
+ optimizations: [],
+ patterns: this.detectPatterns(content)
+ };
+
+ // Detect performance issues
+ this.detectPerformanceIssues(analysis);
+
+ // Suggest optimizations
+ this.suggestOptimizations(analysis);
+
+ return analysis;
+ }
+
+ countNodes(content) {
+ const nodePatterns = [
+ /nodes:\s*\[.*?\]/gs,
+ /const\s+\w+\s*=\s*\[.*?id:.*?position:/gs
+ ];
+
+ let totalCount = 0;
+ nodePatterns.forEach(pattern => {
+ const matches = content.match(pattern);
+ if (matches) {
+ matches.forEach(match => {
+ const nodeMatches = match.match(/id:\s*['"`][^'"`]+['"`]/g);
+ if (nodeMatches) {
+ totalCount += nodeMatches.length;
+ }
+ });
+ }
+ });
+
+ return totalCount;
+ }
+
+ estimateRenderTime(content) {
+ const nodeCount = this.countNodes(content);
+ const edgeCount = this.countEdges(content);
+
+ // Base render time estimation (ms)
+ const baseTime = 5;
+ const nodeTime = nodeCount * 0.1;
+ const edgeTime = edgeCount * 0.05;
+
+ return baseTime + nodeTime + edgeTime;
+ }
+
+ detectPerformanceIssues(analysis) {
+ const { metrics } = analysis;
+
+ if (metrics.nodeCount > 500) {
+ analysis.issues.push({
+ type: 'HIGH_NODE_COUNT',
+ severity: 'high',
+ message: `Too many nodes (${metrics.nodeCount}). Consider virtualization.`,
+ suggestion: 'Implement virtualization or reduce visible nodes'
+ });
+ }
+
+ if (metrics.renderTime > 16) {
+ analysis.issues.push({
+ type: 'SLOW_RENDER',
+ severity: 'high',
+ message: `Render time (${metrics.renderTime.toFixed(2)}ms) exceeds 60fps.`,
+ suggestion: 'Optimize with memoization and incremental rendering'
+ });
+ }
+ }
+}
+```
+
+## Best Practices
+
+### Performance Guidelines
+
+1. **Use React.memo** for node components to prevent unnecessary re-renders
+2. **Implement virtualization** for graphs with 1000+ nodes
+3. **Debounce layout calculations** during rapid interactions
+4. **Use useCallback** for edge creation and manipulation functions
+5. **Implement proper TypeScript types** for nodes and edges
+
+### Memory Management
+
+```typescript
+// Use Map for O(1) lookups instead of array.find
+const nodesById = useMemo(() =>
+ new Map(allNodes.map(n => [n.id, n])), [allNodes]
+);
+
+// Cache layout results
+const layoutCacheRef = useRef