The map component
AI can write
One JSON spec. Markers, layers, choropleths, SQL widgets. Stream it from any LLM and watch the map build itself.
npm install json-mapsAI applications
Your LLM outputs a JSON spec. MapRenderer renders it. Stream the response and watch markers, layers, and choropleths appear token by token.
Data dashboards
Load Parquet, PMTiles, and GeoJSON directly. Add DuckDB SQL widgets that query your data in the browser with viewport-reactive aggregations.
Rapid prototyping
One component, one spec. Go from an idea to an interactive map in minutes. Export the schema and hand it to any model as a tool definition.
Wire it to your LLM
Stream a JSON spec from any model. The map updates as tokens arrive.
import { MapRenderer } from "json-maps";
import { useState } from "react";
import { readStream } from "./stream";
export default function AIMap({ prompt }: { prompt: string }) {
const [spec, setSpec] = useState({});
async function generate() {
const res = await fetch("/api/map", {
method: "POST",
body: JSON.stringify({ prompt }),
});
for await (const chunk of readStream(res)) {
setSpec(JSON.parse(chunk));
}
}
return (
<>
<button onClick={generate}>Generate</button>
<MapRenderer spec={spec} />
</>
);
}Data-driven spec
Choropleth with legend, tooltips, and a DuckDB SQL widget — all from JSON.
{
"layers": {
"states": {
"type": "geojson",
"data": "https://raw.githubusercontent.com/PublicaMundi/MappingAPI/master/data/geojson/us-states.json",
"style": {
"fillColor": {
"type": "continuous",
"attr": "density",
"palette": "Sunset",
"domain": [0, 1000]
}
},
"tooltip": ["name", "density"]
}
},
"legend": {
"density": { "layer": "states", "title": "Density" }
},
"widgets": {
"avg": {
"sql": {
"query": "SELECT ROUND(AVG(density)) as avg FROM states",
"refreshOn": "viewport"
},
"value": "{{avg}} per sq mi"
}
}
}Everything you need
JSON schema for LLMs
Export the spec schema and give it to any model as a tool definition. Typed, validated, constrained generation.
Progressive streaming
Stream JSON from your AI backend. The map updates token by token as markers, layers, and controls arrive.
Browser-native SQL
DuckDB-WASM widgets query your data in the browser. Viewport-reactive aggregations update as users pan and zoom.
Modern data formats
Parquet, PMTiles, MVT, raster tiles. Load millions of rows directly from cloud storage without a tile server.
One component
<MapRenderer spec={spec} /> with className, style, and children. That's the entire API surface.
Production callbacks
onMapClick, onLayerHover, onMarkerDragEnd, onViewportChange, onError. Full control over every interaction.
Stay updated
Get notified about new features and updates.