Specification · v1.2

Format specification

Complete entity-by-entity reference. Fields marked * are required. Any field not documented here MUST be ignored, never rejected by a player — this rule is what makes minor versions backward compatible.

Conventions#

ConceptRule
idFree-form non-empty string, unique within its collection. Prefer short and stable ("d1", "b-x7k2").
datesISO format YYYY-MM-DD (e.g. "2026-08-04").
times24-hour "HH:MM" (ISO 8601 style, zero-padded: "09:00", "14:30"). The file always stores this canonical form; players display times localized to the reader's locale (2:30 PM for en-US) and edit them with native time components.
timezonesAll times are local wall-clock times at the place where the item happens. Optional timezone fields (IANA, e.g. "Europe/Paris") at trip, day, item and transport-point level are metadata enabling cross-zone computations (flights). An item ending the next day uses endDate. Since 1.2.
imagesFields image, cover, voucher, icon: an absolute URL, a player-relative path, or a data-URL. Prefer URLs to keep files small.
fileExtension .roadbook.json, UTF-8 encoded.
versionRoot field formatVersion ("1.2"). Absent means "1.0". See versioning.
pricesprice fields are total amounts (all travelers); currency is ISO 4217 and defaults to the trip's currency (itself defaulting to "EUR"). Since 1.1.
enum valuesEnumerated values are English tokens ("meal", "confirmed"…) and are part of the wire format — used verbatim in the file, translated by the player at display time.

Root object — the trip#

FieldTypeDescription
formatVersionstringFormat version ("1.0"). Absent = 1.0.
currencystringDefault currency for all prices (ISO 4217). Absent = "EUR". Since 1.1.
timezonestringDefault IANA timezone of the trip. Since 1.2.
id *stringUnique trip identifier.
name *stringTrip name.
subtitlestringTagline.
start *dateFirst day.
end *dateLast day (≥ start).
coverimageCover image.
members *Member[]The travelers.
days *Day[]The days, sorted by ascending date.
bookingsBooking[]Reservations (stays, activities…).
checklistsChecklist[]Check lists (luggage, documents…).
contactsContact[]Contacts and emergency numbers.
logisticsLogisticsNote[]Free-form logistics notes.
appsAppLink[]Useful apps for the trip.
peoplePerson[]On-site people to meet: guides, drivers, hosts. Since 1.2.
vehiclesVehicle[]Vehicles used during the trip. Since 1.2.

Member — a traveler#

FieldTypeDescription
id *stringMember identifier.
name *stringDisplay name.
role *enumowner (administers), editor (can modify), viewer (read-only). At least one owner is recommended.
kind *enumadult, teen, child.
agenumberAge (pricing, tickets).
surpriseModeenumSpoiler protection: day = future days hidden for this member; activity = only the next item of the day is revealed.
surprisebooleanDeprecated — boolean ancestor of surpriseMode, kept for compatibility.
phone / emailstringContact details. Since 1.2.
loyaltyarrayLoyalty programs: { program, number }[] (frequent flyer, hotel status…). Since 1.2.
dietarystring[]Dietary restrictions (free tokens: vegetarian, halal, gluten_free…). Since 1.2.
accessibilitystring[]Accessibility needs (free tokens: wheelchair…). Since 1.2.

Person — someone to meet on-site#

Guides, drivers, hosts — referenced by personIds on items and bookings. Since 1.2.

FieldTypeDescription
id * · name *stringIdentifier and display name.
roleenumguide, driver, host, contact, other.
photoimagePhoto — to recognize the person at the meeting point.
phone / emailstringDirect contact.
messagingarray{ app, handle }[] — app is a free token (whatsapp, wechat, telegram…).
languagesstring[]Spoken languages (ISO 639-1).
orgstringOrganization (tour operator, agency…).
signstringRecognition sign ("name board GODON", "red umbrella").
notestringFree note.

Vehicle#

Referenced by route.vehicleId (day) and transport.vehicleId. Since 1.2.

