Documentation

@smalldat/sandycoast

High-performance chart components rendered as points / sand — thousands of grains pour in and settle into shapes. WebGPU-first, Canvas2D fallback. Not SVG.

Each visual takes a single config object and mounts into a DOM element. Grains live in a Structure-of-Arrays buffer uploaded to the GPU once; each frame the CPU only bumps a now uniform and the shader interpolates every grain's position. That's how a chart animates 100k particles without touching the DOM.

Install

# from the package registry
npm install @smalldat/sandycoast

Quick start

import { BarChart } from '@smalldat/sandycoast';

const chart = new BarChart(document.querySelector('#el')!, {
  data: {
    points: [
      { x: 'Q1', y: 120, z: 'EU' },
      { x: 'Q1', y: 90,  z: 'US' },
      { x: 'Q2', y: 140, z: 'EU' },
    ],
  },
  grainDensity: 0.9,
  grain: { sizePx: 2.4, shape: 'disc' },
  animation: { duration: 1100, stagger: 700, ease: 'easeOutCubic' },
  interaction: { hover: { effects: ['highlight', 'jitter'] } },
});

chart.on('hover', ({ bar }) => console.log(bar?.xValue, bar?.yValue));
await chart.whenReady();   // backend picked, first frame scheduled
chart.update(newData);      // grains morph to new targets
chart.dispose();
Container sizing. The chart fills its host element via a 100%-sized canvas and watches it with a ResizeObserver. Give the host an explicit height.

Publishing these docs to GitHub Pages

These pages are plain static HTML/CSS with no build step — GitHub Pages can serve the docs/ folder directly. A .nojekyll file is included so Pages serves the files as-is (no Jekyll processing).

One-time setup

# 1. Commit the docs folder
git add docs
git commit -m "docs: static documentation site"
git push

# 2. In the GitHub repo:
#    Settings → Pages → Build and deployment
#      Source: "Deploy from a branch"
#      Branch: main   /   Folder: /docs   →   Save

Within a minute the site is live at https://<user>.github.io/<repo>/. Every push to main that touches docs/ republishes automatically.

Custom domain (optional). Add a file docs/CNAME containing your domain (e.g. docs.smalldat.com) and point a DNS CNAME record at <user>.github.io.
Note. These docs are separate from the live playground demo at sandycoast.smalldat.com, which is built with Vite and deployed to Firebase Hosting by the .github/workflows/publish.yml action — a release workflow that runs on a push to a release/** branch and publishes the npm package before deploying the site. The Pages docs and the Firebase playground are independent — publishing one does not touch the other, and a docs-only change needs no release.

Status & roadmap

Shipped: data model, scales (linear / time / band), grain packing, WebGPU + Canvas2D backends, BarChart, LineChart, ScatterChart, PieChart (pie/donut), WindRoseChart and CandlestickChart with pour-in, morph update(), and hover. Axes, positionable legend, current-value readout, per-mark solid fill/border/marker/slice reveal, live update / add / remove with smooth tween, a mesh-ready per-point z value and swappable point-cloud approximation strategy on the scatter chart, a series-picking slider — shared by the pie and candlestick charts — that morphs between series, and — new with the wind rose — a two-indicator data model, a shared time table, latest-value highlighting and overridable pointer hooks (which the candlestick chart reuses). The candlestick chart adds an OHLC data model, a configurable rising/falling colour rule (including a custom rule function) and a live-price line. A React binding for every chart above, shipped in this package under @smalldat/sandycoast/react.

Planned next: WebGL2 fallback, an area chart, color-by-value (using the scatter chart's z.value), a mesh chart.

© 2026 · Dual-licensed — see License. MIT for non-commercial use; a paid commercial license is required for revenue-generating organizations.