Serialize any chart's configuration to JSON, encode it as a URL for permalinks, copy it to the clipboard as JSON or JSX, or generate pasteable code. This enables sharing chart views across teams, bookmarking specific chart states, and letting AI agents read and modify chart configurations programmatically.
Why Serialize Charts?
- Share views — copy a chart config and paste it in Slack, email, or a support ticket. Your colleague can reconstruct the exact chart you were looking at.
- Bookmarkable dashboards — encode chart state in the URL. Users can bookmark or share links that restore the exact chart configuration, including which data fields are mapped to which visual channels.
- AI agent integration — an AI agent can call
toConfig() to read a chart's current state, reason about it, modify the config, then pass it to fromConfig() to render a new chart. configToJSX() generates code the developer can paste directly. - Undo/redo — store config snapshots in a history stack for undo/redo functionality without managing individual prop changes.
- Testing and debugging — serialize a chart's config, save it to a test fixture, and use
fromConfig() to reconstruct it in tests. Ensures visual consistency across releases.
Quick Start
JSX
import { toConfig, fromConfig, toURL, fromURL, copyConfig, configToJSX } from "semiotic" // 1. Serialize chart props to a JSON-safe config const config = toConfig("LineChart", { data: salesData, xAccessor: "month", yAccessor: "revenue", colorBy: "region", width: 600, }) // 2. Reconstruct props from config const { componentName, props } = fromConfig(config) // componentName === "LineChart", props has data, xAccessor, yAccessor, etc. // 3. Encode as a URL for permalinks const permalink = `https://app.com/viz?${toURL(config)}` const decoded = fromURL(permalink) // 4. Copy to clipboard as JSON or JSX await copyConfig(config) // JSON to clipboard await copyConfig(config, "jsx") // <LineChart xAccessor="month" ... /> // 5. Generate JSX code snippet const code = configToJSX(config) // '<LineChart\n xAccessor="month"\n yAccessor="revenue"\n .../>'
Round-Trip Demo
Select a chart type to see its props serialized to JSON, JSX, or URL format. The chart on the left is rendered fromfromConfig(toConfig(...)) — proving the round-trip works. Toggle "Include data" off to see a lightweight config suitable for URL sharing.
Rendered from fromConfig()
{ "component": "LineChart", "props": { "data": [ { "x": 1, "y": 4200 }, { "x": 2, "y": 5100 }, { "x": 3, "y": 4800 }, { "x": 4, "y": 6300 }, { "x": 5, "y": 5900 }, { "x": 6, "y": 7200 }, { "x": 7, "y": 6800 }, { "x": 8, "y": 7600 } ], "xAccessor": "x", "yAccessor": "y", "width": 500, "height": 300, "curve": "monotoneX", "showPoints": true }, "version": "1", "createdAt": "2026-07-10T16:45:39.383Z" }Config Editor
Edit the JSON config on the left and see the chart update in real time. Try changing orientation to "horizontal", or modify the data values. This is the same workflow an AI agent uses: read config, modify, render.
Live preview (fromConfig)
What Gets Serialized
| Prop Type | Example | Serialized? |
|---|
| String accessors | xAccessor: "month" | Yes |
| Function accessors | xAccessor: d => d.month | No (stripped) |
| Data arrays | data: [{...}] | Yes (opt-out with includeData: false) |
| Numbers, strings, booleans | width: 600, showGrid: true | Yes |
| Objects, arrays | margin: { top: 20 } | Yes |
| Callbacks | onObservation, tooltip | No (always stripped) |
| React elements | centerContent: <span/> | No (stripped) |
ChartContainer Integration
The ChartContainer component has a built-in "Copy Config" toolbar button. Pass the serialized config via the chartConfig prop.
JSX
import { ChartContainer, LineChart, toConfig } from "semiotic" const chartProps = { data: salesData, xAccessor: "month", yAccessor: "revenue", width: 600, height: 400, } <ChartContainer title="Monthly Revenue" actions={{ export: true, copyConfig: true }} chartConfig={toConfig("LineChart", chartProps)} > <LineChart {...chartProps} /> </ChartContainer>
The copy icon in the toolbar copies the config to the clipboard. Useactions={{ copyConfig: { format: 'jsx' } }} to copy as a JSX code snippet instead.
Selection State
When using LinkedCharts, you can capture the current brush/selection state alongside the chart config. The serializeSelections function converts the internal Map/Set structures to JSON-safe objects.
JSX
import { toConfig, serializeSelections, deserializeSelections } from "semiotic" // Capture selections (inside a component with access to the store) const selections = serializeSelections(store.selections) // Include in config const config = toConfig("Scatterplot", props, { selections }) // Later: restore selections const deserialized = deserializeSelections(config.selections) // → Map<string, Selection> with Set values restored
AI Agent Workflow
The serialization API completes Semiotic's AI agent loop. Combined with observation hooks and the MCP server, an AI agent can:
- Observe — receive structured events via
onObservation - Read — call
toConfig() to get the current chart state - Modify — change the config (adjust accessors, add annotations, switch chart type)
- Render — pass modified config to
fromConfig() or generate code with configToJSX()
JSX
// AI agent workflow const config = toConfig("Scatterplot", currentProps) // Agent modifies the config config.props.colorBy = "category" config.props.showGrid = true config.component = "BubbleChart" config.props.sizeBy = "population" // Generate code for the developer const code = configToJSX(config) // <BubbleChart // data={[...]} // xAccessor="x" // yAccessor="y" // colorBy="category" // showGrid // sizeBy="population" // />
API Reference
| Function | Returns | Description |
|---|
toConfig(name, props, opts?) | ChartConfig | Serialize props to JSON. Options: includeData, selections |
fromConfig(config) | { componentName, props } | Reconstruct component name and props from config |
toURL(config) | string | Encode config as sc=... base64url query param |
fromURL(url) | ChartConfig | Decode config from URL or query string |
copyConfig(config, fmt?) | Promise<void> | Copy to clipboard. fmt: "json" (default) or "jsx" |
configToJSX(config) | string | Generate pasteable JSX code snippet |
serializeSelections(map) | SerializedSelections | Convert Map/Set selection state to JSON |
deserializeSelections(obj) | Map<string, Selection> | Restore Map/Set from JSON |