FieldTypeDescription
id * · name *stringIdentifier and display name ("Our Tesla", "MacBike rentals").
kindenumcar, van, motorcycle, bike, camper, other.
energyenumelectric, gasoline, diesel, hybrid, plugin_hybrid, other.
platestringLicense plate (often required by parking bookings).
rentalobject{ company?, ref?, pickup?, dropoff? }.

TransportDetails — structured journey#

Attached to items (flight, train, drive, transfer…) and to transport bookings. Since 1.2.

FieldTypeDescription
carrier / numberstringAirline / operator, and flight or train number ("Air France", "AF1234").
refstringPNR / booking reference.
from / toTransportPoint{ name?, address?, coords?, terminal?, gate?, platform?, timezone? } — the two ends of the journey (a transfer has a pickup and a destination).
vehicleIdstringVehicle used (references Vehicle.id).

Day#

FieldTypeDescription
id *stringDay identifier.
index *integerDay number (1 = first day), consistent with date order.
date *dateDate, within the trip period.
title *stringLabel (e.g. "Bruges → Brussels").
introstringNarrative introduction for the day.
timezonestringDominant IANA timezone of the day. Since 1.2.
stayBookingIdstringOvernight accommodation (references a Booking.id).
routeobject{ km?, drive?, charge?, vehicleId? } — distance, human-readable driving time, EV charging plan, day's vehicle (vehicleId since 1.2).
coordsobject{ lat, lon, label } — the day's position (weather, map).
items *DayItem[]The day's items, sorted by time.
tipstringTip of the day.
planBstringDay-level fallback plan (free text).

DayItem — an itinerary item#

FieldTypeDescription
id *stringItem identifier.
timetimeStart time ("09:00", "14:30").
endTimetimeEnd time.
endDatedateEnd date when different from the day — overnight flight arriving D+1. Since 1.2.
timezone / endTimezonestringIANA timezones of start/end (times stay local wall-clock). Since 1.2.
title *stringItem title.
descstringFree description.
type *enumActivities & places: activity, nature, heritage, hike, sport, shopping, event, nightlife, wellness, viewpoint, tasting · Journeys: drive, flight, train, boat, ferry, transit, transfer, bike, walk · Food & energy: meal, charging, fuel · Daily life & business: break, laundry, admin, medical, work, meeting, conference · Lodging & free: checkin, checkout, free, night. Extended in 1.2.
stars0–3Must-see level.
placestringHuman-readable address or place.
mapsQuerystringQuery for a mapping service (when place is not enough).
coordsobject{ lat, lon } — item position (offline maps, proximity). Since 1.2.
memberIdsstring[]Travelers concerned (references Member.id); absent = everyone. Since 1.2.
personIdsstring[]On-site people to meet (references Person.id). Since 1.2.
transportTransportDetailsStructured journey (see TransportDetails). Since 1.2.
attachmentsAttachment[]Item-level documents { id, label, url }. Since 1.2.
price / currencynumber / stringTotal price of the item (all travelers) and its ISO 4217 currency (absent = trip currency). Players may aggregate a trip budget. Since 1.1.
priceEstimatedbooleantrue = forecast price; absent/false = actual amount. Since 1.2.
menuUrlstringLink to the menu (restaurants). Since 1.1.
outfitstring[]Recommended outfit / gear. Known tokens: casual, sport, dressy, warm, windproof, waterproof, beach, swimsuit — other strings tolerated. Players may aggregate a day's values into a "what to wear today" hint. Since 1.1.
bookingIdstringLinked reservation (references a Booking.id).
criticalstringCritical warning (strict time slot, last entry…).
status *enumplanned, done, skipped, replaced — the lived state, updated during the trip.
alternativesAlternative[]Conditional fallbacks for this item.
optionsItemOption[]Interchangeable choices — see the distinction below.
chosenOptionIdstringSelected option (references an entry of options). Absent until the choice is made.
imageimageHeader image.
Options ≠ alternatives. options are interchangeable possibilities for the same slot (three candidate restaurants — decided on-site; the chosen option's image replaces the item's). alternatives are fallback plans triggered by an event: triggerrain, wind (with windThreshold km/h), cancellation, closure, fatigue, mood. A player may surface the alternative when the condition occurs.

Alternative — conditional fallback#

