Vega-Embed
Embed interactive Vega and Vega-Lite visualizations into any web page with a single function call.
Repository Health
Technical Analysis
Vega-Embed is a small JavaScript/TypeScript library from the Vega project that turns a Vega or Vega-Lite specification into an interactive, embedded visualization on any web page. It handles rendering, packages in Vega Tooltip and Vega Themes, and adds optional action links for viewing source, exporting PNG/SVG, and opening the chart in the online Vega Editor.
It ships as both an ES module for bundler-based apps and a UMD build for direct <script> tag use (via CDNs like jsDelivr), making it the standard glue layer between a Vega/Vega-Lite spec and a rendered chart in the DOM — used heavily in tools like Observable notebooks and documentation sites across the data-visualization ecosystem.
What You Get
- A single
embed()/vegaEmbed()entry point that renders Vega or Vega-Lite specs into a DOM element or CSS selector and resolves to a Promise with the liveView, spec, compiled Vega spec, and afinalize()cleanup method. - Built-in Vega Tooltip and Vega Themes integration, plus a config-driven action menu for exporting PNG/SVG, viewing the source spec/compiled Vega, and opening the chart in the hosted Vega Editor.
- Dual build output — an ES module for bundler-based apps (
import embed from 'vega-embed') and a UMD bundle for direct<script>tag use via CDNs like jsDelivr/unpkg. - A
container()helper purpose-built for Observable notebooks, returning a value-bearing HTML element instead of a bare Promise. - Support for patching specs at runtime via a function, JSON-Patch (RFC6902) document, or URL, letting you tweak a Vega-Lite-compiled spec before it renders.
Common Use Cases
- Embedding interactive charts and dashboards on documentation sites, blogs, and marketing pages from a Vega-Lite JSON spec.
- Powering chart cells in Observable notebooks via the
container()API. - Adding export-to-PNG/SVG and ‘view source’ affordances to publicly shared data visualizations.
- Loading and rendering third-party or server-generated Vega/Vega-Lite specs by URL without a build step, via the CDN script-tag path.
Under The Hood
Architecture — index.ts exports a polymorphic default function that inspects its arguments (element vs. spec, arg count) and dispatches to either embed() (src/embed.ts) or the Observable-oriented container() (src/container.ts). embed.ts is the core: it resolves the spec (string URL vs. parsed object), infers mode (vega or vega-lite) by parsing the spec’s $schema field, compiles Vega-Lite specs down to Vega specs via vega-lite’s compile(), optionally applies a runtime patch (function, JSON-Patch via fast-json-patch, or a fetched URL), merges themes (vega-themes) and config through mergeDeep (src/util.ts, built on Vega’s own writeConfig), instantiates a vega.View, wires up a Vega Tooltip Handler, renders into the target element, and appends an action-link menu whose “open in Vega Editor” option round-trips the spec to the external editor via post.ts’s postMessage handshake.
Tech Stack — TypeScript (~71% of the codebase), bundled by Rollup (rollup.config.js) into two artifacts: an ESM build (build/embed.js, the package’s exports.default) and a terser-minified UMD build (build/vega-embed.min.js, referenced by the unpkg/jsdelivr fields) via @rollup/plugin-typescript, -node-resolve, -commonjs, and -json. vega and vega-lite are peer dependencies ("*", left for the consumer to pin); direct dependencies are small utilities (fast-json-patch, json-stringify-pretty-compact, semver, tslib, vega-interpreter, vega-schema-url-parser) plus pinned vega-themes/vega-tooltip versions. Component styling is compiled separately from vega-embed.scss into src/style.ts by build-style.sh (Sass) ahead of the Rollup build. Tests run on Vitest with jsdom and vitest-canvas-mock; linting uses ESLint’s flat config with typescript-eslint and Prettier; releases are cut with release-it and conventional-changelog.
Code Quality — The test/ directory has 48 tests across three files (embed.test.ts ~42, container.test.ts 4, util.test.ts 2), covering renderer switching, action-menu rendering, custom Vega expression functions, and spec patching — solid coverage of the public surface for a ~550-line core module, though edge cases around the postMessage editor handshake and error paths are thin. Source files stay small and single-purpose (util.ts 20 lines, types.ts 16, post.ts 33, container.ts 29), keeping complexity low per file. TypeScript types (EmbedOptions, Actions, Hover, Mode) are used consistently across the public API for compile-time safety. Error handling largely relies on native Promise rejection propagating up from Vega’s View rather than custom wrapping, and post.ts uses a hardcoded 10-second polling timeout for the editor handshake rather than an explicit failure/reject path.
API Design — embed(el, spec, opt) needs only two required arguments and ships permissive defaults (DEFAULT_ACTIONS enables the full action menu), auto-detecting vega vs. vega-lite mode from the spec’s $schema so callers rarely set mode explicitly. The polymorphic default export in index.ts (choosing between embed and container based on argument shape) trades a bit of predictability for zero-friction use in Observable notebooks — an unusual but clearly documented pattern. The options object is large (30+ fields) but every field is optional and documented in a README table, and getting started requires nothing beyond embed('#vis', spec). Action-menu labels are overridable via an i18n option, and TypeScript consumers get full autocompletion on EmbedOptions/VisualizationSpec.
Used by 2 apps in this directory
Lightdash
Analytics · Data Engineering
The open-source Looker alternative that turns your dbt project's metrics and dimensions into governed, self-serve charts and dashboards — no license key required.
Rill
Analytics · Data Engineering
The fastest BI tool for humans and agents — define metrics, models, and dashboards as code and query them instantly on ClickHouse or DuckDB.