A React data visualization library designed for AI-assisted development.
Simple charts in 5 lines. Network graphs, streaming data, and coordinated dashboards when you need them. Structured schemas and an MCP server so AI coding assistants generate correct chart code on the first try.
<!-- semiotic-readme-dashboard:start --> <img src="./docs/public/assets/img/semiotic-release-dashboard.svg" alt="Semiotic release dashboard showing chart count, bundle sizes, capability coverage, chart families, and documentation growth" width="100%"> <!-- semiotic-readme-dashboard:end -->What's New in 3.8.7
3.8.7 hardens the physics, server-rendering, and agent-evaluation paths exercised after the 3.8.6 release:
- Physics reduced-motion settling now admits paced spawns and completes time-driven event tapes; runtime preference changes no longer accumulate a giant animation delta. Chain-reaction tiles and lane labels no longer overlap, and physics chrome follows the active theme.
- BigNumber now has native static render evidence, exact source facts flow through reader grounding, and agent guidance keeps value-component props separate from chart-HOC props.
- Static SVG preserves chart-level primitive styling and heatmap cell borders, while horizontal legends clear axis ticks and titles consistently in browser and server renders.
- Physics charts participate in shared linked hover, while the clearer
UnitPileChartandPacketFlowChartnames ship with permanent aliases for their previous names. - The public model-evaluation reading room preserves the complete baseline and three targeted follow-up trials, including the unresolved Luna gauge result rather than smoothing it away.
import { LineChart } from "semiotic/xy"
<LineChart
data={salesData}
xAccessor="month"
yAccessor="revenue"
/>Why Semiotic
Semiotic is a data visualization library for React that combines broad chart coverage with first-class AI tooling. It handles the chart types that most libraries skip — network graphs, streaming data, statistical distributions, coordinated views — and ships with machine-readable schemas so LLMs can generate correct code without examples.
Built for AI-assisted development
Semiotic ships with everything an AI coding assistant needs to generate correct visualizations without trial and error:
semiotic/ai— a single import with the schema-backed chart capability catalog (XY, ordinal, network, realtime, geo, value), optimized for LLM code generation. Seeai/surface-manifest.jsonfor the generated current inventory. Note: the published entry files are pre-bundled, so importing one chart fromsemiotic/aistill ships most of the bundle — treat it as a codegen/tooling surface and use family subpaths (semiotic/xy,semiotic/geo,semiotic/value, …) in production code, at roughly half the single-chart cost.ai/schema.json— machine-readable prop schemas for every componentnpx semiotic-mcp— an MCP server for tool-based chart rendering in any MCP clientnpx semiotic-ai --doctor— validate component + props JSON from the command line with typo suggestions and anti-pattern detectiondiagnoseConfig(component, props)— programmatic anti-pattern detector with actionable fixes, spanning validation, encoding, accessibility, and misleading-design (deception) checksauditData(component, props, data?)— chart-aware numeric preflight for inputs that pass schema validation but break the math: non-finite values, zero-span domains, invalid log inputs, negative size geometry, unsafe normalized totals, and scale-dominating outliers. Returns bounded row evidence and flows intodiagnoseConfig, Chart Clinic, CLI doctor, and opt-inChartContainernotificationsCLAUDE.md— instruction files auto-synced for Claude, Cursor, Copilot, Windsurf, and Clinellms.txt— machine-readable documentation following the emerging standard
Every chart includes a built-in error boundary, dev-mode validation
warnings with typo suggestions, and accessibility features (canvas
aria-label, keyboard-navigable legends, aria-live tooltips, SVG
<title>/<desc>) so AI-generated code fails gracefully with
actionable diagnostics instead of a blank screen.
Accessibility is a release surface
The European Accessibility Act has applied to covered products and services since 28 June 2025. A chart library cannot certify an application's legal compliance: scope, content, surrounding controls, testing, and national enforcement remain the application owner's responsibility. Semiotic supplies testable infrastructure for that work: keyboard interaction, accessible data tables, layered descriptions, structured navigation, reduced-motion and forced-colors paths, and WCAG-derived contrast tests for shipped theme presets. See the Accessibility docs and run the application's own assistive-technology and user testing.
Beyond standard charts
Network visualization. Force-directed graphs, Sankey diagrams, chord diagrams, tree layouts, treemaps, circle packing, and orbit diagrams — all as React components with the same prop API as LineChart.
Streaming data. Realtime charts render on canvas at 60fps with a ref-based push API. Rapid network edge pushes coalesce into one layout per animation frame, while read/mutation methods preserve synchronous read-after-write semantics. Built-in decay, pulse, and staleness encoding for monitoring dashboards.
Coordinated views. LinkedCharts provides hover cross-highlighting,
brush cross-filtering, coordinate-based linked crosshairs, and selection
synchronization across any combination of chart types through shared selection state.
Geographic visualization. Choropleth maps, proportional symbol maps, flow maps with animated particles, and distance cartograms — all canvas-rendered with d3-geo projections, zoom/pan, tile basemaps, and drag-rotate globe spinning.
Statistical summaries. Box plots, violin plots, swarm plots, histograms, LOESS smoothing, forecast with confidence envelopes, and anomaly detection. Marginal distribution graphics on scatterplot axes with a single prop.
First-class annotations. Annotations are data-bound objects, not post-hoc artwork. Labels, callouts, thresholds, enclosures, statistical overlays, and React widgets move with the chart and render through browser, SSR, and export paths. Opt into placement, hierarchy, density, progressive disclosure, audience-aware amount, provenance, and editorial lifecycle when the chart needs to communicate more than its encoding alone.
Choose the API layer
| Layer | For | Example |
|---|---|---|
| Charts | Common chart forms with chart-level props | <LineChart data={d} xAccessor="x" yAccessor="y" /> |
| Frames | Full control over rendering, interaction, and layout | <StreamXYFrame chartType="line" lineStyle={...} /> |
Every Chart component accepts a frameProps prop to access the underlying
Frame API without leaving the simpler interface.
Serialization and interop
Charts serialize to JSON and back: toConfig, fromConfig, toURL,
copyConfig, configToJSX. Have Vega-Lite specs? fromVegaLite(spec)
translates them to Semiotic configs — works with configToJSX() for
full round-trip from notebooks and AI-generated specs.
Need an external pitfall review? The experimental unstable_toDataPitfallsChain() builds a
dependency-free chain input for datapitfalls,
combining the Semiotic config, JSX, reader grounding, diagnostics,
accessibility audit, and optional rendered SVG/image evidence:
import { unstable_toDataPitfallsChain } from "semiotic/experimental"
import { detectPitfalls } from "datapitfalls"
const input = unstable_toDataPitfallsChain("LineChart", props, {
narrative: "Monthly sales are accelerating.",
rendered: { svg, evidence },
})
const report = await detectPitfalls(input, { apiKey: process.env.ANTHROPIC_API_KEY })The return path stays dependency-free too. Use whole-chart findings as
ChartContainer notifications, and only turn findings into annotations after
your app can anchor them to marks or semantic positions:
import { ChartContainer } from "semiotic"
import { LineChart } from "semiotic/xy"
import {
unstable_toDataPitfallsAnnotations,
unstable_toDataPitfallsNotifications,
} from "semiotic/experimental"
const notifications = unstable_toDataPitfallsNotifications(report)
const annotations = unstable_toDataPitfallsAnnotations(report, {
anchorFor: (finding) =>
finding.ruleId === "truncated-axis" ? { x: 9, y: 9000 } : null,
})
<ChartContainer notifications={notifications}>
<LineChart {...props} annotations={annotations} />
</ChartContainer>When to use something else
Need a standard bar or line chart for a dashboard you'll never need to customize beyond colors and labels? Recharts has a larger ecosystem and more community examples. Need GPU-accelerated rendering for millions of data points? Apache ECharts handles that scale.
Semiotic is for projects that outgrow those libraries — when you need network graphs alongside time series, streaming data alongside static snapshots, or coordinated views across chart types.
Install
npm install semioticRequires React 18.1+ or React 19.
Quick Examples
Coordinated Dashboard
Hover one chart and highlight the same data in another through a shared selection:
import { LinkedCharts, Scatterplot, BarChart } from "semiotic"
<LinkedCharts>
<Scatterplot
data={data} xAccessor="age" yAccessor="income" colorBy="region"
linkedHover={{ name: "hl", fields: ["region"] }}
selection={{ name: "hl" }}
/>
<BarChart
data={summary} categoryAccessor="region" valueAccessor="total"
selection={{ name: "hl" }}
/>
</LinkedCharts>Streaming Metrics with Decay
Live data fades old points, flashes new ones, flags stale feeds:
import { RealtimeLineChart } from "semiotic"
const chartRef = useRef()
chartRef.current.push({ time: Date.now(), value: cpuLoad })
<RealtimeLineChart
ref={chartRef}
timeAccessor="time"
valueAccessor="value"
decay={{ type: "exponential", halfLife: 100 }}
staleness={{ threshold: 5000, showBadge: true }}
/>Network Graphs
Force-directed graphs and Sankey diagrams — same API as LineChart:
import { ForceDirectedGraph, SankeyDiagram } from "semiotic"
<ForceDirectedGraph
nodes={people} edges={friendships}
colorBy="team" nodeSize={8} showLabels
/>
<SankeyDiagram
edges={budgetFlows}
sourceAccessor="from" targetAccessor="to" valueAccessor="amount"
/>Geographic Visualization
Choropleth maps, flow maps, and distance cartograms with canvas rendering, zoom/pan, tile basemaps, and animated particles:
import { ChoroplethMap, FlowMap, DistanceCartogram } from "semiotic/geo"
<ChoroplethMap
areas={geoJsonFeatures} valueAccessor="gdp"
colorScheme="viridis" projection="equalEarth" zoomable tooltip
/>
<FlowMap
nodes={airports} flows
…