FieldTypeDescription
id *stringIdentifier.
trigger *stringTrigger — known values: rain, wind, cancellation, closure, fatigue, mood.
title *stringThe replacement activity.
descstringDetails.
windThresholdnumberWind threshold (km/h) for the wind trigger.

ItemOption — on-site choice#

FieldTypeDescription
id *stringIdentifier.
title *stringOption name.
descstringDetails (specialty, price…).
placestringAddress.
mapsQuerystringMapping query.
coordsobject{ lat, lon }. Since 1.2.
menuUrlstringLink to the menu (restaurants). Since 1.1.
imageimageReplaces the item's image when this option is chosen.

Booking — a reservation#

FieldTypeDescription
id *stringIdentifier.
type *enumstay, activity, parking, transport, restaurant, other.
status *enumconfirmed, to_book, optional, cancelled.
title *stringVenue / service name.
hotelStarsnumberHotel star rating.
datesstringHuman-readable dates ("nights of Aug 2–3").
checkin / checkouttimeStructured check-in / check-out times ("15h"). Since 1.2.
breakfastIncludedbooleanBreakfast included (stays). Since 1.2.
roomsRoom[]{ label, memberIds? }[] — rooms and their occupants. Since 1.2.
memberIds / personIdsstring[]Travelers concerned (absent = everyone) and on-site people (host, driver…). Since 1.2.
transportTransportDetailsStructured transfer (pickup → destination) — see TransportDetails. Since 1.2.
paymentobject{ status? (prepaid|deposit|onsite|invoice), deposit?, payer? (personal|company), note? }. Since 1.2.
priceEstimatedbooleantrue = forecast price. Since 1.2.
addressstringPostal address.
gpsAddressstringAddress to feed the GPS when different (parking entrance…).
phone / email / websitestringContact details.
cancellationstringCancellation policy.
instructionsstringArrival instructions, access codes…
price / currencynumber / stringTotal price of the booking and its ISO 4217 currency (absent = trip currency). Since 1.1.
menuUrlstringLink to the menu (restaurants). Since 1.1.
refsBookingRef[]References: { label, value, sensitive? }. sensitive: true = masked by default.
ticketsTicket[]Individual tickets.
attachmentsAttachment[]Attached documents: { id, label, url }.
reminderobject{ date, action, done? } — dated reminder ("book before…").

Ticket#

FieldTypeDescription
id *stringIdentifier.
label *stringLabel ("Adult", "Flight 2").
code *stringHuman-readable ticket number.
holderstringDisplayed holder name (free string — prefer memberId for a strong link).
memberIdstringHolder as a Member.id reference — survives renames. Since 1.2.
date / timedate / timeTicket-specific slot (individual entry time). Since 1.2.
seatstringAssigned seat. Since 1.2.
validUntildateUse-by date (open vouchers). Since 1.2.
payloadstringThe content actually encoded in the QR / barcode, which may differ from the ticket number. This is what a player renders scannable — always store the real payload.
formatenumqr, code128, pdf417 (IATA boarding passes), aztec (European trains), ean13, datamatrix. Extended in 1.2.
voucherimageOriginal voucher image (available offline in a good player).

Checklist#

FieldTypeDescription
id * · title * · emojistringIdentifier, title, decorative emoji.
items *arrayEntries { id, label, done }.

Contact#

FieldTypeDescription
id * · name *stringIdentifier and name.
phonestringNumber, callable from a player.
notestringContext ("valid across the EU").

LogisticsNote#

FieldTypeDescription
id * · title * · content *stringIdentifier, title, content (multiline).
emojistringDecorative emoji.
FieldTypeDescription
id * · name *stringIdentifier and name.
descstringWhat it is useful for on this trip.
urlstringWebsite.
ios / androidstringApp Store / Google Play links — a player shows the current platform's.
icon / emojiimage / stringIcon (emoji as fallback).

Integrity rules#

Beyond structure, the official validator checks:

id uniqueness within each collection · startend and day dates within the trip period · days sorted by date with consistent index values · valid references (bookingId, stayBookingId, chosenOptionId) · date and time formats.

Structural defects are errors (invalid file); reference or ordering inconsistencies are warnings (the file remains playable).