You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Rewrite Static/Dynamic Composition definitions to mirror each other
and say explicitly what VDP does and does not describe
- Explain the recursion in the abstract instead of asserting it
- State the concrete cost of hardcoded template choices in the
problem statement
- Fix the Section 5.4 resolution example: relative refs without a
leading slash resolve under /api/ per RFC 3986, so use root-relative
paths and note the difference
- Align Section 13.1 prose with its example (VDP-Support/VDP-Version
headers, not a token in Allow)
- Fix multi-view example use case to match its dashboard templates
- Smaller fixes: parallel bullet lists, resolution algorithm recursion
wording, homepage phrasing
A layout template with nested slots, forming a template tree. The sidebar layout has two slots: `sidebarNav` for navigation, and `mainContent` for a dashboard that itself contains three further slots.
31
+
A layout template with nested slots, forming a template tree. The sidebar layout has two slots: `sidebarNav` for navigation and `mainContent` for a dashboard that itself contains three further slots.
32
32
33
33
**Use case:** A dashboard page with a sidebar navigation, stats cards, an activity table, and a chart.
Copy file name to clipboardExpand all lines: docs/index.md
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -23,7 +23,7 @@ hide:
23
23
24
24
## What is VDP?
25
25
26
-
The **View Descriptor Protocol** defines a standard way for APIs to tell clients which templates to use for rendering data. A view descriptor is a JSON structure that identifies a root template by URL and declares how sub-templates compose into named **slots**, forming a recursive template tree.
26
+
The **View Descriptor Protocol** defines a standard way for APIs to tell clients which templates to use for rendering data. A view descriptor is a JSON structure that names a root template by URL and declares which sub-templates fill its named **slots**. Because each slot is itself described by a view descriptor, descriptors form a recursive template tree.
27
27
28
28
VDP works with **any rendering framework** — HTML/Qute, SwiftUI, Jetpack Compose, React, or anything else that supports named insertion points.
29
29
@@ -57,15 +57,15 @@ Embed view descriptors inline (`_view` / `_views` in HAL+JSON) or reference them
57
57
58
58
### Cacheable Descriptors
59
59
60
-
View descriptors are standalone resources with their own URLs, independently cacheable from the data they describe.
60
+
View descriptors are standalone resources with their own URLs, cacheable independently of the data they describe.
61
61
62
62
</div>
63
63
64
64
<divclass="vdp-feature"markdown>
65
65
66
66
### Cross-Platform
67
67
68
-
One API response, multiple views. Serve different template trees for desktop, mobile, compact, and full layouts from the same data endpoint.
68
+
One API response, multiple views. Serve different template trees — desktop, mobile, compact — from the same data endpoint.
Copy file name to clipboardExpand all lines: docs/specification.md
+27-25Lines changed: 27 additions & 25 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,11 +5,11 @@
5
5
6
6
## Abstract
7
7
8
-
The View Descriptor Protocol (VDP) defines a standard mechanism for associating API data responses with the templates that should render them. A **view descriptor** is a JSON structure that identifies a root template by URL and declares how sub-templates compose into named slots, forming a recursive template tree. View descriptors can be transported via HTTP headers (for constrained formats like OData4) or inline in the response body (for flexible formats like HAL+JSON). The protocol is framework-agnostic — templates can be HTML/Qute, SwiftUI views, Compose layouts, or any other rendering format.
8
+
The View Descriptor Protocol (VDP) defines a standard mechanism for associating API data responses with the templates that should render them. A **view descriptor** is a JSON structure that names a root template by URL and declares which sub-templates fill its named slots. Because each slot is itself described by a view descriptor, descriptors form a recursive template tree. View descriptors can be transported via HTTP headers (for constrained formats like OData4) or inline in the response body (for flexible formats like HAL+JSON). The protocol is framework-agnostic — templates can be HTML/Qute, SwiftUI views, Compose layouts, or any other rendering format.
9
9
10
10
## 1. Problem Statement
11
11
12
-
REST APIs return structured data (JSON, XML) that carries no presentation information. The client must independently decide how to render this data — typically by hardcoding template choices into client logic. This creates tight coupling between API consumers and their rendering layer.
12
+
REST APIs return structured data (JSON, XML) that carries no presentation information. Each client must decide on its own how to render that data — typically by hardcoding template choices into client code. As a result, every presentation change requires updating each client, and every client maintains its own copy of the same data-to-template mapping.
13
13
14
14
**VDP solves this by letting the server declare:**
15
15
@@ -28,8 +28,8 @@ REST APIs return structured data (JSON, XML) that carries no presentation inform
28
28
-**Template URL**: A URL identifying a template resource. The URL MUST resolve to a renderable template in the client's rendering framework.
29
29
-**Slot**: A named insertion point in a template where a sub-template can be composed. Slot names correspond to the template's own insertion point identifiers (e.g., Qute's `{#insert slotName}`, HTML's `<slot name="slotName">`).
30
30
-**View Descriptor Resource**: A standalone JSON document containing a view descriptor, addressable by its own URL, cacheable independently of the data it describes.
31
-
-**Static Composition**: Template includes that are hardcoded within the template itself (e.g., a layout always including its `_head` partial). VDP does not manage these — they are the template's internal concern.
32
-
-**Dynamic Composition**: Template slots whose content varies per API response. VDP manages these.
31
+
-**Static Composition**: Composition written directly into a template's source — for example, a layout that always includes its `_head` partial. VDP does not describe static composition; it is internal to the template.
32
+
-**Dynamic Composition**: Composition that changes per API response — a slot whose template is chosen by the server at request time. These are the slots a view descriptor declares.
33
33
34
34
## 3. View Descriptor Format
35
35
@@ -99,7 +99,7 @@ Since each slot value is itself a view descriptor, composition nests to arbitrar
99
99
100
100
### 3.4 Multiple Views
101
101
102
-
A single API response may offer multiple views (e.g., a summary view and a detail view, or views for different device classes). Use a named object at the top level:
102
+
A single API response may offer multiple views (e.g., a summary view and a detail view, or views for different device classes). Declare them as a named map under the `views` key:
103
103
104
104
```json
105
105
{
@@ -187,8 +187,8 @@ The client fetches `https://example.com/views/dashboard.json` to get the view de
187
187
188
188
- Keeps the data payload completely clean
189
189
- Works with **any** data format (JSON, XML, OData4, GraphQL, Protocol Buffers)
190
-
-The view descriptor resource is independently cacheable
191
-
-Uses existing web standards ([RFC 8288](https://www.rfc-editor.org/rfc/rfc8288) Link Relations)
190
+
-Makes the view descriptor independently cacheable
191
+
-Builds on existing web standards ([RFC 8288](https://www.rfc-editor.org/rfc/rfc8288) Link Relations)
192
192
193
193
**For simple cases** (single template, no composition), a shorthand header is also defined:
194
194
@@ -325,19 +325,21 @@ Given an API response at `https://example.com/api/dashboard` with an inline view
325
325
```json
326
326
{
327
327
"_view": {
328
-
"template": "templates/layouts/sidebar",
328
+
"template": "/templates/layouts/sidebar",
329
329
"slots": {
330
330
"mainContent": {
331
-
"template": "templates/components/card"
331
+
"template": "/templates/components/card"
332
332
}
333
333
}
334
334
}
335
335
}
336
336
```
337
337
338
338
Both template URLs resolve against `https://example.com/api/dashboard`:
Note that resolution follows RFC 3986 exactly: a reference without a leading slash resolves relative to the base URL's path, so `templates/components/card` would yield `https://example.com/api/templates/components/card` instead.
341
343
342
344
Servers SHOULD use absolute URLs when view descriptors may be consumed by multiple clients with different base URL contexts.
343
345
@@ -357,23 +359,23 @@ This keeps view descriptors small and avoids pushing selection logic into client
357
359
358
360
## 6. Template Requirements
359
361
360
-
VDP is agnostic to the template language. However, templates used with VDP MUST satisfy one requirement: **named insertion points (slots) that can be filled externally**.
362
+
VDP is agnostic to the template language. However, a template used with VDP MUST meet one requirement: **it exposes named insertion points (slots) that can be filled from outside the template**.
Not all insertion points in a template need to be managed by VDP. Templates commonly include static partials (like a shared `_head` or a footer) that are hardcoded. Only slots that vary per API response need to appear in the view descriptor.
378
+
Not every insertion point in a template needs to appear in the view descriptor. Templates commonly include partials that never change — a shared `_head`, a footer — and those stay hardcoded in the template (static composition, Section 2). Only slots whose content varies per API response belong in the view descriptor (dynamic composition).
377
379
378
380
## 7. Examples
379
381
@@ -514,7 +516,7 @@ This is the pattern used by **quarkus-pha**: Quarkus acts as the BFF, fetching d
514
516
4.**Identify slot insertion points** in the template.
515
517
5.**For each slot** declared in the view descriptor:
516
518
a. Fetch the sub-template from its `template` URL.
517
-
b. If the sub-template's view descriptor has `slots`, recurse (go to step 4).
519
+
b. If the slot's view descriptor itself declares `slots`, repeat steps 3–5 for that descriptor.
518
520
c. Insert the resolved sub-template into the slot.
519
521
6.**Render** the composed template tree with the API response data.
520
522
@@ -551,7 +553,7 @@ When a view descriptor is malformed (invalid JSON, missing required `template` f
551
553
552
554
### 9.4 Graceful Degradation
553
555
554
-
Error handling follows a principle of progressive failure:
556
+
Error handling follows the principle that a failure stays as local as possible:
555
557
556
558
1. A single slot failure does not prevent the rest of the template tree from rendering.
557
559
2. A root template failure prevents rendering entirely — the client falls back to raw data or a default template.
@@ -600,7 +602,7 @@ APIs SHOULD advertise VDP support so clients can detect it programmatically.
600
602
601
603
### 13.1 OPTIONS Response
602
604
603
-
An API endpoint supporting VDP MUST include the `VDP` token in the `Allow` or a custom header in its `OPTIONS` response:
605
+
An API endpoint supporting VDP MUST advertise it in its `OPTIONS` response, using the `VDP-Support` and `VDP-Version` headers:
0 commit comments