Interactive notebook platform for data visualization. Built on the Celine runtime with Observable Plot, D3, Alpine.js, and Pyodide. Deno-native.
# Start the development server
deno task dev
# Server runs at http://localhost:8030- Code — JavaScript/TypeScript cells running in the Observable Runtime. Full access to Plot, D3, htl, and Inputs.
- Markdown — Rich text cells with CommonMark rendering.
- Python — Python cells via Pyodide (CPython in WebAssembly). NumPy, pandas, scipy, scikit-learn, and 100+ packages available.
Cells can be named to create reactive dependencies using @variable syntax. Execution is topological — cells re-run when their dependencies change, regardless of document order.
// Cell named "params"
return { amplitude: 3, frequency: 1.5 };
// Another cell — automatically re-executes when params changes
const { amplitude, frequency } = @params;
return Plot.plot({ marks: [Plot.line(data, { x: "t", y: d => amplitude * Math.sin(frequency * d.t) })] });Marimo-style reactive inputs that drive downstream cells:
// Slider, dropdown, color picker, buttons
return Inputs.range([0, 10], { label: "Amplitude", step: 0.1, value: 3 });- Arrays of objects → searchable, sortable, paginated data table
- Plain objects → JSON viewer with syntax highlighting
- DOM nodes → direct render (charts, HTML elements)
- Markdown → rendered HTML
- Errors → formatted stack traces
Load CSV, JSON, JSONL, TSV, Markdown, and plain text files. Data files are served from the data/ directory and accessible as @filename variables in any notebook.
// Fetch directly
const data = await fetch('/data/aapl.csv').then(r => r.text());
// Or reference by @slug (auto-parsed)
const stocks = @aapl;Upload data via the UI with drag-and-drop or the inline Monaco editor.
Observable Plot (primary) — 30+ mark types including line, bar, dot, area, cell (heatmap), box, density, contour, tree, geo, image, vector, waffle, and more. Faceting, scales, tips, crosshairs, and trend lines built in.
D3 — Full D3 v7+ for custom SVG visualizations, layouts (pie, sankey, treemap, force), geo projections, and scales.
Built-in globals: Plot, d3, htl, Inputs, notebook
Generate visualization code from natural language. Supports Anthropic Claude, OpenAI, and Groq as inference providers. The AI has context about your notebook cells, @variables, and available data files.
# Configure in .env
ANTHROPIC_API_KEY=sk-...
OPENAI_API_KEY=sk-...
INFERENCE_PROVIDER=anthropic # or "openai", "groq", "custom"
# Custom OpenAI-compatible provider (OpenRouter, Together, local, etc.)
CUSTOM_API_KEY=sk-...
CUSTOM_BASE_URL=https://openrouter.ai/api/v1
CUSTOM_MODEL=gpt-4oAPI keys can also be configured in the UI settings panel (stored in browser localStorage).
Full CPython via Pyodide — no server required. First load downloads the runtime (~10MB, cached), then cells reuse the interpreter.
// Cell named "py" — loads Pyodide once
const pyodide = await loadPyodide();
return { run, runWithPackages };
// Other cells use @py
const result = await @py.runWithPackages(['numpy', 'pandas'], `
import numpy as np
import pandas as pd
df = pd.DataFrame({'x': np.random.randn(100)})
df.describe().to_dict()
`);Server-side Python execution is also available via UV (POST /api/python).
Eclair ships with built-in example notebooks demonstrating key capabilities:
| Notebook | Highlights |
|---|---|
| Data Visualization Basics | Line charts, heatmaps, data-driven styling |
| Science Examples | Volcano plots, phage-bacteria heatmaps, linked growth curves |
| Working with APIs | REST API fetching, data tables, penguins scatterplot |
| Stock Charts | Candlestick, Bollinger Bands, MACD/RSI, Bloomberg-style dashboards |
| Reactive Cells Demo | Sine wave with reactive parameters, chained dependencies |
| Interactive Inputs Demo | Sliders, color pickers, dropdowns driving reactive plots |
| Micrograd Neural Network | Autograd engine, MLP training, decision boundary visualization |
| Python in the Browser | NumPy stats, pandas DataFrames, classic algorithms |
Plus 52 standalone example snippets covering financial charts, scientific visualizations, network graphs, maps, diagrams, and more.
- Notebooks —
.notebook.jsonfiles with acellsarray - Pages —
.page.htmlfiles for custom HTML dashboards - Slides —
.slides.htmlfiles for presentations - Documents —
.doc.mdfiles for markdown documentation
All content types appear in the sidebar and are served from the notebooks/ directory.
deno task export:html # All notebooks → offline HTMLThree HTML export modes:
| Mode | Flag | Description |
|---|---|---|
| Self-contained | --self-contained |
All JS/CSS inlined, offline-ready |
| Lite-runner | --lite-runner |
Interactive CodeMirror editors with run buttons |
| Full-bundle | --full-bundle |
Lite-runner + all dependencies bundled (no CDN) |
deno task export:examples # All examples → PNG
deno task export:examples --format svg # All examples → SVG
deno task export:pdf # Notebook → PDF
# Single notebook/cell
deno run -A cli/export.ts -i notebook.json --all -o ./images/
deno run -A cli/export.ts -i notebook.json -c cell-id -o cell.pngPOST /api/export/cell-image # Single cell → PNG/SVG
POST /api/export/pdf # Notebook → PDF| Option | Alias | Default | Description |
|---|---|---|---|
--output <dir> |
-o |
./examples/images |
Output directory |
--format <fmt> |
-f |
png |
png, svg, or pdf |
--width <px> |
-w |
800 |
Output width in pixels |
--caption |
-c |
false |
Include description as caption |
--self-contained |
false |
Inline all dependencies | |
--lite-runner |
false |
Interactive export with editors | |
--full-bundle |
false |
Fully offline interactive export | |
--all-notebooks |
false |
Export all notebooks in directory | |
--root <path> |
. |
Project root for content resolution |
Use Eclair in your own projects at three levels:
Run Eclair's server pointing at your project directory:
deno run -A jsr:@yawnxyz/eclair --root .Your project provides notebooks/ and data/; Eclair provides the UI, runtime, and AI chat.
Import the Celine runtime directly from JSR to embed charts in your own app:
<script type="module">
import { Runtime } from "https://esm.sh/jsr/@celine/celine";
</script>Generate self-contained HTML files from notebooks — no server needed to view:
deno run -A jsr:@yawnxyz/eclair/export --all-notebooks --self-contained --root . -o ./export/See templates/ for starter projects at each tier.
Create an eclair.config.ts at your project root:
export default {
project: "My Project",
data: { liveBundle: "path/to/data" },
server: { port: 8030 }
};The notebook runtime includes library loaders for:
- Leaflet (
celine.library.L()) — Interactive maps - Mermaid (
celine.library.mermaid()) — Flowcharts and diagrams - Graphviz (
celine.library.dot()) — DOT language graphs - KaTeX (
celine.library.tex()) — LaTeX equations - Marked (
celine.library.md()) — Markdown rendering
| Endpoint | Description |
|---|---|
GET / |
Serve frontend |
GET /api/tree |
Notebook directory tree |
GET /api/config |
Project configuration |
GET /data/:filename |
Serve data files |
POST /api/chat |
AI chat (Claude/Groq) |
POST /api/execute |
Run JS in isolated Deno subprocess |
POST /api/python |
Run Python via UV |
POST /api/fetch |
CORS-friendly fetch proxy with caching |
POST /api/export/cell-image |
Export cell as PNG/SVG |
POST /api/export/pdf |
Export notebook as PDF |
GET /api/cache/stats |
Cache hit/miss stats |
POST /api/cache/clear |
Clear fetch cache |
eclair/
├── main.ts # Hono server entry point
├── cli/
│ ├── export.ts # Export CLI (PNG, SVG, PDF, HTML)
│ ├── export-examples.ts # Batch example export
│ ├── self-contained.ts # Inline all dependencies for offline HTML
│ └── lite-runner-runtime.ts # Interactive export runtime (CodeMirror)
├── frontend/
│ └── src/html/
│ ├── partials/ # HTML partials (sidebar, chat, settings, modals)
│ └── index.template.html
├── notebooks/
│ └── examples/ # Built-in example notebooks
├── examples/
│ ├── *.example.json # 52 example snippets
│ └── images/ # Exported example images
├── data/ # Sample data files (CSV, JSON, TSV)
├── src/
│ ├── inference.ts # AI provider abstraction
│ ├── config.ts # Project config loader
│ ├── cache/ # In-memory fetch cache
│ └── queue/ # Task queue with concurrency limits
├── templates/ # Starter projects for each adoption tier
└── docs/ # Architecture and guide documentation
deno task dev # Dev server with watch mode
deno task build:html # Build frontend from partials
deno task serve # Production server
deno task test # Run tests
deno fmt # Format code
deno check main.ts # Type check| Variable | Default | Description |
|---|---|---|
ANTHROPIC_API_KEY |
— | Claude API key for AI chat |
OPENAI_API_KEY |
— | OpenAI API key |
GROQ_API_KEY |
— | Groq API key (alternative provider) |
INFERENCE_PROVIDER |
anthropic |
"anthropic", "openai", "groq", or "custom" |
ANTHROPIC_MODEL |
claude-sonnet-4-20250514 |
Override default Anthropic model |
OPENAI_MODEL |
gpt-5.4 |
Override default OpenAI model |
GROQ_MODEL |
llama3-70b-8192 |
Override default Groq model |
CUSTOM_API_KEY |
— | API key for custom OpenAI-compatible provider |
CUSTOM_BASE_URL |
— | Base URL for custom provider |
CUSTOM_MODEL |
gpt-4o |
Model name for custom provider |
PORT |
8030 |
Server port |
The templates/ directory contains starter files for each adoption tier:
Templates are available in the templates/ directory or from the GitHub repo:
# Download templates from GitHub
# https://github.com/janzheng/eclair/tree/main/templatesAn agent skill template is also included for projects that use AI coding assistants (Claude Code, etc.):
# Copy the skill into your project
mkdir -p skills/eclair
# Download SKILL.md from https://github.com/janzheng/eclair/tree/main/templates/skillTo give Claude Code knowledge of Eclair's notebook format and APIs, install the agent skill into your project:
# From your project directory
mkdir -p .claude/skills/eclair
# Download SKILL.md from https://github.com/janzheng/eclair/blob/main/templates/skill/SKILL.mdOnce installed, Claude Code will automatically use the skill when working with .notebook.json files, data references, and export commands.