About the vellum ecosystem
One ecosystem, four packages
vellum is a family of R packages for drawing, built around a shared scene model and a common design. The metaphor runs through the names: vellum is the parchment, vellumplot is the pen, and vellumwidget is the annotation revealed on the page.
| Package | Role | Analogue |
|---|---|---|
| vellum | Low-level graphics framework: units, viewports, grobs, layout, and PNG/SVG/PDF rendering, with the scene graph and renderers implemented in Rust. | grid |
| vellumplot | A declarative, pipe-first grammar of graphics that compiles an inspectable plot spec into a vellum scene. | ggplot2 |
| vellumwidget | Client-side interactive HTML widgets over a vellum scene: hover, select, brush, and zoom, read from the scene’s own geometry. | plotly / htmlwidgets |
| vellumverse | A meta-package that installs and loads the whole ecosystem together. | tidyverse |
One seam
The three packages are worth using together because they share a single joint. vellum measures text and solves layout without opening a device, so a compiled scene can report where everything landed: scene_model() gives one row per drawn element with its data key and resolved device-pixel box, and element_geometry() gives the true vertices behind that box. vellumplot compiles a plot spec into such a scene. vellumwidget hosts that same scene in a browser, reading the table rather than re-drawing anything.
So one specification yields a static figure, a vector file, and an interactive widget that cannot disagree about geometry, because there is one solved layout behind all three.
What that buys you
Everything below needs the geometry to exist before the draw, which a device-driven stack cannot offer:
- Read the figure back: ask the scene where every mark, label, and panel landed, with nothing drawn.
- Fit text to a box: wrap a label to a measure and shrink it until the block fits, re-wrapping at each probe. Long titles and long discrete axis labels wrap on the same rule.
- Move colliding labels apart in the engine. Placement is solved in device pixels and applied as an absolute offset, so faceted, polar, and warped panels are handled in one pass.
- Lint a figure before anyone sees it: text below a legibility floor, colour contrast under the WCAG threshold, a mark that will never be painted.
- Treat a scene as a value. Hash it, diff it, nest one inside another. A structural diff beats an image diff, because it is immune to the font stack.
- Ship accessible output: simulate colour-vision deficiency in the render, encode redundantly with real hatch geometry, and emit a tagged PDF a screen reader can navigate.
Some capabilities have no device-driven equivalent at all: text set along a curve, boolean path operations on real geometry, contours chained into polylines, SVG icon paths as crisp vector markers, animated SVG, multi-page PDF, and font pinning that makes “identical pixels everywhere” checkable rather than claimed.
Rendering is deterministic, so the same scene is byte-identical across platforms and figures can be snapshot-tested. The paint model covers gradients, tiling patterns, alpha and luminance masks, group opacity, blend modes, and real Gaussian blur. Large point clouds go through built-in aggregation with datashade(), and sketch() gives a hand-drawn look that is generated in the engine, so it is identical on every backend.
Pipe-first, ggplot2-adjacent
If you know ggplot2 the vocabulary will feel familiar (mark_point(), scale_color_continuous(), facet_wrap(), theme_minimal()), but plots are composed with the native pipe |> rather than +, and aesthetics are plain named arguments on each mark, with no aes():
library(vellumplot)
vplot(mtcars) |>
mark_point(x = wt, y = mpg, color = hp) |>
scale_color_continuous()About this gallery
Every example on this site is real, runnable code, rendered by vellumplot on the vellum backend and frozen into the site so the deployment never has to rebuild the Rust engine. The site is built with Quarto and styled to match the ecosystem’s pkgdown pages (a parchment and sepia palette, set in Spectral).
Source lives at r-vellum/vellumgallery.