Reference Entry
From Raw API Payloads to Browser Dashboards
Guides · querying · order 30
A practical pattern for turning raw API responses into local-first dashboard interactions with Querylight TS.
Relevant APIs
From Raw API Payloads to Browser Dashboards
The new dashboard demo exists to make one point clear: Querylight TS is not just for search boxes.
If an API gives you rows of JSON instead of pre-aggregated charts, you can still build a usable analytics surface in the browser:
- download or collect raw records
- normalize them into a stable local shape
- index the fields you want to filter and aggregate
- derive subsets with queries
- turn those subsets into chart series
That is the pattern used in the demo dashboard.
Why this pattern is useful
Many APIs return data in one of these shapes:
- events
- measurements
- time-series rows
- records with tags, categories, and timestamps
That is enough for exploration, but not enough for a ready-made dashboard. Normally you would solve that with:
- a backend analytics service
- a warehouse
- SQL transformation jobs
- custom aggregation endpoints
For small datasets, prototypes, internal tools, and static demos, that can be overkill.
A good document shape for analytics
The core idea is to treat each API row as a document and index the parts you want to slice on.
const index = new DocumentIndex({
country: new TextFieldIndex(tagAnalyzer, tagAnalyzer),
indicatorId: new TextFieldIndex(tagAnalyzer, tagAnalyzer),
year: new NumericFieldIndex(),
value: new NumericFieldIndex()
});
index.index({
id: "usa-pop-2024",
fields: {
country: ["United States"],
indicatorId: ["SP.POP.TOTL"],
year: ["2024"],
value: ["340110988"]
}
});
That is not very different from indexing documents for search. The difference is what you do with the matching ids afterward.
Use queries to define a subset
In the dashboard demo, charts start with a filtered subset:
const filters = [
new TermQuery("indicatorId", "SP.POP.TOTL"),
new TermsQuery("country", ["United States", "Germany", "Japan"]),
new RangeQuery("year", { gte: "2018", lte: "2024" })
];
const subset = new Set(
index.search(new BoolQuery([], [], filters)).map(([id]) => id)
);
Once you have subset, you can treat it as the current slice of the data.
Build chart inputs from the slice
The charting library does not need to know anything about Querylight TS.
It only needs arrays of numbers, labels, and series data.
For example:
termsAggregation(...)gives you category countsstats(...)gives you summary metricshistogram(...)gives you numeric bucketsdateHistogram(...)gives you time bucketsgetTopSignificantTerms(...)gives you characteristic vocabulary for a slice
That is enough to power:
- bar charts
- pies
- histograms
- time series
- heatmaps
- scatter plots
What the dashboard demo intentionally does not do
The demo is deliberately small in scope.
- The datasets are toy snapshots.
- The chart logic is illustrative rather than authoritative.
- The category heuristics are simple and may contain bugs.
- The goal is to show the pattern, not to ship a production BI stack.
That is an acceptable tradeoff for a docs demo because the architectural idea is the real subject.
When this approach is a good fit
- static dashboards bundled with a browser app
- internal tools over modest datasets
- API exploration and prototyping
- educational demos
- local-first tools where shipping raw records is acceptable
It is less suitable when:
- the dataset is too large for browser memory
- you need complex joins
- you need strict reporting guarantees
- the query cost belongs on a backend