CLI tool
andrewcourtice/ripl avatar
andrewcourtice/ripl

Ripl: one TypeScript scene graph that renders to Canvas, SVG, terminal or WebGPU

Ripl provides a unified, cross-platform API for 2D and 3D graphics rendering with a focus on high performance and interactive data visualization. Write once, render to Canvas, SVG, WebGPU, or the terminal - in the browser, on the server, or in a headless environment.

328 stars7 forksTypeScriptMIT

At a glance

What is it?
Ripl is a zero-dependency TypeScript charting, drawing and animation library that puts a DOM-like API over Canvas, SVG, terminal and WebGPU contexts. The same scene renders anywhere, but the abstraction has edges worth knowing before you commit.
Who is it for?
Adopt Ripl if you need the same scene to appear in a browser canvas, as SVG markup, in a terminal, or in a headless Node process, and you accept the monorepo's Node 24.18.1 floor plus a Yarn 4 toolchain. Do not adopt it if you need server-side raster output or a rendering backend the package table does not list, because the README does not document that path.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 16 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The Canvas-or-SVG decision Ripl removes

Canvas and SVG diverge enough that most projects pick one at the start and stay there. The README frames this as the problem Ripl exists to solve: the Canvas API has no concept of objects, hierarchy or events, while SVG is easier to reason about but carries its own performance limits and API differences. Ripl exposes one API over both, modelled on the DOM and CSSOM, so switching between them is described as a one-line change. That claim is the whole product. If you are building a dashboard that must work as an interactive canvas in the browser and as static SVG markup in a report, the two rendering paths no longer need two codebases. The audience is TypeScript developers building charts, drawings or animated scenes who expect to change rendering target at least once, or who need a terminal or headless output alongside a browser one.

How the scene graph, renderer and contexts fit together

The architecture is a hoisted scenegraph with a renderer on top and pluggable contexts underneath. Elements carry visual properties that cascade through the tree the way CSS does, so a group can set a colour or transform and its children inherit it. Rendering is described as O(n), with an automatic requestAnimationFrame loop driving the frame cycle. Events bubble, can be delegated, and support stop propagation with disposable subscriptions, which is the DOM model transplanted onto shapes. Querying follows the same analogy: getElementById, getElementsByType, getElementsByClass, plus query and queryAll with selector syntax. A Navigator handles pan, zoom and brush gestures on flat contexts, positioned as the 2D analogue of the 3D camera. Transforms, path-based clipping, shadows, filters, blend modes, gradients and pattern fills are element-level properties, not per-context special cases. The 3D side adds a camera, five light types, Blinn-Phong materials with specular and shininess, textures with wrap and filter modes, fog, and triangle raycasting that reports the shape, world-space point, face, normal and texture coordinate of each hit. Both 3D backends resolve fog term for term, which is the kind of detail that usually drifts between implementations.

Installing Ripl and rendering a first scene

The README names @ripl/web as the main entry point for browser usage, re-exporting core plus the canvas context with browser platform bindings. The repository is a Yarn 4 monorepo whose root package.json declares [email protected] as the package manager and requires Node 24.18.1 or newer, so check your runtime before anything else. Installing a package looks like this:

bash
yarn add @ripl/web

For a headless or server-side run, the package table points at @ripl/node, described as Node.js runtime bindings that configure the platform factory for headless environments. The terminal context lives in @ripl/terminal and renders braille characters with ANSI truecolor. To build the repository itself rather than consume it, the root scripts are lerna-driven:

bash
yarn install
yarn build
yarn test

The README does not print a complete minimal scene in the section available here, so the honest first step is the homepage at ripl.run and the packages directory, where each package carries its own README. What you should expect after install is a scene you construct from the built-in primitives (arc, circle, rect, line, polyline, polygon, ellipse, text, path, image), attach to a context, and hand to the renderer. Exporting is covered by the context export feature: snapshot any context to ImageData, an object URL, or a string, which means PNG data URL from Canvas, SVG markup from the SVG context, and terminal text from the terminal context.

Where the unified API costs you

One API over four backends means the API can only expose what all four can do. The terminal context is the clearest constraint: braille characters and ANSI truecolor are a coarse output medium, so a scene tuned for WebGPU will not translate down without visual loss. The README does not document what happens to gradients, blend modes, shadows or textures when a scene is rendered to the terminal, and that silence is worth testing early if terminal output is a requirement rather than a curiosity. The same question applies to WebGPU: the package description mentions hardware depth testing and WGSL shaders, which are capabilities the Canvas 3D context cannot match, so a scene relying on them is not portable back to Canvas. Feature parity across contexts is the promise; per-context capability differences are the reality the feature list implies. There is also a runtime floor. Node 24.18.1 is recent, and a project pinned to an older LTS cannot build the monorepo or run the Node bindings without upgrading. Finally, the Navigator for pan, zoom and brush is described as working on any context, but gesture handling in a terminal is a different proposition from a browser, and the README does not spell out how input reaches a headless process.

How Ripl differs from D3 and from charting wrappers

The scales are explicitly inspired by D3, and the list is long: 14 scale types covering continuous, discrete, ordinal, band, point, diverging, logarithmic, symmetric-log, power, radial, quantile, quantize, threshold and time, plus scaleLog and scaleSqrt shortcuts. But the difference in approach is where the rendering lives. D3 generates SVG or manipulates canvas directly; the output medium is your responsibility, and the scales and shapes are the library. Ripl inverts that. It keeps a live scenegraph, owns the render loop, and treats the output context as a swappable backend, with 25 pre-built chart types in @ripl/charts covering line, bar, area, trend, scatter, histogram, box plot, stock, realtime, pie, polar, radial bar, radar, gauge, heatmap, treemap, sunburst, packed circle, sankey, chord, arc diagram, force-directed, funnel and gantt. If you want to compose primitives yourself and control every emitted element, D3's model is more direct. If you want a scene that survives a change of renderer, Ripl's model is the one built for it. Against thin wrappers around a single charting engine, the difference is the same: those bind you to one output, and Ripl's whole reason to exist is not doing that.

Maintenance, licence and what an upgrade costs

The repository is not archived, and the last push was on 2026-08-11, the same day v1.3.0 was released. v1.2.0 landed on 2026-08-06 and v1.0.0 on 2026-07-23, so the release cadence has been tight in that window. That is a short history: v1.0.0 is roughly three weeks older than v1.3.0, which means the API stabilised recently and pre-1.0 churn is not far behind you. Budget for reading CHANGELOG.md between minor versions rather than assuming additive-only changes. The licence is MIT, declared in the root package.json and present as a LICENSE file. MIT is permissive, but the repository also ships assets/ and apps/, and the README does not state that every bundled asset carries the same terms, so check the LICENSE file and the assets directory before redistributing anything beyond the npm packages. The workspace is private and versioned at 1.0.0 independently of the individual packages, which are published through lerna from-package. For consumers, that means version numbers on npm are per package, not per repository release, and pinning to @ripl/web alone will not pin the transitive @ripl/core behaviour.

Deciding whether Ripl fits your project

The strongest case is a codebase that must produce the same visual scene in more than one medium: an interactive canvas in the browser, SVG markup for export, braille output in a terminal, and a headless Node run for tests or batch work. The zero-dependency claim matters there, because it keeps the install surface small and the bundle tree-shakable, and the modular package split means a project that only needs 2D Canvas is not forced to pull in WebGPU. The weakest case is a project that has already committed to one renderer and one output format. If everything is SVG and stays SVG, Ripl's abstraction layer is overhead, and D3's directness will be easier to reason about. If everything is WebGPU and needs hardware depth testing, the unified API is not buying you anything either. The middle case, a charting application that needs 25 chart types and a live render loop without writing the animation, scales and interpolation machinery, is where @ripl/charts earns its place, provided one of the 25 matches what you need.

Editorial conclusion

Adopt Ripl if you need the same scene to appear in a browser canvas, as SVG markup, in a terminal, or in a headless Node process, and you accept the monorepo's Node 24.18.1 floor plus a Yarn 4 toolchain. Do not adopt it if you need server-side raster output or a rendering backend the package table does not list, because the README does not document that path. Before writing production code, check the @ripl/charts package for the chart type you need, confirm whether your target context has a Navigator for pan and zoom, and read the LICENSE file rather than assuming the MIT label covers every bundled asset.

Frequently asked questions

What is Ripl and what problem does it solve?

Ripl is a zero-dependency TypeScript charting, drawing and animation library built on a unified API for 2D graphics rendering. It lets you write a scene once and render it to Canvas, SVG, a terminal, or a Node process, with 3D on Canvas and WebGPU alongside, so you do not have to commit to Canvas or SVG at the outset.

How do I install Ripl?

For browser usage the README names @ripl/web as the main entry point, re-exporting core plus the canvas context with browser platform bindings. Headless environments use @ripl/node, which configures the platform factory for Node. The repository itself is a Yarn 4 monorepo that requires Node 24.18.1 or newer.

Which rendering contexts does Ripl support?

The package table lists @ripl/canvas for Canvas 2D, @ripl/svg for SVG, @ripl/terminal for braille output with ANSI truecolor, @ripl/3d for 3D on Canvas, and @ripl/webgpu for WebGPU-accelerated 3D with hardware depth testing and WGSL shaders. @ripl/node provides runtime bindings for headless environments.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
For maintainers

Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/andrewcourtice-ripl.svg)](https://hysenlabs.com/projects/andrewcourtice-ripl)
Community notes

Community notes