starsight
a typed, layered figure compiler for Rust — from zero-config one-liners to GPU-accelerated 3D, eight backends, no global state.
starsight turns a Figure of marks (line, scatter, bar, area, histogram, heatmap, box-plot, violin, KDE, pie, contour, candlestick, polar arc, radar, error bars, …) into pixel-perfect output through a tiny-skia or SVG backend, with PDF, terminal, and GPU paths arriving on the roadmap. It is designed for the moments when a paper, a notebook, and a service need to render the same chart.
[!WARNING] starsight is at 0.3.2 of a planned 1.0.0 trajectory. The roadmap below is the contract — items marked shipped are stable within the 0.x line; items marked planned may shift in scope. Pre-1.0, every minor bump is potentially breaking. MSRV bumps require a minor version bump until 1.0.
Thirty Seconds
[]
= "0.3"
use *;
The plot! macro forwards through Figure::from_arrays, which builds an 800×600 figure with a single LineMark and dispatches to the tiny-skia backend by file extension. There is no global state, no implicit theme, no runtime config — every figure is a value. See examples/ for 38 self-contained programs. Longer-form recipes live on the GitHub wiki — a 25-step Tutorials ladder from Hello starsight to implementing a custom Mark or DrawBackend, plus Comparisons showing matplotlib / ggplot2 / plotters / 15+ libraries side-by-side.
Install
The default feature ships a usable starting set: LineMark, PointMark, BarMark, AreaMark, HistogramMark, HeatmapMark, BoxPlotMark, ViolinMark, PieMark, ContourMark, CandlestickMark, polar marks (ArcMark, PolarBarMark, PolarRectMark, RadarMark), the tiny-skia raster backend, the SVG backend, and Wilkinson tick generation. Feature flags toggle the rest:
full enables everything; minimal is core types only with no rendering. The science and dashboard bundles compose related flag sets.
Architecture
A pipeline of three stages — compose, resolve, render:
- compose — you build a
Figureand add marks. Marks own their data references and their style. - resolve — starsight computes scales, ticks, layout, and a flat list of geometric primitives. This stage is pure; it does not touch I/O.
- render — a backend walks the primitives and writes output.
The facade crate (starsight) is the only crate users add to Cargo.toml. It exposes three access patterns so users can pick the one that fits their style:
- Prelude:
use starsight::prelude::*;for the common types. - Semantic modules:
use starsight::marks::LineMark;,use starsight::backends::SkiaBackend;— by category. - Latin layer aliases:
use starsight::components::marks::LineMark;— by layer.
Separating compose from render lets the same Figure produce a PNG for a notebook, an SVG for a paper, and a Vec<u8> for an HTTP response without re-stating intent. Separating resolve from compose lets us cache layout when only style changes — which is most of the time, in interactive contexts.
The seven layers exist to encode a one-way dependency rule: marks (L3) cannot reach into figures (L5), and figures cannot reach into export (L7). This makes the library refactor-friendly: adding a new mark type touches one layer; adding a new backend touches two; adding a new statistical transform touches one. The rule is enforced at workspace Cargo.toml level, not by convention — try to add an upward dependency and cargo check rejects it.
Pipeline
What plot!() actually does, stage by stage:
A Worked Example — the Lorenz Attractor
starsight is a viz library; the math is what it draws. The Lorenz system
$$ \dot{x} = \sigma (y - x), \qquad \dot{y} = x (\rho - z) - y, \qquad \dot{z} = x y - \beta z $$
with $\sigma = 10$, $\beta = 8/3$, $\rho = 28$ is the textbook strange attractor. Eleven trajectories sweeping $\rho \in {13, 15, 18, 21, 24.06, 28, 35, 50, 100, 160, 250}$, integrated with RK4 at $\mathrm{d}t = 0.005$ for 80 000 steps and projected onto the $x$–$z$ plane:
use *;
Real source: examples/scientific/lorenz_line.rs (the eleven-trajectory sweep, coloured by $\rho$ on prismatica's inferno map). A second worked example — the Kruskal–Szekeres coordinate chart for the Schwarzschild metric — lives at examples/scientific/kruskal_szekeres_line.rs.
Showcase
Source for every panel — and 29 more — lives under examples/, regenerated by cargo xtask gallery.
Status
What ships now and what's planned, broken out per subsystem. Click a category to expand. (Marks open by default — that's the question most readers want answered first.)
The DrawBackend trait is the only interface marks need to render; new backends slot in by implementing it — no other layer needs to change.
[!NOTE] PNG vs. SVG fidelity at high category density. The raster (PNG) backend rounds float coordinates to pixel boundaries through skia, so at >50 categories per axis (think 90 daily candles or denser) you may see ±1 px drift between bar edges and gridlines, even when the math is f64-exact. For papers, posters, or anywhere pixel-perfect alignment matters, prefer
.save("…svg")— the SVG backend is float-precise and shows no drift. PNG is best for slides, dashboards, and quick local renders where the eye won't notice 1-pixel offsets at 90+ categories.
Ecosystem
starsight composes with, but does not depend on:
polars/ndarray/arrow— feed columns into mark constructors viaFrom<&[T]>;polarsis wired today,ndarrayandarrowarrive in 0.11.time/chrono—DateTimeScalewill consume either (planned 0.5).serde— every mark and theme implementsSerialize/Deserializefor spec-as-data workflows.ratatui— the plannedRatatuiBackendrenders into TUI cells (planned 0.8).
It is part of the resonant-jovian ecosystem of Latin/Greek-named scientific Rust crates: chromata (1 104 editor / terminal color themes as compile-time constants), prismatica (260+ perceptually uniform colormaps as compile-time LUTs), caustic (6D Vlasov–Poisson plasma solver), phasma (terminal UI for caustic).
Longer-form recipes and tutorials live on the GitHub wiki: Comparisons walks through matplotlib / ggplot2 / plotters / 15+ others side-by-side, and Tutorials is a 25-step ladder from Hello starsight to implementing a custom Mark or DrawBackend.
Coming from Another Language
61 concrete syntax mappings across 15 source libraries. Find your line, copy the right column.
vs. Siblings
The bet behind starsight: one crate covering CPU + GPU + terminal + PDF with a grammar-of-graphics builder and shared themes/colormaps via chromata + prismatica. All siblings are alive and growing — these comparisons are "as of starsight 0.3" and the gaps narrow as each ships.
Roadmap
The full task-level roadmap with 338 checkboxes lives in .spec/STARSIGHT.md.
Minimum Supported Rust Version
starsight 0.3.x compiles on Rust 1.89 and later, edition 2024. The MSRV tracks the floor required by direct dependencies (currently cosmic-text at 1.89). The long-term policy is latest stable minus two, consistent with wgpu and ratatui. MSRV bumps require a minor version bump until 1.0.
Contributing
Contribution guide: CONTRIBUTING.md. The workspace conventions (layered architecture, error policy, snapshot tests) are documented in AGENTS.md. Issues and discussion: github.com/resonant-jovian/starsight/issues.
License
starsight is licensed under GPL-3.0-only. See LICENSE. Any project that links against it must be GPL-3.0-compatible — copyleft propagates through derivative works. If the GPL is incompatible with your use case, reach out — a permissively-licensed core may be carved out post-1.0.
Funding
starsight is built by Albin Sjögren (ORCID 0009-0008-1372-1727) as a solo open-source project. If your work depends on it, consider funding development so the next milestone lands sooner: github sponsors · thanks.dev.
Citing
CITATION.cff is the canonical source — GitHub renders a "Cite this repository" button from it automatically. The BibTeX block below is the manual fallback: