rdbk · v1.0application/x-roadbook.rdbk
The .rdbk standard
An open format for digital roadbooks, packaged as a ZIP container. A self-contained UTF-8 roadbook.json carries the whole route — track, notes, headings, junction diagrams and its own symbols — alongside optional photos and voice notes, so a roadbook is just a file you can read, follow, share and archive.
Why .rdbk
- Self-contained. A
.rdbkembeds the symbols it uses (as data URIs), so it renders identically anywhere — offline, years later — with no external icon packs to lose. - Plain JSON inside. Open
roadbook.jsonin any text editor, parse it with one line in any language, diff it in git. - Map-ready. The full GPS track travels with the notes, so any reader can draw the route and place you on it.
- Symbols are first-class. Each note can carry positioned, rotated, scalable pictograms and colored junction vectors — not just a line of text.
Container (the file)
A .rdbk file is a ZIP container. Inside it, roadbook.json holds the roadbook — the schema described below, with symbols still embedded in its icons — alongside optional bundled media:
my-roadbook.rdbk (ZIP)
├─ roadbook.json // the roadbook — schema below
├─ media.json // optional — geotags for the bundled media
├─ photos/… // optional — geotagged photos
└─ audio/… // optional — voice notes
Photos and voice notes are optional: they travel only when the exporter includes them. The file's MIME type stays application/x-roadbook.
Document structure
roadbook.json is a single JSON object with four top-level keys:
{
"meta": { … }, // document metadata
"track": [ … ], // the GPS polyline (ordered points)
"notes": [ … ], // navigation notes, ordered along the track
"icons": { … } // embedded symbol library (name → data URI)
}
Coordinates are WGS-84 decimal degrees. Distances are integer metres. Headings are degrees clockwise from true north (0–360). Symbol angles are degrees clockwise.
meta
| Field | Type | Meaning |
|---|---|---|
title | string | Human-readable roadbook title. |
total_distance | integer | Total route length in metres (derived from track). |
note_count | integer | Number of navigational notes (comment notes are not counted). |
description | string | Optional. Free text shown on the public challenge page. |
author | string | Optional. Name of the roadbook author. |
organization | string | Optional. Organizing club / event organizer. |
modified | string | Optional. Last-modified date, ISO YYYY-MM-DD. |
logo | string | Optional. Event logo as a base64 data: URI (embedded, self-contained — like the symbols in icons). |
map_access | boolean | Optional. Whether a reader may show a map of the route while navigating. Absent or true = allowed; false hides the map (e.g. competitions where map-reading would be cheating). |
profile | string, optional | Optional. Scopes the waypoint-type vocabulary an editor offers: basic (default, essential markers only) or rally (full FIA set). Absent = basic. Editorial only — it does not change how a reader interprets the file. |
default_wp_radius | integer, optional | Optional. Roadbook-wide default validation radius (metres) for waypoints that carry no wp_radius of their own. |
track
An ordered array of points describing the route polyline. Notes reference into it by index. Each point may carry an optional ele — the elevation in integer metres — and an optional t — the fix time in epoch milliseconds (UTC), kept from a recording so tools can order or time-match points.
"track": [
{ "lat": 45.82712, "lon": 9.41164, "ele": 1245, "t": 1783065600000 },
{ "lat": 45.82740, "lon": 9.41180 }
]
notes
The heart of a roadbook: an ordered list of waypoints, each with an instruction, heading and symbols. A reader highlights the active note and validates progress against the GPS track.
| Field | Type | Meaning |
|---|---|---|
num | integer | 1-based note number (display order). |
idx | integer | Index into track where this note sits. |
lat, lon | number | Note position (decimal degrees). |
distance | integer | Cumulative distance from the start (metres). |
partial_distance | integer | Distance from the previous note (metres). |
text | string | The instruction / comment. |
cap | integer | null | CAP — the heading in degrees (0–360) to hold to the next note, when shown. |
cap_distance | integer | null | Straight-line distance to hold that heading (metres). |
cap_type | string, optional | Optional. Qualifies the CAP: exit (default), average, calculated or turning. |
bearing_in | number | Track bearing arriving at the note (degrees). |
bearing_out | number | Track bearing leaving the note (degrees). |
road_type_in | 0–4 | Surface arriving — see road types. |
road_type_out | 0–4 | Surface leaving. |
speed_limit | integer, optional | Optional. Declarative speed limit (km/h) in force from this note; 0 = limit lifted. Preferred over a limit encoded in a symbol name. |
danger | 1–3, optional | FIA-style danger grading. Renders as ! / !! / !!! in red inside the diagram box (never in the text column). Absent or 0 = no danger. |
wp_type | string, optional | Optional. FIA waypoint type: the seven types masked / control / security / navigation / precise / visible / eclipse, plus the start/finish, selective-section, zone and control markers. In a stored .rdbk file the value is written as its OpenRally standard code (WPM, WPN, WPE, WPS, WPC, WPP, WPV, DSS, ASS, DZ, FZ, DN, FN, DT, FT, CP, PC, STOP), which a reader maps back to these types on import. Rendered as a coloured acronym badge by the note number and mapped to a Garmin/OSMAnd symbol on GPX export. |
wp_radius | integer, optional | Optional. Per-note validation radius (metres). When absent, falls back to meta.default_wp_radius then the type default. |
icons | array | Positioned symbols — see symbols. |
junctions | array | null | Junction vectors — see junctions. |
note_kind | string, optional | Optional. When set to "comment", the note is a non-navigational comment note (e.g. a sponsor logo). It carries no lat/lon/idx/num and no geodata, keeps a fixed position in the list, and is shown in the Reader, PDF and challenge view but skipped by the map, scoring, GPS validation and GPX/KMZ export. Absent = a normal navigational note. |
image | string, optional | Optional (comment notes). An embedded image as a data: URI, rendered in the note's diagram box. |
{
"num": 12, "idx": 184,
"lat": 45.8321, "lon": 9.4002,
"distance": 8420, "partial_distance": 630,
"text": "Bear right onto the gravel track",
"cap": 247, "cap_distance": 300, "cap_type": "average",
"bearing_in": 92, "bearing_out": 247,
"road_type_in": 2, "road_type_out": 3,
"speed_limit": 30,
"danger": 2,
"icons": [
{ "name": "S03_30km.svg", "pos": [40, 22], "angle": 0, "size": 32, "flip_x": false }
],
"junctions": [
{ "pivot": [0, 0], "tip": [45, 25], "width": 3, "road_type": 3 }
]
}
A comment note (note_kind: "comment") is coordinate-less — it holds only its text and an optional embedded image:
{
"note_kind": "comment",
"text": "Presented by ACME Rally Gear",
"image": "data:image/png;base64,iVBORw0KGgo…"
}
Symbols (note icons + top-level icons library)
A note's icons array places pictograms on a fixed 230 × 162 reference box. The origin is the box centre; +y points up. This makes a note render the same at any display size.
| Field | Type | Meaning |
|---|---|---|
name | string | Symbol key; looked up in icons. |
pos | [x, y] | Centre position in reference units, from box centre, +y up. |
size | number | Box size in reference units (square). |
angle | number | Rotation, degrees clockwise. |
flip_x | boolean | Horizontal mirror. |
The symbols themselves live inside the file in icons, a map from symbol name to a data URI. This is what makes a .rdbk portable: every symbol it draws is embedded.
"icons": {
"S03_30km.svg": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0i…",
"P07_ponte.png": "data:image/png;base64,iVBORw0KGgoAAAANS…"
}
Resolution order for a symbol: an inline data: URI on the icon → the file's icons (case-insensitive) → a host symbol set. A note may also carry a speed limit encoded in a symbol name (e.g. S03_30km ⇒ 30 km/h; S99_end clears it).
Road types
| id | Type | Rendering |
|---|---|---|
0 | Default | neutral, medium stroke |
1 | Motorway / paved fast | solid, widest stroke |
2 | Asphalt | solid, wide stroke |
3 | Track / piste | solid, medium stroke (default off-road) |
4 | Off-piste | dashed, thinnest stroke |
A note's vignette is a tulip: the road you arrive from always enters from the bottom edge to the box centre (drawn per road_type_in), the road you leave on exits from the centre to an arrow at the top (per road_type_out), and junction vectors branch from the centre. Stroke width is indicative of the road type.
Junction vectors (junctions)
Beyond text, a note can draw the junction itself: one or more vectors on the same 230 × 162 box. Each goes from a pivot to a tip (arrow head), colored by road type and drawn with a stroke width.
"junctions": [
{ "pivot": [0, 0], "tip": [45, 25], "width": 3, "road_type": 3 },
{ "pivot": [0, 0], "tip": [-30, 40], "width": 2, "road_type": 4 }
]
| Field | Type | Meaning |
|---|---|---|
pivot | [x, y] | Vector start (reference units, +y up). |
tip | [x, y] | Vector tip / arrow head. |
width | number | Stroke thickness. |
road_type | 0–4 | Road type → vector color. |
Result token (optional, for events)
When a roadbook is followed competitively, a reader can emit a compact, fixed-width 49-character result token (suitable for a QR code). It is a sequence of zero-padded numeric fields and carries no personal data:
| Field | Width | Meaning |
|---|---|---|
team | 3 | Vehicle number. |
date | 6 | Date DDMMYY. |
start | 6 | Start time HHMMSS. |
end | 6 | End time HHMMSS. |
accuracy | 4 | Accuracy penalty. |
skip | 4 | Skipped-note penalty. |
extra | 4 | Overshoot penalty. |
cap | 4 | Heading penalty. |
speed | 4 | Speed penalty. |
km | 5 | Distance, deci-km. |
avg | 3 | Average speed, deci-km/h. |
The token may be appended with -<sig>, a truncated HMAC over the token, for tamper-evidence between the reader and the scorer.
Conformance
- A
.rdbkis a ZIP container with a UTF-8roadbook.jsoninside; extension.rdbk, media typeapplication/x-roadbook. - A conforming reader MUST read
roadbook.jsonfrom the container, rendertrackandnotesin order and resolve symbols fromiconsfirst. - A conforming writer MUST embed every symbol referenced by any note into
icons, soroadbook.jsonis self-contained. - Unknown fields MUST be preserved on round-trip and ignored if not understood (forward-compatibility).
- A conforming reader MUST render notes with
note_kind: "comment"in the roadbook list but MUST NOT number them, place them on the map, score them or emit them as GPX/KMZ waypoints.
Full minimal example
{
"meta": { "title": "Demo loop", "total_distance": 1210, "note_count": 2,
"author": "Alex Driver", "organization": "Rally Club", "modified": "2026-06-09",
"logo": "data:image/png;base64,iVBORw0KGgo…" },
"track": [
{ "lat": 45.8271, "lon": 9.4116 },
{ "lat": 45.8290, "lon": 9.4135 },
{ "lat": 45.8305, "lon": 9.4150 }
],
"notes": [
{
"num": 1, "idx": 0, "lat": 45.8271, "lon": 9.4116,
"distance": 0, "partial_distance": 0, "text": "Start",
"cap": null, "cap_distance": null, "bearing_in": 0, "bearing_out": 45,
"road_type_in": 3, "road_type_out": 3, "icons": [], "junctions": null
},
{
"num": 2, "idx": 2, "lat": 45.8305, "lon": 9.4150,
"distance": 1210, "partial_distance": 1210, "text": "Finish",
"cap": null, "cap_distance": null, "bearing_in": 45, "bearing_out": 0,
"road_type_in": 3, "road_type_out": 3,
"icons": [ { "name": "i01_arrivo.png", "pos": [0, 0], "angle": 0, "size": 40, "flip_x": false } ],
"junctions": null
}
],
"icons": { "i01_arrivo.png": "data:image/png;base64,iVBORw0KGgoAAAANS…" }
}