Skip to content

Repository files navigation

ChatTree

English | 简体中文

A non-linear tree-based chat interface for any OpenAI-compatible LLM provider.

Conversations are displayed as a tree. Branch at any node, merge paths back together, and explore multiple ideas in parallel without losing context.

ChatTree screenshot


✨ Feature Highlights

Feature Description
🌳 Tree-based conversations Branch from any node and explore multiple directions independently while preserving context
🔀 Branch merging Merge 2+ nodes in one click, with per-branch context strategies (raw / milestone / condensed)
🗂️ Canvas artifacts Place text/image artifact nodes on the canvas and inject them into merged prompts
🖼️ Multimodal support Upload images and automatically detect vision capability (OpenRouter/OpenAI compatible)
📎 File attachments Parse PDF, Word, Excel, TXT, and more on the client and inject content into prompts
✏️ Edit propagation Edit any node and automatically regenerate all downstream child nodes
🔍 Focus mode Double-click a node to enter fullscreen mode with up/down navigation
📖 Linear view Side panel shows the active path in classic chat bubbles with streaming and collapsible thinking blocks
📍 Milestone navigation Visual timeline marks branch/merge points for quick jumping
🔌 Provider-agnostic API Works with OpenRouter, OpenAI, Ollama, LM Studio, and any OpenAI-compatible endpoint
💾 Local-only storage All data stays in browser localStorage; nothing is uploaded to a server
🔗 Stateless sharing Entire conversation tree is gzip-compressed and encoded into the URL
🌐 Bilingual UI Switch between Chinese and English in Settings

🚀 Quick Start

# 1) Clone the repository
git clone https://github.com/yourusername/ChatTree.git
cd ChatTree

# 2) Install dependencies
npm install

# 3) Start development server
npm run dev

Open http://localhost:3000, then fill in your API key in Settings.


⚙️ API Configuration

Option A: .env file (server-side proxy)

Create .env at the repository root:

OPENAI_API_KEY=sk-your-key-here

The key is used through a Next.js API route proxy and is not exposed to the client.

Option B: Settings panel (direct client connection)

  1. Open ⚙️ Settings in the sidebar
  2. Fill in API Key and API URL (leave URL empty to use OpenAI default)
  3. Click 🔄 Sync to fetch model list
  4. Enable 🙈 to persist the key in browser storage

⚠️ In direct client mode, your key is sent directly to the provider.

Local model endpoints

Service API URL
Ollama http://localhost:11434/v1
LM Studio http://localhost:1234/v1
Any OpenAI-compatible service your endpoint + /v1

🏗️ Tech Stack

Technology Version Purpose
Next.js 16 App framework (App Router + Turbopack)
React 19 UI framework
ReactFlow 11 Tree/canvas rendering
MUI 7 Component library
pako 2 gzip compression for share links
react-dnd 16 Drag-and-drop ordering
markdown-to-jsx 9 Markdown rendering (code highlight, LaTeX, Mermaid)
KaTeX (CDN) latest Math formula rendering

📁 Project Structure

chattree/
├── src/
│   ├── app/
│   │   ├── api/chat/route.js       # Next.js API route (server-side key proxy)
│   │   ├── privacy/page.js         # Privacy policy page
│   │   ├── layout.js               # Global layout (fonts, metadata)
│   │   └── page.js                 # Entry page mounting <TreeChat />
│   │
│   ├── components/                 # React components (see doc/components.md)
│   │   ├── TreeChat.js             # Main app container and state hub
│   │   ├── ChatNode.js             # Conversation tree node card
│   │   ├── ArtifactNode.js         # Canvas artifact node
│   │   ├── LinearChatView.js       # Linear chat view + milestone sidebar
│   │   ├── InputPanel.js           # Message input panel (including merge config)
│   │   ├── InfoPanel.js            # Left sidebar (conversation list)
│   │   ├── SettingsModal.js        # Settings modal
│   │   ├── ModelSelector.js        # Model picker (search/favorites)
│   │   ├── MergeEdge.js            # Custom ReactFlow merge edge
│   │   ├── FocusModeOverlay.js     # Fullscreen focus overlay
│   │   ├── MarkdownContent.js      # Markdown rendering (code/LaTeX/Mermaid/SVG)
│   │   └── ...                     # Other helper components
│   │
│   ├── hooks/                      # Custom React hooks (see doc/hooks.md)
│   │   ├── useChatApi.js           # Streaming LLM requests (SSE parsing)
│   │   ├── useChatManagement.js    # Conversation list CRUD
│   │   ├── useNodeOperations.js    # Node CRUD, merge, cascade regeneration
│   │   ├── useFocusMode.js         # Focus mode keyboard navigation
│   │   ├── useGroupedChats.js      # Grouped conversation canvas
│   │   └── useModels.js            # Model list fetch + cache
│   │
│   └── utils/                      # Pure utility functions
│       ├── constants.js            # Global constants/defaults
│       ├── storage.js              # localStorage access (with quota fallback)
│       ├── treeUtils.js            # Tree traversal + prompt context building
│       ├── sharing.js              # URL share encode/decode (gzip + base64)
│       ├── fileParser.js           # Client-side file parsing
│       └── visionModels.js         # Vision capability detection
│
├── doc/                            # Standalone documentation
│   ├── components.md               # Component architecture details
│   ├── hooks.md                    # Hook reference
│   ├── storage.md                  # Storage strategy and fallback
│   ├── merge-context.md            # Merge context strategy
│   └── sc.png                      # UI screenshot
│
├── public/                         # Static assets
├── next.config.mjs
└── package.json

🛠️ Development

# Development (Turbopack hot reload)
npm run dev

# Production build
npm run build

# Run production build locally
npm run start

# Lint
npm run lint

# Deploy to GitHub Pages
npm run deploy

For more details, see the doc/ directory:


🔒 Security & Privacy

ChatTree is designed with a client-first, privacy-preserving architecture:

  • API key isolation and local storage: API keys are stored in a dedicated localStorage key, separate from chat data. If persistence is disabled in Settings, the key is cleared when the page is closed.
  • Sandboxed HTML preview: HTML preview uses a sandboxed iframe without allow-same-origin (sandbox="allow-scripts"), so preview content cannot access parent window localStorage.
  • Safe SVG rendering: SVG content is rendered via URL-encoded <img> loading rather than dangerouslySetInnerHTML, preventing script execution.
  • Strict Mermaid security: Mermaid is configured with strict security mode (securityLevel: "strict") to block script/HTML injection.
  • Stateless sharing: Shared trees are encoded locally (gzip + URL-safe base64) with no backend storage requirement.

📄 License

Apache-2.0

About

A non-linear tree-based chat interface for any LLM. Branch off and merge conversation paths.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages