Thanks for your interest in contributing to Ripple! This guide covers development setup, architecture, code conventions, and testing.
You will need Node.js (for building the extension) and Python with JupyterLab >= 4.0.0.
The jlpm command is JupyterLab's pinned version of
yarn that is installed with JupyterLab. You may use
yarn or npm in lieu of jlpm below.
# Clone the repo
git clone https://github.com/orbrx/jupyterlab-ripple.git
cd jupyterlab-ripple
# Create a virtual environment and install in development mode
python -m venv .venv
source .venv/bin/activate
pip install --editable "."
# Link the development version with JupyterLab
jupyter labextension develop . --overwrite
# Build the extension
jlpm buildjlpm install # Install dependencies
jlpm build:lib # Compile TypeScript only
jlpm build # Full build (lib + labextension)
jlpm watch # Watch mode for developmentFor active development, run jlpm watch in one terminal and JupyterLab in
another — the extension rebuilds automatically when source files change:
# Terminal 1
jlpm watch
# Terminal 2
jupyter labRipple replaces JupyterLab's default INotebookCellExecutor plugin with a
reactive version that intercepts cell execution and automatically re-runs
downstream dependent cells.
| File | Responsibility |
|---|---|
src/index.ts |
Plugin registration (two plugins: executor + UI) |
src/dag.ts |
Dependency graph, topological sort (Kahn's algorithm), cycle detection (Tarjan's SCC) |
src/analyzer.ts |
Kernel-side Python AST analysis via silent requestExecute |
src/reactiveState.ts |
Per-notebook state: analysis cache, graph, stale/conflict tracking |
src/reactiveCellExecutor.ts |
Custom INotebookCellExecutor wrapping default runCell |
src/ui/toggleButton.ts |
Toolbar toggle button and command registration |
src/ui/dependencyIndicators.ts |
CSS class management for visual cell indicators |
- Topological sort — Kahn's algorithm in
getDownstreamCells()determines execution order for downstream dependents - Cycle detection — Tarjan's strongly connected components in
detectCycles()identifies circular dependencies - AST analysis — Python
ast.parse()sent as a silent kernel execution extracts variable definitions and references per cell
- User executes a cell
ReactiveCellExecutor.runCell()delegates to the defaultrunCell- If reactive mode is on, re-analyzes the cell via
analyzeCell()(kernel-side AST) - Rebuilds the dependency graph via
buildGraph() - Gets downstream cells in topological order via
getDownstreamCells() - Executes each downstream cell sequentially via default
runCell
- Single quotes, no trailing commas, arrow parens avoided (Prettier config in
package.json) - Interfaces prefixed with
I(e.g.,ICellAnalysis,IDependencyGraph) - Private members prefixed with
_(Lumino convention) - Use
console.warn()for operational messages,console.error()for errors — noconsole.log() - Import types with
import typewhere possible
This extension uses Jest for JavaScript code testing:
jlpm testIntegration tests use Playwright with the JupyterLab helper Galata.
See ui-tests/README.md for details.
jlpm lint # Auto-fix ESLint, Prettier, and Stylelint issues
jlpm lint:check # Verify everything is clean (runs in CI)Run jlpm lint before committing — Prettier formatting drift will fail CI.
See RELEASE.md.