An infinite canvas application for branching AI conversations. Create child conversations by selecting text from AI responses, building a visual tree of related queries and responses.
- π¨ Infinite Canvas: Pan and zoom freely with React Flow
- π³ Text Selection Branching: Select any text to create child conversation nodes
- β‘ Streaming AI Responses: Real-time streaming from OpenRouter API (GPT-4o-mini)
- π Smart Auto-Layout: Dynamic node positioning with collision avoidance
- π Visual Connections: Bezier curves show parent-child relationships (RightβLeft initially, BottomβTop after positioning)
- π Markdown Support: Rich text rendering for AI responses
- π Multi-Canvas Tabs: Create multiple independent conversation canvases
- βοΈ Settings Dialog: Easy API key management via UI
- πΎ Auto-Save: Conversations and settings persist in localStorage
npm installnpm run dev- Open http://localhost:3000
- Click the gear icon (βοΈ) in the top-right corner
- Enter your OpenRouter API key
- Click Save
Get your API key: openrouter.ai/keys
Note: You do NOT need to create a
.env.localfile. All API key management is done through the Settings dialog.
- Type your query in the initial node
- Press Enter
- Watch the AI response stream in real-time
- Select any text in an AI response
- Click the "+" button that appears
- A child node will appear to the right
- Type your follow-up query
- Press Enter - the node will slide below the parent
- Click "+ New Canvas" in the tab bar to create a new workspace
- Each tab has completely independent conversations
- Click the X on a tab to delete it (cannot delete the last tab)
- Pan: Click and drag on the canvas background
- Zoom: Scroll wheel
- Move nodes: Drag from the header area (with grip icon)
- Framework: Next.js 16.0 (App Router, TypeScript)
- Canvas: React Flow 11.11
- State Management: Zustand
- AI API: OpenRouter (GPT-4o-mini with streaming)
- Styling: Tailwind CSS + Shadcn/UI
- Animations: Framer Motion
/components
βββ Canvas.tsx # Main React Flow canvas wrapper
βββ CanvasNode.tsx # Individual conversation node
βββ NodeContent.tsx # Markdown rendering for AI responses
βββ NodeInput.tsx # Query input field
βββ PlusButton.tsx # Text selection "+" button
βββ TabBar.tsx # Multi-canvas tab management
βββ SettingsDialog.tsx # API key configuration
/store
βββ useCanvasStore.ts # Zustand state (tabs, nodes, edges, selections)
/lib
βββ smart-layout.ts # Auto-positioning & collision detection
βββ openrouter.ts # API client
/app/api
βββ chat/route.ts # Streaming SSE endpoint
/types
βββ node.types.ts # TypeScript interfaces
- Initial state: Child nodes appear to the RIGHT of parent with RightβLeft edge
- After Enter press: Child moves BELOW parent, edge switches to BottomβTop
- Smooth animated transitions
- Multiple children from the same parent spread horizontally
- Centered under parent with 40px minimum spacing
- Automatic repositioning when new siblings are added
- Each tab has completely independent state
- Deep cloning prevents cross-tab contamination
- Dimension cache cleared on tab switch
- Real-time collision detection using rectangle overlap
- Automatic position adjustments (40px buffer)
- Pauses during node dragging, resumes after
- Tabs & conversations: Saved to localStorage
- API key: Stored securely in localStorage
- Viewport state: Auto-restored on reload
Currently using openai/gpt-4o-mini. To change the model:
- Edit
/app/api/chat/route.ts:
model: 'openai/gpt-4o-mini', // Change to your preferred model- Available models: openrouter.ai/models
Adjust spacing and dimensions in /lib/smart-layout.ts:
const DEFAULT_CONFIG: LayoutConfig = {
nodeWidth: 600, // Node width (px)
nodeHeight: 250, // Default node height (px)
horizontalGap: 40, // Spacing between siblings (px)
verticalGap: 120, // Spacing between parent and children (px)
collisionBuffer: 40, // Minimum clearance (px)
};- "API Key Required" message: Click gear icon and add your OpenRouter API key
- "Failed to get response": Check browser console for detailed error messages
- Invalid credentials: Verify your API key at openrouter.ai/keys
- Nodes overlapping: Try refreshing the page to reset dimension cache
- Incorrect positioning: Check browser console for errors in smart-layout.ts
- Slow rendering: Large conversation trees (100+ nodes) may experience performance degradation
- Recommended: Keep individual canvases under 50 nodes for optimal performance
β Complete Features:
- Infinite canvas with pan/zoom controls
- Dynamic node creation and text selection
- Streaming AI responses with SSE
- Smart auto-repositioning (right β below)
- Reference text context in child nodes
- Markdown rendering with syntax highlighting
- Tab-based multi-canvas support
- Settings dialog for API key management
- Collision detection and avoidance
- localStorage persistence
- Hydration-safe SSR
Contributions welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
MIT License - feel free to use this project for personal or commercial purposes.
- Built with Claude Code
- Powered by OpenRouter
- UI components from Shadcn/UI
Questions? Open an issue on GitHub or check the documentation in the /docs folder.