The FestiView lineup spec.
A single JSON file that describes a festival — its stages, days, and every set. FestiView reads it straight into the lineup, the map, and your crew's shared schedule. No CMS, no backend calls.
Top-level shape
A lineup file is one JSON object with three keys.
{
"festival": { ... },
"stages": [ ... ],
"days": [ ... ]
}
festival
Metadata about the event. Used for the lineup subtitle, the map anchor, and timezone-aware schedule rendering.
namestringDisplay name of the festival.editionstringThe specific instance — e.g."2026 Weekend 1"or"2025 Edition".venuestringVenue name shown on the lineup header.locationstringCity + region, e.g."Indio, CA".timezoneIANA stringGoverns how set times render in the app. Example:"America/Los_Angeles".latitudenumberFestival center latitude (WGS-84).longitudenumberFestival center longitude.dates.startYYYY-MM-DDFirst day of the festival in local time.dates.endYYYY-MM-DDLast day, inclusive.mapOverlayobject · optionalA georeferenced venue map image. See below.
mapOverlay (optional)
If present, FestiView draws a bitmap venue map on top of the base map, aligned to the coordinates you provide.
imageNamestringName of an image asset bundled by FestiView for this festival.centerLatitudenumberImage center latitude.centerLongitudenumberImage center longitude.latitudeSpannumberVertical extent of the image in degrees.longitudeSpannumberHorizontal extent in degrees.rotationnumber · degreesClockwise rotation applied to the overlay. Use0if the image is already north-up.
stages
An array of every stage at the venue. FestiView uses the color to tint set cards and the coordinates to draw stages on the map.
idstring · stable slugReferenced by every set. Never change this for an existing festival — users' stars are keyed by it.namestringDisplay name. E.g."Coachella Stage","Outdoor Theatre".sortOrderintegerLeft-to-right order in the timeline grid. Lower numbers come first.colorhex stringAccent color, e.g."#E8453C". Used for the timeline column and set cards.latitudenumberStage location for precision-finding and meet-ups.longitudenumberStage longitude.radiusinteger · meters · optionalStage footprint radius, used to size the geofence drawn on the map.
days
An ordered array, one entry per festival day. Each day carries its own list of sets.
dateYYYY-MM-DDLocal-time date the day starts. Late-night sets that spill past midnight still belong to the day they started on.labelstringShort name shown on the day picker —"Friday","Day 1", etc.setsarrayAll sets happening on this day, across every stage.
Set fields
artiststringThe performer name as it should appear on the lineup card.stageIdstring · nullableMust match one ofstages[].idwhen set.nullmeans "artist is on the lineup, stage not yet announced."startTimeISO 8601 · nullableWith an explicit timezone offset, e.g."2026-04-10T21:00:00-07:00".nullwhen set times haven't been published.endTimeISO 8601 · nullableMust be strictly afterstartTimewhen both are set. Crossing midnight is fine — just use the next date.setIDstring · globally uniqueA stable identifier used to key stars, crew overlays, and shared schedules. Convention:"<festival>-<year>-<artist-slug>".
stageId, startTime, and endTime as null. FestiView still shows those sets in the Lineup tab so fans can search, browse, and star their favorites — the timeline and map just light up later when the schedule drops.
Minimal example
{
"festival": {
"name": "Mirage Music Festival",
"edition": "2025 Edition",
"venue": "Sunstone Flats",
"location": "Joshua Tree, CA",
"timezone": "America/Los_Angeles",
"latitude": 33.6803,
"longitude": -116.2373,
"dates": { "start": "2025-04-11", "end": "2025-04-13" }
},
"stages": [
{
"id": "horizon",
"name": "Horizon Stage",
"sortOrder": 0,
"color": "#E8453C",
"latitude": 33.681,
"longitude": -116.238
}
],
"days": [
{
"date": "2025-04-11",
"label": "Friday",
"sets": [
{
"artist": "LUNA RAY",
"stageId": "horizon",
"startTime": "2025-04-11T23:10:00-07:00",
"endTime": "2025-04-12T00:30:00-07:00",
"setID": "mirage-2025-luna-ray"
}
]
}
]
}
Validation rules
- Every
stageIdindays[].sets[]must exist instages[]. setIDmust be globally unique within the file and stable across edits — they're how stars roam between app launches.endTimemust be afterstartTime. Post-midnight sets use the next calendar day in the ISO string but still live under the previous day'ssets.- Every timestamp must carry an explicit UTC offset. Don't emit naked local-time strings.
stages[].sortOrdervalues don't have to be contiguous — FestiView just sorts ascending.
Updates after publication
Lineups change — rain delays, surprise guests, stage swaps. FestiView re-fetches the file on every app open and reconciles by setID. Safe edits to a published file:
- Shift
startTime/endTimeon an existingsetID. - Move a set to a different
stageId. - Add new sets with fresh
setIDs. - Remove a set by dropping it — stars on that set become inactive.
Don't rename a setID or a stages[].id. That silently orphans every user's starred schedule.
Submitting a lineup
- Host the JSON at a stable public URL (Gist, S3, your own server — anything that serves CORS-friendly plain JSON).
- Email lineups@festiview.com with the URL, the festival name, and the dates.
- We'll validate it, add it to the in-app festival picker, and ping you when it's live.
Updates are automatic: once the picker entry exists, it points at your URL, and every re-fetch pulls your latest changes.