Wire protocol
Your cart form posts, the badge changes, the drawer morphs, and another tab catches up. On the wire, that flow is a small set of readable headers and HTML-like frames. This page names those pieces so you can inspect a network trace, understand what the loader will apply, and compare prod delta frames with dev's full values.
The vocabulary is shared across enhanced mutations, typed reads, first-render defer streams, and live/refetch transports. The server does not keep a session of what is on screen; the browser sends the stamped targets it currently has, and the response carries server truth for those targets.
Enhanced mutation request#
An enhanced form posts to the generated mutation endpoint with ordinary form data plus framework headers derived from the live DOM:
POST /_m/cart/add HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Kovo-Fragment: true
Kovo-Targets: cart-badge=cart; cart-drawer=cart
Kovo-Live-Targets: cart-badge#cart-badge:{}
Kovo-Idem: cart-submit-01
productId=p1&quantity=2&kovo-csrf=csrf-tokenKovo-Fragment: trueasks for an enhanced response instead of the no-JS POST-redirect-GET path.Kovo-Targetsis read fromkovo-depsstamps in the current DOM. It tells the server which visible targets depend on which query instances.Kovo-Live-Targetscarries the reconstructable component target identity and serialized props the compiler proved sufficient to render a server-refreshable fragment.Kovo-Idemis the replay token. Duplicate submissions replay the stored result instead of re-running the write.kovo-csrfstays in form data so the same mutation endpoint works with and without JavaScript.
App code does not construct these headers. The compiler and loader derive them from declared queries, mutations, components, guards, and DOM stamps.
Enhanced mutation response#
After the mutation commits, the server intersects the committed changes with the submitted targets and sends query values, fragments, or both:
HTTP/1.1 200 OK
Content-Type: text/vnd.kovo.fragment+html; charset=utf-8
Kovo-Build: mutation-response-test-build
Kovo-Changes: [{"domain":"cart","keys":["cart"]}]
Kovo-Idem: cart-submit-01<kovo-query name="cart">{"count":3,"items":[{"id":"p1","qty":2}]}</kovo-query>
<kovo-fragment target="cart-drawer">
<aside kovo-c="cart-drawer" kovo-deps="cart">...</aside>
</kovo-fragment>Kovo-Changes is intentionally small: changed domains and keys only. It must not include input
values, validation detail, stack traces, or other internal state.
<kovo-query> replaces the held query value, then the loader runs that query's generated update
plan across bindings, named derives, and stamps.
<kovo-fragment> morphs the target DOM. Focus, selection, scroll position, CSS transitions, and
user-agent state survive where the morph algorithm can preserve them. mode="append" is the
explicit append vocabulary for list pagination and streams.
Run it#
Submit one enhanced mutation with the network panel open. The request should carry the stamped target headers, and the response should be readable as text:
Kovo-TargetsandKovo-Live-Targetsshow what the browser said was visible.- The body comes back as
<kovo-query>and<kovo-fragment>frames in the order the loader will apply them.
If you want the raw bytes, repeat the same submit with "Copy response" or with an HTTP client against the same mutation endpoint.
Typed reads#
Every query instance is also addressable as a GET. The loader uses this endpoint for focus refetches, GET-form fragment responses, async option reads, and recovery from an unsafe delta:
GET /_q/product?id=p1 HTTP/1.1
Kovo-Fragment: true<kovo-query name="product:p1">{"name":"Mug","stock":4}</kovo-query>/_q/<query-key> responses carry the app-build token. If a long-open tab has a
different token, the client discards the in-place merge and follows the build-skew recovery path
instead of merging a foreign query shape.
Guarded or session-dependent query reads are credentialed private reads. They must carry
Cache-Control: private, no-store and Vary: Cookie; only compiler-proved session-independent
queries can opt into a cacheable read posture.
Streaming frames#
First-render <Defer> and streaming mutation responses reuse the same readable frame vocabulary:
<kovo-defer target="product-grid" state="pending"></kovo-defer>
<kovo-query name="productGrid">{"items":[...]}</kovo-query>
<kovo-fragment target="product-grid">...</kovo-fragment><kovo-defer> is framework-emitted. App TSX authors the public <Defer> primitive; the wire
placeholder is an implementation frame.
Streaming mutation text uses a narrow text source, not raw HTML:
<kovo-fragment target="messages" mode="append">
<article data-stream-text="assistant:a1"></article>
</kovo-fragment>
<kovo-text target="assistant:a1" mode="append">Escaped token text</kovo-text>
<kovo-text target="assistant:a1" mode="checkpoint">Server-confirmed text so far</kovo-text><kovo-text> appends or checkpoints text. It does not insert model output as markup. Rich rendering
has to pass through an explicit trusted-HTML boundary, which keeps model-output XSS visible to
audits.
Prod delta frames#
Development responses favor full values because they are easiest to read. Production may send a smaller frame when the compiler and runtime can prove it is equivalent. There is no per-call-site knob; prod picks full or delta per response.
Delta frames are scoped by the committed change record, not by a server-side memory of the client. This is the real envelope shape from the committed wire tests:
<kovo-query name="cart" key="cart:c1" version="7" settles="idem_update_p0" delta>
{"set":{"count":3},"lists":{"items":{"key":"productId","upsert":[{"productId":"p0","qty":2}]}}}
</kovo-query>The attributes matter when you are reading a trace:
keynames the concrete query instance.versionis the query value version when the response carries one.settlesnames the optimistic tokens this truth chunk commits.Kovo-Buildon the HTTP response carries the app-build token used for skew checks.
The client treats arriving server truth as authoritative for the committed mutation response. It drops the matching optimistic prediction before re-applying any still-pending predictions, so confirmed writes are not counted twice. Settlement bookkeeping is a client/runtime concern, not an app-authored wire attribute.
Deep-merge semantics are fixed:
- Non-keyed scalar fields present in the delta replace the base field.
- Non-keyed object fields present in the delta replace the whole object subtree.
- Keyed collections merge by
kovo-key: touched rows are upserted by identity, and rows are deleted only when their key appears inlists.<path>.remove. setreplaces top-level non-collection fields,listscarries keyed collection edits, and there is no field tombstone vocabulary.
A collection is delta-eligible only when its kovo-key maps to domains and explicit keys in the
change record. Otherwise the response ships the whole value or a full fragment.
The client applies a delta only when it already has a base value for that query and the render-plan
version token matches. Missing base, long-open-tab skew, or stale prerender skew all fall back to a
full read over /_q/<query-key>.
Live scope#
The same <kovo-query> and <kovo-fragment> vocabulary is designed to work over live transports,
but <kovo-live> is not part of the shipped guide surface yet. Treat live subscriptions as
technical-preview roadmap material until the live-query guide and implementation evidence say
otherwise.
Next#
- Mutations & forms - the authoring surface that produces enhanced mutation requests.
- Queries & invalidation - query instances, DOM stamps, and update plans.
- Streaming & defer - first-render defer and streaming mutation examples.
- Request shell - dispatch order for
/_m/,/_q/, client modules, endpoints, and routes.
Spec & diagnostics
Enhanced mutation request and response headers, target selection, text/vnd.kovo.fragment+html,
Kovo-Changes, query/frame escaping, fragment morphing, streaming mutation text, and no-JS
degradation: SPEC §9.1. Prod delta encoding, deep-merge semantics, removed-key lists, base-version
validation, full-vs-delta selection, and kovo explain reconstruction:
SPEC §9.1.1. BroadcastChannel, refetch, and live transport vocabulary: SPEC §9.3. Typed reads,
guarded read cache posture, and canonical query instance keys: SPEC §9.4. Build-skew recovery:
SPEC §14.
API reference: @kovojs/browser, @kovojs/core, @kovojs/server.