Back to .md Directory

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

May 2, 2026
0 downloads
0 views
ai agent claude
View source

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Dash UI is the Next.js frontend for the Dash data agent. It provides a chat interface for data analysis — fetch URLs, query databases, run Python/R, and create charts. Works with any data source, not just SQL.

Commands

# Install dependencies
npm install

# Run development server (port 3000)
npm run dev

# Build for production
npm run build

# Start production server
npm start

Note: The backend API server (FastAPI) must be running on port 8000. See ../dash-repo/ for backend setup.

Architecture

Single-Page Application

The entire UI is in app/page.js (~1750 lines). Key sections:

LinesComponentPurpose
1-90UtilitiesextractChart(), extractD3Chart(), renderMarkdown()
90-270Chart ComponentsChartImage, D3Chart, ImageModal
270-400UI ComponentsIcons, CopyableCode, CodeBlockItem
400-630CodePanelSlide-out panel showing all executed code, export to .py/.R/.ipynb
630-660ContextBoxCollapsible plain text box for data dictionaries/readmes
660-780ToolCallCollapsible tool execution display (SQL, Python, R)
780-940Message ComponentsMessage, StreamingMsg with inline charts
940-1750Home (main)State management, SSE streaming, chat flow, sidebar, Kaggle/TidyTuesday tabs

Data Flow

User Input → POST /chat/stream → SSE Events → UI Updates
                                    ↓
                            tool_start → ToolCall (running)
                            tool_complete → ToolCall (result) + inline Chart
                            delta → Streaming text
                            done → Finalize message

State Management

// In Home component
const [messages, setMessages] = useState([])        // Chat history
const [streamEvents, setStreamEvents] = useState([]) // Current streaming response
const [language, setLanguage] = useState('python')   // Python or R preference
const [conversationId, setConversationId] = useState(null) // Current conversation UUID
const sessionIdRef = useRef(generateSessionId())     // Backend session ID (= conversationId)

Session Isolation

Each conversation gets its own backend session — no cross-contamination:

  • sessionIdRef.current is set to conversationId when a conversation is created or loaded
  • New conversation: generates a fresh sessionIdRef, creates a new conversation via POST /conversations
  • Load old conversation: sets sessionIdRef.current = convId, calls /restore to rebuild agent history
  • Switch conversations: different sessionId = different backend DashAgent instance

Message Format

// User message
{ role: 'user', content: 'Who won most championships?' }

// Assistant message with events (tools + context + text interleaved)
{
  role: 'assistant',
  events: [
    { type: 'tool', tool: { name: 'run_sql', args: {...}, result: '...' } },
    { type: 'context', title: 'Data dictionary', content: '...' },  // collapsible plain text box
    { type: 'text', content: 'Based on the data...' }
  ]
}

Conversations & Permalinks

  • Sidebar lists saved conversations via GET /conversations
  • Clicking a conversation loads it, restores backend agent history, and updates URL to ?c=<uuid>
  • Refreshing or sharing the URL reopens the same conversation
  • New conversations get a URL permalink after the first message is sent
  • "New conversation" generates a fresh session and clears URL back to /
  • Titles are auto-generated by Haiku on the backend after the first user message

Key Features

Chart Rendering

Charts are embedded in tool results using markers:

  • Matplotlib/ggplot2: [CHART_BASE64]<base64>[/CHART_BASE64] → renders as <img>
  • D3.js: [D3_CHART]{"code":"...","data":[...]}}[/D3_CHART] → renders in sandboxed iframe

Code Panel

Right sidebar shows all executed code (SQL, Python, R) with:

  • Individual copy buttons per block
  • Export to .py or .R file with boilerplate (DB setup, imports)
  • Export to .ipynb Jupyter notebook with user/AI markdown cells, code cells, and captured outputs (text results + base64 chart images)
  • Language auto-detection based on tools used

Language Toggle

On home screen, user selects Python or R. This:

  1. Sends language field in API request
  2. Updates CodePanel export format
  3. Backend prepends [USER PREFERS R] to guide tool selection

Dataset Browser (Kaggle & TidyTuesday)

Home screen has three tabs: Presets | Kaggle Datasets | TidyTuesday.

  • Kaggle tab: Searchable, sortable grid of dataset cards fetched via GET /kaggle/datasets backend proxy. Supports pagination ("Load more").
  • TidyTuesday tab: Year-selectable list of weekly datasets from the R4DS GitHub repo via GET /tidytuesday/datasets.
  • Instant-load flow: Clicking a dataset card calls POST /kaggle/load or POST /tidytuesday/load. The backend downloads + explores data directly in CodeInterpreter (no Claude API call), fabricates a conversation with tool events, seeds agent history, and returns pre-populated messages. The frontend sets these as the conversation — user sees results instantly.
  • context event type: Dataset descriptions/readmes are returned as {type: 'context', title, content} events, rendered by ContextBox as a collapsible plain text box (no markdown rendering).

API Integration

// Streaming chat (SSE) — session_id ties to conversation
fetch('http://localhost:8000/chat/stream', {
  method: 'POST',
  body: JSON.stringify({ message, session_id: sessionIdRef.current, language })
})

// Restore agent history when loading a conversation
fetch('http://localhost:8000/restore', {
  method: 'POST',
  body: JSON.stringify({ session_id: convId, messages })
})

SSE Event Types

EventAction
tool_startAdd collapsible ToolCall in "running" state
tool_completeUpdate ToolCall with result, extract/render charts
deltaAppend to streaming text content
doneFinalize message, save to backend, refresh sidebar
errorDisplay error message

Styling

  • Framework: Tailwind CSS v4 with @tailwindcss/postcss
  • Theme: Light/dark mode via CSS custom properties (--ink, --bg, --red, etc.) and @media (prefers-color-scheme: dark)
  • Fonts: Newsreader (serif display), Outfit (sans body), JetBrains Mono (code)
  • Layout: Max-width 3xl centered, responsive code panel, collapsible sidebar
  • User message selection: Uses [data-user-msg] attribute selector in globals.css for visible text selection on dark bubbles (Tailwind v4 purges class-based selectors from CSS files)

File Structure

dash-ui/
├── app/
│   ├── page.js       # All UI components and logic (~1750 lines)
│   ├── layout.js     # Root layout, metadata, font loading
│   └── globals.css   # Design tokens, dark mode, prose styling, animations
├── package.json      # Dependencies: next, react 19, tailwindcss v4
├── postcss.config.js # PostCSS with @tailwindcss/postcss
└── tailwind.config.js

Related Documents