Skip to main content

Vega-Lite Chart

A widget that demonstrates how to use Vega-Lite to render a chart. Vega-Lite is a high-level grammar of interactive graphics — you describe the chart declaratively as JSON, and the renderer handles the rest.

For Vega-Lite, your endpoint simply needs to return a Vega-Lite JSON specification. No extra Python package is required to build the spec — but if you'd like helpers, you can install altair:

pip install altair
Vega-Lite Chart Example
from fastapi import FastAPI, Query

app = FastAPI()


def _vega_theme(theme: str) -> dict:
"""Return mark color + base config for the given theme."""
if theme == "light":
colors = {"fg": "#1a1a1a", "grid": "#e5e5e5", "mark": "#2563eb"}
else:
colors = {"fg": "#e5e7eb", "grid": "#2a2a2a", "mark": "#60a5fa"}
return {
"mark_color": colors["mark"],
"config": {
"background": "transparent",
"axis": {
"labelColor": colors["fg"],
"titleColor": colors["fg"],
"gridColor": colors["grid"],
"domainColor": colors["grid"],
"tickColor": colors["grid"],
},
"legend": {"labelColor": colors["fg"], "titleColor": colors["fg"]},
"title": {"color": colors["fg"]},
"view": {"stroke": "transparent"},
},
}


@register_widget({
"name": "Population by Era (Vega-Lite)",
"description": "Vega-Lite bar chart of population by era",
"type": "chart-vegalite",
"endpoint": "era_population_vega",
"gridData": {"w": 20, "h": 12}
})
@app.get("/era_population_vega")
def get_era_population_vega(theme: str = Query("dark")):
"""Vega-Lite bar chart of total population by era."""
values = [
{"era": "Pre-WWII", "total": 8_500_000},
{"era": "WWII", "total": 12_300_000},
{"era": "Post-WWII", "total": 18_700_000},
{"era": "Modern", "total": 24_500_000},
{"era": "Contemporary", "total": 31_200_000},
]
t = _vega_theme(theme)

return {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": "Population by Era (Vega-Lite)",
"width": "container",
"height": "container",
"autosize": {"type": "fit", "contains": "padding"},
"config": t["config"],
"data": {"values": values},
"mark": {"type": "bar", "color": t["mark_color"], "tooltip": True},
"encoding": {
"x": {"field": "era", "type": "nominal", "sort": "-y", "title": "Era"},
"y": {"field": "total", "type": "quantitative", "title": "Total"},
},
}

Note that for Vega-Lite, the type field is set to "chart-vegalite" instead of "chart" (Plotly) or "chart-highcharts" (Highcharts).

The endpoint must return a valid Vega-Lite JSON spec. The two most important pieces are:

  • data.values — an inline array of records to plot. You can also use data.url to point at a remote dataset.
  • encoding — maps fields in your data to visual channels (x, y, color, size, etc.).

Theme Support

The example includes full theme support for both dark and light modes. The theme parameter is automatically provided by OpenBB Workspace based on the user's current display mode (dark/light). The _vega_theme helper returns a config block that styles axes, legends, titles, and the view background to match the workspace.

  • Dark mode: light text (#e5e7eb), dark grid lines (#2a2a2a), light blue mark (#60a5fa)
  • Light mode: dark text (#1a1a1a), light grid lines (#e5e5e5), darker blue mark (#2563eb)

The background is set to "transparent" so the chart blends into the widget canvas regardless of theme.

Additional Resources

For more information on Vega-Lite specifications, visit the Vega-Lite Documentation and the example gallery.

You can find more examples of how to set up your own backend in the Backend for OpenBB Workspace GitHub.