GraphRenderer Component Refactoring Plan
Execution Plan
Refactor the 3382-line GraphRenderer.tsx into smaller, composable components and utilities while maintaining all existing functionality. This plan follows principles that a principal frontend engineer would approve.
Overview
Component Organization Strategy
Subdirectory Structure with Index Files
Goal: Organize components into subdirectories with index.tsx files for cleaner imports and better maintainability.
Target Directory Structure
src/components/Graph/
├── GraphRenderer/ # Main component (stays at root for now)
│ ├── index.tsx # Re-exports GraphRenderer
│ ├── GraphRenderer.tsx # Main implementation
│ ├── GraphRenderer.module.css
│ └── GraphRenderer.stories.tsx
├── GraphMenuBar/
│ ├── index.tsx # Re-exports GraphMenuBar
│ ├── GraphMenuBar.tsx
│ └── GraphMenuBar.stories.tsx
├── GraphInfoPanel/
│ ├── index.tsx # Re-exports GraphInfoPanel
│ ├── GraphInfoPanel.tsx
│ └── GraphInfoPanel.stories.tsx
├── GraphCanvas/
│ ├── index.tsx # Re-exports GraphCanvas
│ ├── GraphCanvas.tsx
│ └── GraphCanvas.stories.tsx
├── GraphRightClickMenu/ # New component (extracted)
│ ├── index.tsx
│ ├── GraphRightClickMenu.tsx
│ └── GraphRightClickMenu.stories.tsx
├── GraphContextMenu/ # New component (extracted)
│ ├── index.tsx
│ ├── GraphContextMenu.tsx
│ └── GraphContextMenu.stories.tsx
├── hooks/ # Custom hooks
│ ├── index.ts # Re-exports all hooks
│ ├── useGraphDimensions.ts
│ ├── useGraphState.ts
│ ├── useGraphData.ts
│ ├── useGraphInteractions.ts
│ ├── useGraphCanvasSetup.ts
│ ├── useGraphMenuHandlers.ts
│ └── useGraphUrlFragment.ts
├── utils/ # Utility functions
│ ├── index.ts # Re-exports all utils
│ ├── graphConstants.ts
│ ├── GraphDataUtils.ts
│ ├── GraphNodeUtils.ts
│ ├── GraphRenderingUtils.ts
│ ├── GraphTextUtils.ts
│ ├── GraphCanvasDrawingUtils.ts
│ ├── GraphEdgeDrawingUtils.ts
│ └── graphUtils.ts # Backward compatibility re-exports
├── types.ts # Shared types
└── README.md # Component documentation
Index File Pattern
Each component subdirectory will have an index.tsx that re-exports the component:
// GraphMenuBar/index.tsx
export { GraphMenuBar } from './GraphMenuBar';
export type { GraphMenuBarProps } from './GraphMenuBar';
This allows clean imports:
// Before
import { GraphMenuBar } from './GraphMenuBar/GraphMenuBar';
// After
import { GraphMenuBar } from './GraphMenuBar';
Story Organization
Stories will be co-located with components in their subdirectories:
// GraphMenuBar/GraphMenuBar.stories.tsx
import { Meta, StoryObj } from '@storybook/react';
import { GraphMenuBar } from './GraphMenuBar';
const meta: Meta<typeof GraphMenuBar> = {
title: 'Graph/GraphMenuBar',
component: GraphMenuBar,
};
export default meta;
type Story = StoryObj<typeof GraphMenuBar>;
export const Default: Story = {
// ...
};
Benefits of This Structure
- Cleaner Imports:
import { GraphMenuBar } from './GraphMenuBar'instead of'./GraphMenuBar/GraphMenuBar' - Co-location: Component, styles, stories, and tests in one place
- Better Discoverability: Easy to find all files related to a component
- Scalability: Easy to add new components without cluttering root
- Maintainability: Clear boundaries between components
Migration Strategy
Phase 0: Reorganize Existing Components (Before refactoring)
-
Create subdirectories for existing components
mkdir -p src/components/Graph/GraphMenuBar
mkdir -p src/components/Graph/GraphInfoPanel
mkdir -p src/components/Graph/GraphCanvas -
Move component files
mv GraphMenuBar.tsx GraphMenuBar/GraphMenuBar.tsx
mv GraphMenuBar.stories.tsx GraphMenuBar/GraphMenuBar.stories.tsx -
Create index.tsx files
// GraphMenuBar/index.tsx
export { GraphMenuBar } from './GraphMenuBar';
export type { GraphMenuBarProps } from './GraphMenuBar'; -
Update imports in GraphRenderer
// Before
import { GraphMenuBar } from './GraphMenuBar';
// After (no change needed if index.tsx is created)
import { GraphMenuBar } from './GraphMenuBar'; -
Create hooks/ subdirectory
mkdir -p src/components/Graph/hooks
mv useGraphState.ts hooks/
mv useGraphData.ts hooks/
mv useGraphInteractions.ts hooks/ -
Create hooks/index.ts
// hooks/index.ts
export { useGraphState } from './useGraphState';
export { useGraphData } from './useGraphData';
export { useGraphInteractions } from './useGraphInteractions'; -
Create utils/ subdirectory (if not exists)
mkdir -p src/components/Graph/utils
# Move utility files to utils/ -
Update all imports
- Update GraphRenderer imports
- Update Storybook stories
- Update tests
- Update documentation
Timing: This reorganization should happen before starting the refactoring phases, as it provides a clean foundation.
Current State Analysis
File Size: 3382 lines
Main Sections:
- Drawing Functions (~600 lines):
drawNodeCircle,drawDebugSectionSeparators,drawTitle,drawStatusIndicator - Edge Rendering Functions (~100 lines):
getEdgeWidth,getEdgeCoordinates,drawComparisonEdge,drawEdgeLabel - Main Component Logic (~2600 lines): State, event handlers, dimension calculations, canvas setup, menus, info panel
- Constants:
NEO4J_COLORS,DEBUG_SHOW_NODE_SECTIONS
Existing Utilities (Already Extracted):
- ✅
GraphDataUtils.ts- Tree traversal, data cleaning - ✅
GraphNodeUtils.ts- Node properties, styling, validation - ✅
GraphRenderingUtils.ts- Rendering calculations, coordinates - ✅
GraphTextUtils.ts- Text processing, wrapping, font sizing - ✅
NodeRenderer.ts- Node rendering class - ✅
useGraphData.ts- Graph data hooks - ✅
useGraphInteractions.ts- Interaction hooks - ✅
useGraphState.ts- State management hooks
Existing Components (Already Extracted):
- ✅
GraphCanvas.tsx- Canvas wrapper - ✅
GraphInfoPanel.tsx- Info panel component - ✅
GraphMenuBar.tsx- Menu bar component
Refactoring Strategy
Phase 1: Extract Canvas Drawing Utilities (Low Risk)
Goal: Move pure drawing functions to utility files
1.1 Create GraphCanvasDrawingUtils.ts
Extract:
drawNodeCircle→drawNodeCircledrawDebugSectionSeparators→drawDebugSectionSeparatorsdrawStatusIndicator→drawStatusIndicatordrawTitle→drawTitle(complex, ~400 lines - keep as-is but move to utils)
Location: src/components/Graph/GraphCanvasDrawingUtils.ts
Dependencies:
- Canvas context
- Node data
- Styling parameters (colors, sizes)
Risk: Low - Pure functions, no component state
1.2 Create GraphEdgeDrawingUtils.ts
Extract:
drawComparisonEdge→drawComparisonEdgedrawEdgeLabel→drawEdgeLabelgetEdgeWidth→getEdgeWidth(already in GraphRenderingUtils? Check)
Location: src/components/Graph/GraphEdgeDrawingUtils.ts
Risk: Low - Pure functions
Phase 2: Extract Dimension Calculation Logic (Low Risk)
Goal: Move responsive dimension calculations to a custom hook
2.1 Create useGraphDimensions.ts
Extract:
- Dimension calculation logic (lines ~2349-2361)
baseGraphAreaHeight,graphCanvasHeight,graphAreaHeightcalculationsgraphWidth,panelWidthcalculations- Container width measurement logic
Location: src/components/Graph/useGraphDimensions.ts
Returns:
{
graphAreaHeight: number;
graphCanvasHeight: number;
graphWidth: number;
panelWidth: number;
actualContainerWidth: number;
isMobile: boolean;
}
Risk: Low - Isolated logic, easy to test
Phase 3: Extract Event Handlers (Medium Risk)
Goal: Move event handler logic to custom hooks
3.1 Enhance useGraphInteractions.ts
Extract:
handleNodeClick→useNodeClickHandlerhandleNodeRightClick→useNodeRightClickHandlerhandleLinkClick→useLinkClickHandlerhandleLinkRightClick→useLinkRightClickHandlerhandleNodeDrag→useNodeDragHandlerhandleNodeDragEnd→useNodeDragEndHandlerhandleZoom→useZoomHandlerhandleWheel→useWheelHandler
Location: src/components/Graph/useGraphInteractions.ts (enhance existing)
Risk: Medium - Need to ensure all dependencies are passed correctly
3.2 Create useGraphMenuHandlers.ts
Extract:
copyAnchorLink→useCopyAnchorLinktogglePane→useTogglePane- Context menu click outside handler
- Right-click menu logic
Location: src/components/Graph/useGraphMenuHandlers.ts
Risk: Low - Isolated menu logic
Phase 4: Extract Canvas Setup Logic (Medium Risk)
Goal: Move canvas initialization and event listeners to a hook
4.1 Create useGraphCanvasSetup.ts
Extract:
- Canvas ref setup
- Event listener registration (wheel, contextmenu)
- Canvas cleanup
nodeCanvasObjectandlinkCanvasObjectcreation
Location: src/components/Graph/useGraphCanvasSetup.ts
Returns:
{
graphRef: RefObject<any>;
nodeCanvasObject: (node, ctx, globalScale) => void;
linkCanvasObject: (link, ctx, globalScale) => void;
linkCanvasObjectMode: (link) => string;
}
Risk: Medium - Complex setup logic, need to ensure all dependencies
Phase 5: Extract Menu Components (Low Risk)
Goal: Extract inline menu JSX to separate components
5.1 Create GraphRightClickMenu.tsx
Extract:
- Right-click menu JSX (lines ~2425-2486)
- Menu item rendering logic
Location: src/components/Graph/GraphRightClickMenu.tsx
Props:
{
menu: { nodeId: string; x: number; y: number } | null;
isDarkMode: boolean;
expandedNodes: Set<string>;
onToggleExpansion: (nodeId: string) => void;
onCopyLink: (nodeId: string) => void;
onClose: () => void;
}
Risk: Low - Pure presentational component
5.2 Create GraphContextMenu.tsx
Extract:
- Context menu JSX (lines ~2487-2510)
Location: src/components/Graph/GraphContextMenu.tsx
Props:
{
menu: { x: number; y: number; nodeId?: string; edgeId?: string } | null;
isDarkMode: boolean;
onCopyLink: (nodeId?: string, edgeId?: string) => void;
onClose: () => void;
}
Risk: Low - Pure presentational component
Phase 6: Extract URL Fragment Handling (Low Risk)
Goal: Move URL fragment parsing and highlighting to a hook
6.1 Create useGraphUrlFragment.ts
Extract:
- URL fragment parsing logic
highlightNodeandhighlightEdgecalls from URL- Scroll to graph logic
Location: src/components/Graph/useGraphUrlFragment.ts
Risk: Low - Isolated URL handling
Phase 7: Extract Constants (Low Risk)
Goal: Move constants to a separate file
7.1 Create graphConstants.ts
Extract:
NEO4J_COLORS→NEO4J_COLORSDEBUG_SHOW_NODE_SECTIONS→DEBUG_SHOW_NODE_SECTIONS
Location: src/components/Graph/graphConstants.ts
Risk: Low - Simple constants
Phase 8: Refactor Main Component (High Risk - Do Last)
Goal: Simplify GraphRendererImpl to orchestrate hooks and components
8.1 Final GraphRendererImpl Structure
const GraphRendererImpl = ({ ... }) => {
// Hooks
const dimensions = useGraphDimensions(width, height, paneVisible, isMobile);
const graphState = useGraphState(initialExpandedNodes);
const interactions = useGraphInteractions(/* deps */);
const canvasSetup = useGraphCanvasSetup(/* deps */);
const menuHandlers = useGraphMenuHandlers(graphId);
const urlFragment = useGraphUrlFragment(/* deps */);
// Memoized callbacks
const nodeCanvasObject = canvasSetup.nodeCanvasObject;
const linkCanvasObject = canvasSetup.linkCanvasObject;
// Render
return (
<div>
<GraphMenuBar />
<div className={styles.graphArea}>
<GraphCanvas>
<ForceGraph2D {...props} />
</GraphCanvas>
{paneVisible && <GraphInfoPanel />}
</div>
<GraphRightClickMenu />
<GraphContextMenu />
</div>
);
};
Risk: High - This is the integration point, need careful testing
Implementation Order (Risk-Based)
Phase 0: Reorganize Structure (Week 0 - Prerequisite)
Goal: Set up subdirectory structure before refactoring
- ✅ Create subdirectories for existing components
- ✅ Move components to subdirectories with index.tsx
- ✅ Move stories to component subdirectories
- ✅ Create hooks/ subdirectory and move hooks
- ✅ Create utils/ subdirectory (if needed)
- ✅ Update all imports across codebase
- ✅ Verify all tests still pass
- ✅ Verify Storybook stories still work
Timing: Do this before starting Phase 1
Week 1: Low-Risk Extractions
- ✅ Phase 7: Extract Constants →
utils/graphConstants.ts - ✅ Phase 1: Extract Canvas Drawing Utilities →
utils/GraphCanvasDrawingUtils.ts&utils/GraphEdgeDrawingUtils.ts - ✅ Phase 2: Extract Dimension Calculation Logic →
hooks/useGraphDimensions.ts - ✅ Phase 5: Extract Menu Components →
GraphRightClickMenu/&GraphContextMenu/
Week 2: Medium-Risk Extractions
- ✅ Phase 3: Extract Event Handlers →
hooks/useGraphInteractions.ts(enhance) - ✅ Phase 4: Extract Canvas Setup Logic →
hooks/useGraphCanvasSetup.ts - ✅ Phase 6: Extract URL Fragment Handling →
hooks/useGraphUrlFragment.ts - ✅ Phase 7: Extract Menu Handlers →
hooks/useGraphMenuHandlers.ts
Week 3: High-Risk Integration
- ✅ Phase 8: Refactor Main Component
- ✅ Comprehensive Testing
- ✅ Update Documentation
Testing Strategy
Test Directory Structure
test/
├── e2e/ # End-to-end tests (Playwright)
│ ├── graph-renderer.spec.ts
│ ├── graph-selection-state.spec.ts
│ ├── graph-title-rendering.spec.ts
│ └── helpers/
│ └── canvas-utils.ts
├── unit/ # Unit tests (Jest)
│ └── GraphRenderer.title.test.ts
├── utils/ # Test utilities
│ └── canvasMock.ts
└── setup.ts # Jest setup
Unit Tests (Jest) - test/unit/
Phase 1: Utility Function Tests
Location: test/unit/
New Test Files to Create:
-
GraphCanvasDrawingUtils.test.ts- Test
drawNodeCirclewith various parameters - Test
drawDebugSectionSeparators(when debug enabled) - Test
drawStatusIndicatorfor leaf vs parent nodes - Test
drawTitlewith various text lengths and zoom levels - Use
createMockCanvasContext()fromtest/utils/canvasMock.ts
- Test
-
GraphEdgeDrawingUtils.test.ts- Test
drawComparisonEdgerendering - Test
drawEdgeLabelwith various labels and scales - Test
getEdgeWidthcalculations
- Test
-
graphConstants.test.ts- Test
NEO4J_COLORSarray structure - Test
DEBUG_SHOW_NODE_SECTIONSflag
- Test
-
useGraphDimensions.test.ts- Test dimension calculations for mobile vs desktop
- Test pane visibility impact on dimensions
- Test container width measurement
- Use React Testing Library to test hook
Update Existing:
GraphRenderer.title.test.ts: Update imports ifdrawTitlemoves to utils
Phase 2: Hook Tests
Location: test/unit/
New Test Files:
-
useGraphMenuHandlers.test.ts- Test
useCopyAnchorLinkwith clipboard API - Test
useTogglePanestate changes - Test context menu click outside handler
- Test
-
useGraphUrlFragment.test.ts- Test URL fragment parsing
- Test
highlightNodefrom URL - Test
highlightEdgefrom URL - Test scroll to graph behavior
-
useGraphCanvasSetup.test.ts- Test canvas ref setup
- Test event listener registration
- Test
nodeCanvasObjectcreation - Test
linkCanvasObjectcreation
Enhance Existing:
useGraphInteractions.ts(if exists): Add tests for extracted handlers
Test Utilities to Create/Update
Location: test/utils/
-
graphHookTestUtils.ts(New)// Utilities for testing graph hooks
export function renderGraphHook<T>(hook: () => T, wrapper?: ReactWrapper)
export function createMockGraphRef()
export function createMockGraphData() -
canvasMock.ts(Update)- Add more mock methods if needed for new drawing functions
- Ensure compatibility with extracted drawing utilities
End-to-End Tests (Playwright) - test/e2e/
Update Strategy for E2E Tests
Key Principle: E2E tests should remain largely unchanged since they test the public API of GraphRenderer, not internal implementation details.
Files to Update:
-
graph-renderer.spec.ts- No changes needed - Tests public API (canvas rendering, interactions)
- May need to update selectors if component structure changes slightly
- Verify canvas still renders correctly after refactoring
-
graph-selection-state.spec.ts- No changes needed - Tests selection behavior (public API)
- Verify node/edge selection still works after refactoring
- Test URL hash behavior still works
-
graph-title-rendering.spec.ts- No changes needed - Tests title rendering (visual output)
- Verify ellipsis regression test still passes
- May need screenshot updates if rendering changes slightly
New E2E Tests to Add:
-
graph-responsive-behavior.spec.ts(New)// Test responsive behavior
- Test mobile layout (pane below graph)
- Test desktop layout (pane beside graph)
- Test pane visibility toggle
- Test graph area resizing
- Test canvas overflow prevention -
graph-menu-interactions.spec.ts(New)// Test menu interactions
- Test right-click menu
- Test context menu
- Test copy anchor link
- Test menu positioning
E2E Test Helpers to Update:
helpers/canvas-utils.ts- No changes needed - Generic canvas utilities
- May add helpers for testing responsive behavior if needed
Integration Tests (New Category)
Location: test/integration/ (Create if doesn't exist)
Purpose
Test interactions between hooks and components in isolation from full E2E flow.
New Test Files:
-
GraphRenderer.integration.test.tsx// Test GraphRenderer with all hooks integrated
- Test component renders with all hooks
- Test hook interactions (e.g., dimension changes trigger re-render)
- Test state synchronization between hooks
- Use React Testing Library -
GraphHooks.integration.test.tsx// Test hook interactions
- Test useGraphDimensions + useGraphState interaction
- Test useGraphInteractions + useGraphCanvasSetup interaction
- Test useGraphUrlFragment + useGraphState interaction
Test Update Checklist Per Phase
Phase 1: Extract Constants & Drawing Utilities
- Create
GraphCanvasDrawingUtils.test.ts - Create
GraphEdgeDrawingUtils.test.ts - Create
graphConstants.test.ts - Update
GraphRenderer.title.test.tsimports if needed - Run unit tests:
yarn test - Verify all tests pass
Phase 2: Extract Dimension Calculations
- Create
useGraphDimensions.test.ts - Test mobile vs desktop calculations
- Test pane visibility impact
- Run unit tests:
yarn test - Run E2E tests:
yarn test:e2e(verify no regressions)
Phase 3: Extract Event Handlers
- Enhance
useGraphInteractions.test.ts(if exists) - Test all event handlers in isolation
- Run unit tests:
yarn test - Run E2E tests:
yarn test:e2e(verify interactions still work)
Phase 4: Extract Canvas Setup
- Create
useGraphCanvasSetup.test.ts - Test canvas ref setup
- Test event listener registration
- Run unit tests:
yarn test - Run E2E tests:
yarn test:e2e(verify canvas still renders)
Phase 5: Extract Menu Components
- Create
GraphRightClickMenu.test.tsx - Create
GraphContextMenu.test.tsx - Test menu rendering and interactions
- Run unit tests:
yarn test - Run E2E tests:
yarn test:e2e(verify menus still work)
Phase 6: Extract URL Fragment Handling
- Create
useGraphUrlFragment.test.ts - Test URL parsing and highlighting
- Run unit tests:
yarn test - Run E2E tests:
yarn test:e2e(verify URL hash still works)
Phase 7: Extract Menu Handlers
- Create
useGraphMenuHandlers.test.ts - Test clipboard API interactions
- Test pane toggle
- Run unit tests:
yarn test - Run E2E tests:
yarn test:e2e(verify menu actions still work)
Phase 8: Refactor Main Component
- Create
GraphRenderer.integration.test.tsx - Test full component with all hooks
- Run all unit tests:
yarn test - Run all E2E tests:
yarn test:e2e - Visual regression test in Storybook
- Performance test (ensure no degradation)
Test Maintenance Strategy
After Each Phase:
-
Run Test Suite
# Unit tests
yarn test
# E2E tests
yarn test:e2e
# With coverage
yarn test:coverage -
Update Test Documentation
- Update
test/README.mdif test structure changes - Update
test/e2e/README.mdif E2E tests change - Update
test/unit/README.mdif unit tests change
- Update
-
Fix Broken Tests
- Update imports if code moves
- Update mocks if APIs change
- Update selectors if component structure changes
-
Add New Tests
- Add tests for newly extracted code
- Ensure coverage doesn't decrease
- Add integration tests for hook interactions
Test Coverage Goals:
- Unit Tests: > 80% coverage for utility functions
- Hook Tests: > 70% coverage for custom hooks
- Component Tests: > 60% coverage for components
- E2E Tests: Cover all critical user flows
Regression Testing
Visual Regression Tests
- Use Storybook for visual regression testing
- Compare screenshots before/after refactoring
- Test all graph states (expanded, collapsed, selected, etc.)
Performance Regression Tests
- Measure render time before/after refactoring
- Measure memory usage
- Test with large graphs (100+ nodes)
- Ensure no performance degradation
Functional Regression Tests
- Run full E2E test suite after each phase
- Test all user interactions
- Test all responsive breakpoints
- Test all pane visibility states
Test Utilities to Create
test/utils/graphHookTestUtils.ts (New)
import { renderHook } from '@testing-library/react';
import { ReactNode } from 'react';
/**
* Renders a graph hook with necessary providers
*/
export function renderGraphHook<T>(
hook: () => T,
options?: {
wrapper?: ({ children }: { children: ReactNode }) => JSX.Element;
}
) {
// Implementation
}
/**
* Creates a mock graph ref for testing
*/
export function createMockGraphRef() {
// Implementation
}
/**
* Creates mock graph data for testing
*/
export function createMockGraphData() {
// Implementation
}
test/utils/graphComponentTestUtils.tsx (New)
/**
* Utilities for testing graph components
*/
export function renderGraphComponent(props: GraphRendererProps) {
// Implementation with all necessary providers
}
export function waitForGraphToStabilize() {
// Helper to wait for force graph to stabilize
}
E2E Test Updates
Minimal Changes Required
E2E tests should require minimal changes because they test the public API. However:
-
Selector Updates (if component structure changes)
- Update canvas selectors if wrapper structure changes
- Update menu selectors if menu components are extracted
-
Wait Strategy Updates (if initialization changes)
- Update wait times if hook initialization changes
- Update wait conditions if component mounting changes
-
Screenshot Updates (if visual changes)
- Update baseline screenshots if rendering changes
- Add new screenshots for new features
E2E Test Maintenance
- Keep E2E tests focused on user-facing behavior
- Don't test internal implementation details
- Use page objects if tests become complex
- Add visual regression tests for critical UI states
Blog Post and Documentation Updates
Files That Import Graph Components
Documentation Files:
-
docs/6-techniques/3-blogging-techniques/1-embed-structural-components/graph.mdx- Imports:
GraphRenderer,NodeRendererDemo - Usage: Component documentation and examples
- Impact: High - Main component documentation
- Imports:
-
docs/3-mental-models/6-understanding-the-genai-domain/2025-11-10-ai-framework-landscape.md- Imports:
AIFrameworkGraph - Usage: Displays AI framework comparison graph
- Impact: High - Live graph visualization
- Imports:
Blog Posts:
-
blog/2025-03-07-DFS-vs-BFS.md- May reference graph concepts (needs verification)
- Impact: Low - Likely just mentions, not imports
-
blog/2025-09-27-my-contributions.mdx- May reference graph components (needs verification)
- Impact: Low - Likely just mentions, not imports
Import Path Updates Required
When components move to subdirectories, import paths in MDX files need updates:
Before:
import GraphRenderer from '@site/src/components/Graph/GraphRenderer';
import NodeRendererDemo from '@site/src/components/Graph/NodeRendererDemo';
import AIFrameworkGraph from '@site/src/components/Graph/AIFrameworkGraph';
After (if components move to subdirectories):
// Option 1: If index.tsx is created, no change needed
import GraphRenderer from '@site/src/components/Graph/GraphRenderer';
import NodeRendererDemo from '@site/src/components/Graph/NodeRendererDemo';
import AIFrameworkGraph from '@site/src/components/Graph/AIFrameworkGraph';
// Option 2: If explicit paths are preferred
import GraphRenderer from '@site/src/components/Graph/GraphRenderer/GraphRenderer';
import NodeRendererDemo from '@site/src/components/Graph/NodeRendererDemo/NodeRendererDemo';
import AIFrameworkGraph from '@site/src/components/Graph/AIFrameworkGraph/AIFrameworkGraph';
Recommendation: Use index.tsx files so imports don't need to change.
Update Strategy for Blog Posts and Docs
Phase 0: Before Reorganization
-
Audit all imports
# Find all files importing Graph components
grep -r "from '@site/src/components/Graph" blog/ docs/ -
Document current import paths
- List all files that import Graph components
- Note which components are imported
- Create checklist for updates
Phase 0: During Reorganization
-
Update import paths (if needed)
- If using
index.tsx, imports may not need changes - If not using
index.tsx, update all import paths - Test each file after updating
- If using
-
Verify components still work
- Build Docusaurus site:
make build - Check each page that uses Graph components
- Verify graphs render correctly
- Test interactive features (clicking, zooming, etc.)
- Build Docusaurus site:
After Each Refactoring Phase
-
Test affected pages
- Rebuild Docusaurus:
make build - Check pages that use Graph components
- Verify no regressions
- Rebuild Docusaurus:
-
Update documentation if needed
- Update component documentation if APIs change
- Update examples if usage patterns change
- Update README files if structure changes
Files to Update Checklist
Documentation:
-
docs/6-techniques/3-blogging-techniques/1-embed-structural-components/graph.mdx- Update
GraphRendererimport if path changes - Update
NodeRendererDemoimport if path changes - Verify examples still work
- Update documentation if component API changes
- Update
-
docs/3-mental-models/6-understanding-the-genai-domain/2025-11-10-ai-framework-landscape.md- Update
AIFrameworkGraphimport if path changes - Verify graph renders correctly
- Test interactive features
- Update
Blog Posts:
-
blog/2025-03-07-DFS-vs-BFS.md- Check if it actually imports components (may just mention)
- Update if needed
-
blog/2025-09-27-my-contributions.mdx- Check if it actually imports components (may just mention)
- Update if needed
Other Documentation:
- Check all files in
docs/that mention "graph" or "Graph"- Update import paths if needed
- Update examples if component API changes
- Update code snippets if usage patterns change
Testing Blog Posts and Docs
After Each Phase:
-
Build Docusaurus
cd bytesofpurpose-blog
yarn build -
Check for Build Errors
- Look for import errors
- Look for component not found errors
- Fix any broken imports
-
Visual Verification
- Start dev server:
yarn start - Navigate to each page that uses Graph components
- Verify graphs render correctly
- Test interactive features
- Start dev server:
-
Anchor Link Testing
- Test URL hash navigation (e.g.,
#graph-node-123) - Verify nodes/edges highlight correctly
- Verify scrolling to graph works
- Test URL hash navigation (e.g.,
Backward Compatibility Strategy
Goal: Ensure existing blog posts and docs continue to work without changes.
Strategy:
- Use index.tsx files - Allows imports to remain unchanged
- Maintain public API - Don't change component props or behavior
- Re-export from root - Consider re-exporting from
Graph/index.tsfor convenience
Example re-export file:
// src/components/Graph/index.ts
// Re-export all public components for convenience
export { GraphRenderer } from './GraphRenderer';
export { AIFrameworkGraph } from './AIFrameworkGraph';
export { NodeRendererDemo } from './NodeRendererDemo';
export type { GraphRendererProps } from './GraphRenderer';
This allows imports like:
import { GraphRenderer, AIFrameworkGraph } from '@site/src/components/Graph';
Documentation Update Guidelines
When to Update Documentation:
- ✅ Component moves to subdirectory (update import paths)
- ✅ Component API changes (update examples)
- ✅ New features added (document new features)
- ✅ Breaking changes (document migration path)
- ❌ Internal refactoring only (no doc updates needed if public API unchanged)
What to Update:
- Import statements - If paths change
- Code examples - If API changes
- Usage patterns - If best practices change
- Component documentation - If features change
- README files - If structure changes
What NOT to Update:
- Internal implementation details (unless relevant to users)
- File structure (unless it affects imports)
- Utility functions (unless they're part of public API)
Storybook Story Updates
Story Path Updates
When components move to subdirectories, Storybook story paths may need updates:
Before:
// GraphMenuBar.stories.tsx (at root)
import { Meta } from '@storybook/addon-docs/blocks';
<Meta title="Graph/GraphMenuBar" />
After:
// GraphMenuBar/GraphMenuBar.stories.tsx
import { Meta } from '@storybook/addon-docs/blocks';
<Meta title="Graph/GraphMenuBar" />
// Path stays the same - Storybook uses title, not file path
Story Co-location Benefits
- Stories live next to components
- Easy to find component documentation
- Stories can import from
./ComponentName(same directory) - Better organization in Storybook sidebar
Story Import Updates
When components move to subdirectories:
Before:
// GraphMenuBar.stories.tsx
import { GraphMenuBar } from './GraphMenuBar';
After:
// GraphMenuBar/GraphMenuBar.stories.tsx
import { GraphMenuBar } from './GraphMenuBar'; // Same directory
// OR
import { GraphMenuBar } from '.'; // From index.tsx
Migration Checklist
Phase 0: Reorganization (Before Refactoring)
- Create subdirectories for existing components
- Move component files to subdirectories
- Create index.tsx files for each component
- Move stories to component subdirectories
- Create hooks/ subdirectory
- Move hooks to hooks/ subdirectory
- Create hooks/index.ts
- Create utils/ subdirectory (if needed)
- Update all imports in GraphRenderer
- Update all imports in stories
- Update all imports in tests
- Audit blog posts and docs for Graph component imports
- Update import paths in blog posts and docs (if needed)
- Build Docusaurus:
make build - Verify all pages with Graph components render correctly
- Test interactive features in blog posts/docs
- Run tests:
yarn test - Run E2E tests:
yarn test:e2e - Verify Storybook stories work
- Update Storybook story paths if needed
- Test in Docusaurus
- Code review
- Merge
For Each Refactoring Phase:
- Create new file(s) in appropriate subdirectory
- Move code to new file(s)
- Create index.tsx if new component
- Create stories in component subdirectory
- Update imports in GraphRenderer
- Update imports in stories
- Update imports in tests
- Build Docusaurus:
make build - Verify blog posts/docs with Graph components still work
- Test interactive features in blog posts/docs
- Run tests
- Check Storybook stories
- Test in Docusaurus
- Update documentation (if API changes)
- Code review
- Merge
Success Criteria
- ✅ GraphRenderer.tsx reduced to < 500 lines
- ✅ All existing functionality preserved
- ✅ No performance degradation
- ✅ All tests passing
- ✅ Storybook stories working
- ✅ Docusaurus integration working
- ✅ Code review approved
- ✅ Documentation updated
Notes
- Incremental Approach: Each phase is independent and can be merged separately
- Backward Compatibility: Maintain existing public API
- Type Safety: Ensure all extracted code is properly typed
- Performance: Monitor for any performance regressions
- Documentation: Update JSDoc comments as code moves
Potential Challenges
- Circular Dependencies: Watch for circular imports between utilities
- Hook Dependencies: Ensure all hook dependencies are correctly passed
- Ref Management: Graph ref needs careful handling across hooks
- State Synchronization: Ensure state updates don't cause infinite loops
- Event Handler Context: Ensure event handlers have correct context
Future Improvements (Post-Refactoring)
- Consider extracting ForceGraph2D wrapper to separate component
- Consider using React Context for graph state (if needed)
- Consider memoization optimizations
- Consider TypeScript strict mode improvements
- Consider adding more comprehensive error boundaries
Execution Results / Attempts
✅ Work In Progress (2025-11-08 to 2025-11-17)
Work Period: November 8, 2025 to November 17, 2025
Commits: 10 commits related to graph component refactoring
Key Accomplishments:
- Initial graph component implementation
- Added menu bar to graph component
- Made graph component reactive/responsive
- Added anchor links to specific nodes in graphs
- Added integration and E2E tests for graph component
- Checkpointed graph renderer refactoring work
- Finalized graph component as part of blog structure overhaul
- Revamped graph component with modularization
- Added Storybook tab to document components
- Improved graph rendering on mobile devices
Notable Commits:
a64d629e(2025-11-08): Updating authors and adding graph component plus stats structures and algos7333d884(2025-11-08): Making graph component reactived2e8bf6d(2025-11-08): Adding menu bar to graph component92e82a04(2025-11-08): Added ability to have anchor links to specific nodes in specific graphsf57ee652(2025-11-10): Adding integ and e2e tests for graph componentb5c58a8a(2025-11-10): Checkpointing graph renderercca8ae25(2025-11-12): Big blog structure overhaul + finalization of graph componente657ebde(2025-11-12): Revamp to readmes plus fix for graph7634d68b(2025-11-16): Revamping graph component, modularizing it, etc. Also added storybook tab to document components6ec4aaac(2025-11-17): Revamp component setup, story book stories, graph render on mobile, etc
Status: Work is in progress. The graph component has been significantly refactored and modularized, with Storybook integration added for documentation. Mobile responsiveness has been improved. Further refactoring work continues based on the comprehensive plan outlined above.