About the vellum ecosystem

What vellum is, how the pieces fit together, and how this gallery is built.

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 backend: a retained scene graph, a unit/layout engine, and PNG/SVG/PDF rendering, all running in a Rust engine. 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 built from a vellum scene: hover, select, brush, and zoom, with no server. plotly / htmlwidgets
vellumverse A meta-package that installs and loads the whole ecosystem together. tidyverse

What makes it different

vellum’s scene graph, layout solver, and renderers (raster, SVG, PDF) run in Rust through extendr. The rendering is deterministic, so the same scene produces byte-identical output across platforms and graphics can be snapshot-tested. That one scene renders to PNG, SVG, or PDF with the same geometry and text shaping.

A vellumplot plot is a serializable spec, not a picture. Nothing is drawn until it compiles: encodings resolve, scales train, the panel layout is measured, and guides and marks become vellum grobs. The scene it produces is retained rather than drawn immediate-mode, so every element keeps a data key and a bounding box. That is what vellumwidget reads to wire up interactivity in the browser.

The paint model covers gradients, tiling patterns, alpha and luminance masks, group opacity, and blend modes. Large point clouds go through built-in aggregation with datashade(), and sketch() gives a hand-drawn look.

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()
Back to top