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 container Structure meta track notes symbols road types junctions result QR conformance full example

Why .rdbk

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

FieldTypeMeaning
titlestringHuman-readable roadbook title.
total_distanceintegerTotal route length in metres (derived from track).
note_countintegerNumber of navigational notes (comment notes are not counted).
descriptionstringOptional. Free text shown on the public challenge page.
authorstringOptional. Name of the roadbook author.
organizationstringOptional. Organizing club / event organizer.
modifiedstringOptional. Last-modified date, ISO YYYY-MM-DD.
logostringOptional. Event logo as a base64 data: URI (embedded, self-contained — like the symbols in icons).
map_accessbooleanOptional. 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).
profilestring, optionalOptional. 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_radiusinteger, optionalOptional. 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.

FieldTypeMeaning
numinteger1-based note number (display order).
idxintegerIndex into track where this note sits.
lat, lonnumberNote position (decimal degrees).
distanceintegerCumulative distance from the start (metres).
partial_distanceintegerDistance from the previous note (metres).
textstringThe instruction / comment.
capinteger | nullCAP — the heading in degrees (0–360) to hold to the next note, when shown.
cap_distanceinteger | nullStraight-line distance to hold that heading (metres).
cap_typestring, optionalOptional. Qualifies the CAP: exit (default), average, calculated or turning.
bearing_innumberTrack bearing arriving at the note (degrees).
bearing_outnumberTrack bearing leaving the note (degrees).
road_type_in0–4Surface arriving — see road types.
road_type_out0–4Surface leaving.
speed_limitinteger, optionalOptional. Declarative speed limit (km/h) in force from this note; 0 = limit lifted. Preferred over a limit encoded in a symbol name.
danger1–3, optionalFIA-style danger grading. Renders as ! / !! / !!! in red inside the diagram box (never in the text column). Absent or 0 = no danger.
wp_typestring, optionalOptional. 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_radiusinteger, optionalOptional. Per-note validation radius (metres). When absent, falls back to meta.default_wp_radius then the type default.
iconsarrayPositioned symbols — see symbols.
junctionsarray | nullJunction vectors — see junctions.
note_kindstring, optionalOptional. 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.
imagestring, optionalOptional (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.

FieldTypeMeaning
namestringSymbol key; looked up in icons.
pos[x, y]Centre position in reference units, from box centre, +y up.
sizenumberBox size in reference units (square).
anglenumberRotation, degrees clockwise.
flip_xbooleanHorizontal 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

idTypeRendering
0Defaultneutral, medium stroke
1Motorway / paved fastsolid, widest stroke
2Asphaltsolid, wide stroke
3Track / pistesolid, medium stroke (default off-road)
4Off-pistedashed, 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 }
]
FieldTypeMeaning
pivot[x, y]Vector start (reference units, +y up).
tip[x, y]Vector tip / arrow head.
widthnumberStroke thickness.
road_type0–4Road 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:

FieldWidthMeaning
team3Vehicle number.
date6Date DDMMYY.
start6Start time HHMMSS.
end6End time HHMMSS.
accuracy4Accuracy penalty.
skip4Skipped-note penalty.
extra4Overshoot penalty.
cap4Heading penalty.
speed4Speed penalty.
km5Distance, deci-km.
avg3Average 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

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…" }
}

Open a .rdbk in the Reader