- Discovery: how the extension learns that the adapter recorded an entry.
- Correlation headers: the request and response headers that link entries and group them.
- Read API: the endpoints that return recorded entries, and the format of those entries.
Discovery
For every response, the adapter generates a unique entry id and sets it on a response header. The id may be any collision-resistant string of 1 to 256 characters, such as a ULID.The generated id of the entry, set on every response. The extension reads the id from this header, then fetches the entry from the read API.
/admin, needs one more value. The extension sends read API requests to that subpath, so the adapter reports it.
The path the application is served from, such as
/admin. The adapter sets it only when the application is not served from the root of its origin. The adapter also adds the value to the discovery script as a data-inertia-devtools-base-path attribute.Correlation Headers
The correlation headers link entries to client-side page state and group related requests. The extension sets the request headers, and the adapter stores their values on the entry. The adapter sets the response header. The extension sends the following request headers. Each header is optional.A UUID for the browser tab, stored as
__meta.tabUuid. The adapter stores entries separately for each tab, so one tab’s history does not evict another tab’s history.The client’s visit id, stored as
__meta.visitId. The extension uses it to pair the entry with the page snapshot it took in the browser.The id of the entry that started the batch, stored as
__meta.batchId. The adapter stores the value unchanged. The client handles grouping.Set to
1 on the follow-up request for deferred props. The request is otherwise identical to a partial reload, so the client marks it with this header.Set to
1 on a polling request. A polling request is otherwise identical to a partial reload as well.The id of the batch root. The batch root is the
batchId of the request, or the entry’s own id when the request starts a batch. The client sends this value as X-Inertia-Devtools-Parent on its next follow-up request, such as a partial reload, a deferred props request, or a polling request. Every follow-up request then points at the root, which keeps the batch flat. A full navigation sends no parent header and starts a new batch, so a redirect and its target appear as separate roots. A prefetch response returns its own id instead. The user may never visit a prefetched page, so a prefetch must not change the batch root for other requests.X-Inertia-Devtools-Id as the next parent. Each follow-up request then attaches to the previous response instead of the batch root.
The Read API
The read API has two endpoints at fixed paths below the application’s base path. The adapter allows access to them only in development or for an authorized developer.GET /_inertia/devtools/entries/{id} returns one entry as JSON, or a 404 response for an unknown id. The extension calls only this endpoint. It reads an id from the discovery script or the response header, then fetches that entry.
GET /_inertia/devtools/entries returns a JSON array of entry summaries, newest first. Each summary is the entry’s __meta object. The extension does not call this endpoint, so it is optional. It serves tools that list a tab’s history. An adapter may support the following optional query parameters:
component: keep only entries for this exact component name.type: keep only entries with these request types, as a comma-separated list.exclude: drop entries with these request types, as a comma-separated list.offsetandlimit: page through the results.
The Entry Format
An entry is a JSON object with required and optional fields. The panel needs every required field, so for a value that does not exist, the adapter emits the documented empty form ornull instead of leaving the key out.
Optional fields add detail. An adapter may leave an optional field out, or emit null where the field’s type allows it. The propValues map may also be {}. The panel still works with less detail. For example, it hides “open in editor” links when source locations are missing.
An adapter may add fields beyond this specification. The extension ignores unknown fields instead of rejecting the entry.
A fully populated entry for a standard navigation looks like this.
Meta
The__meta object carries the entry’s identity and summary.
One of the request types.
The Inertia page component, or
null for a response that rendered no Inertia page.The time of the request in seconds since the Unix epoch, as a float. The panel uses it for stable ordering.
The value of
X-Inertia-Devtools-Tab, or null when the request carries no tab header. The extension adds the header only for hosts where it has discovered an entry before, and it remembers those hosts. A request to a host it has not discovered yet has no tab header.timestamp and utime describe the same instant in two forms. timestamp keeps a stored entry readable on its own. utime has sub-millisecond precision, and the panel orders and groups entries by it. The adapter derives both values from the same instant.HTTP
Thehttp object and each of its keys are required. With nothing to show, the adapter emits the empty form.
BodyCapture is a tagged union.
value is a string for a raw text body. For structured data, such as parsed JSON or form input, it is a JSON-compatible value. The panel recognizes the following omitted reasons: non-inertia-response, non-inertia-request, non-textual, streamed, too-large, unserializable, and binary. It shows a readable notice for each one, and a generic message for an unknown reason, so an adapter may add new reasons. An adapter should redact sensitive keys and summarize file uploads instead of serializing binary content.
Props
Metadata for each prop, keyed by dotted path. The panel builds its prop tree from this map and adds intermediate nodes for dotted paths. A listed prop without metadata children shows its nested values from
propValues, so those nested paths need no entries of their own. A prop with metadata children shows the child rows instead. An adapter that cannot classify a top-level prop still lists it, with empty metadata. With props set to {}, the panel shows no props, even when propValues contains values.The resolved prop values, keyed by dotted path. The adapter replaces sensitive values with
"[REDACTED]". It may leave the field out or send {}, and the panel handles both.Route
The source location of the render call, or
null when the adapter cannot resolve it.null and loses only those links.
Request Type Derivation
The adapter derives the request type from the request headers, including the two DevTools hint headers. It checks the following conditions in order and uses the first match.initial and http are both non-Inertia requests. The adapter tells them apart by whether it rendered an Inertia page. The application’s initial full-page load renders a page, so its component is set and its type is initial. A plain JSON or text endpoint that the application serves next to Inertia renders no page, so its component is null and its type is http. The adapter knows which kind of response it produced, so it sets the type instead of leaving the panel to work it out.
The client-visit and cache-hit types are client-only and never come from an adapter.
Storage Semantics
An adapter keeps recent entries and evicts old ones. It usually limits the number of entries for eachtabUuid, so a busy tab cannot evict another tab’s history. It also removes entries older than a time limit. The adapter chooses these limits. The protocol requires only that the read API return the stored entries, newest first.