dragonJSON is a JavaScript client library that lets you navigate your server’s JSON data as though it were a plain local object — but every property access is lazy. Under the hood, each path you traverse is intercepted by an ES Proxy, and data is fetched from the server only when youDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/michael-tiger-2010/dragonjson/llms.txt
Use this file to discover all available pages before exploring further.
await a value. The result lands in an in-memory cache, so any child property you access next resolves instantly from what the server already returned. dragonJSON is designed for JSON-shaped datastores (think NoSQL or document databases) and is especially useful when you want fast iteration speed without writing a schema, resolver, or query language.
What problem does it solve?
Most REST APIs expose coarse endpoints: you ask for a resource and receive the entire document, even when you only need two fields. Alternatively, you make many small, serial requests to drill into nested data, paying a network round trip for each hop. Both patterns waste bandwidth and add latency. dragonJSON sits in front of your API and handles the coordination for you:- Fetch only what you access. Property traversal is recorded as a path string (
posts.page1.title). The request is fired only when youawait— and only for the segment the cache doesn’t yet hold. - Reuse what you already have. If you fetched
posts.page1to read the title, the body field is already cached. Accessing it next costs zero network calls. - Batch concurrent requests automatically. When multiple paths are awaited in quick succession, dragonJSON coalesces them into a single round trip using the batch protocol.
- Stay in sync across clients. A lightweight relay hook (WebSocket, BroadcastChannel, or anything else) lets every connected client receive cache invalidations the moment another client mutates data.
Core concepts at a glance
Lazy Loading
Data is fetched on demand, one path at a time, only when you
await it.Caching
Every fetched subtree is stored in an in-memory cache. Children of a cached node resolve without a network call.
Batching
Concurrent requests within the same event-loop tick are merged into a single HTTP round trip.
Live Sync
Relay cache invalidations over any transport to keep every connected client up to date in real time.
How it compares
Plain fetch | GraphQL | dragonJSON | |
|---|---|---|---|
| Schema required | No | Yes | No |
| Fetches only needed fields | Manual | Yes | Yes |
| Automatic caching | Manual | Varies by client | Built-in |
| Real-time sync | Manual | Subscriptions | Built-in relay hook |
| Setup overhead | Minimal | Moderate–high | Minimal |
fetch: Writing raw fetch calls gives you full control but puts the caching, batching, and invalidation logic on you. Every new nested path requires a new endpoint or query parameter, and keeping multiple components in sync means manually wiring state updates.
vs. GraphQL: GraphQL is an excellent fit for large teams and production APIs where a strict schema, typed resolvers, and fine-grained access control are worth the investment. dragonJSON trades that rigour for simplicity: there is no schema to define, no resolver to write, and no query language to learn. It is well-suited to quick prototypes, smaller projects, and internal tools where you want to move fast and your data is already JSON-shaped.
Constraints to know
dragonJSON uses the ES Proxy to intercept property names and build path strings, which means a small number of naming rules apply to your data:- Property names must not contain
.— the dot is the path separator. - Property names cannot be
thenorexists— these are intercepted by the proxy to supportawaitand existence checks. - Property names cannot start with
$— names beginning with$are reserved for dragonJSON’s own mutation and utility methods ($set,$add,$remove,$on, etc.). - Your server must return
{ invalidate: [...] }from all mutation endpoints — dragonJSON uses this list to mark stale cache paths and fire the relevant$on()listeners after every write.
Ready to try it? Follow the quickstart to have a working client in under five minutes.