Skip to content
Selected work

02 / Immersive visitor platform.

The software behind UN Geneva’s new visitor centre

Immersive visitor platform · UN Geneva Visitor Centre · Dorier · 2025–2026

Forty visitors walk through three pavilions, each hearing narration in their own language that follows them from room to room and stays in step with the projections around them, while a guide runs the tour from a tablet. That is Together, the 60-minute experience at the heart of UN Geneva’s new visitor centre, open since June 2026. I was one of the software engineers on the system behind it: the visitor’s audio guide, the guide’s tablet and the Go services that keep every device in sync.

At a glance

  • Open to the public since June 2026, with about 200,000 visitors a year expected.
  • 3 pavilions · 8 languages · up to 40 visitors per session, every hour.
  • Covered at opening by Geneva Solutions, UN Today and geneveMonde.ch. Watch the experience.

From arrival to a shared decision

Visitors join a scheduled tour and select a language on their audio guide. The guide’s tablet shows the group and controls progression through the experiences. As visitors explore, the backend combines location updates with show cues to determine the audio state sent to each handheld.

In the final experience, kiosks assign visitors fictional-country roles. Visitors choose priorities, consider amendments and cast a final vote. The kiosks follow the presentation’s cues and display shared results received through the messaging system.

What looks like one continuous experience spans several applications, content services and physical systems. The engineering challenge is keeping those parts aligned as people move, devices reconnect and guides advance the tour.

Four steps: join a scheduled tour and choose a language on the audio guide; explore with audio responding to location and show cues; cast a vote at a kiosk; see shared results. A guide tablet controls tour progression.
Visitors join a tour, explore with location-aware audio and take part in a shared voting experience. Staff coordinate the tour from a separate tablet.Open full-size diagram

Visitor audio guide

Four audio-guide screens: language choice with eight languages, the welcome screen, a lobby countdown asking visitors to be at the meeting point, and the site map of the three pavilions.
The visitor’s audio guide, from language choice to the meeting point. Screens from the user manual.Open full-size image

Guide tablet

Four guide-tablet screens: the lobby with a connected visitor, Experience 1 running with a timer, a prompt to lead the group to Experience 2, and the tour-end summary.
The guide’s tablet runs the tour: lobby, show in progress, hand-off to the next pavilion, tour end. Screens from the user manual.Open full-size image

Voting kiosk

Five kiosk screens from the negotiation: choose a priority, receive advice from stakeholder groups, choose an amendment, vote in favour, against or abstain, and the result: agreement passed.
The third pavilion’s negotiation on the kiosks: priority, advice, amendment, final vote, result. The kiosk app was built mainly by Local Projects; screens from the user manual.Open full-size image

My responsibility

Local Projects built the original platform from January 2024, with software engineers Charles Veasey and Miguel Bermudez. In summer 2025 Dorier’s Creative Technology team took it over and carried it to opening. Filipe Lopes Pires led the engineering team under David Granite, director of Creative Technology, with André d’Melo, Boris Poget, Pierre-Igor Berthet and me as software engineers.

Taking over meant learning a production system we had not written, a monorepo of React Native apps, native Android modules, Go services and a CMS, before changing any of it. Local Projects ran a nine-week handoff from 21 July to 19 September 2025: the repository and core services, the guide’s tablet and audio guide, deployment, show control and positioning, logging and how to modify the apps safely, the voting kiosks, testing procedures and the handoff documentation. Alongside those sessions we read our way through the codebase, tracing each flow from the device to the services and back. My first change landed in week eight. Much of the documentation I later wrote started as the map I needed for that.

I worked across the visitor’s audio guide, the guide’s tablet and the Go tour services: positioning inside the app, audio synchronisation and headphone recovery, device-aware tour control, group language flows, the accessibility mode, the Gathering effect, emergency audio, the per-site release builds, and most of the technical documentation the visitor centre’s team now operates from.

React Native · TypeScript · Kotlin · Go · MQTT · Payload CMS · PostgreSQL

Visitors seated in a curved negotiation chamber, voting at kiosks under blue ceiling rings.
A Common Answer, the third pavilion: visitors negotiate and vote on a shared resolution. Photo: Filipe Lopes Pires.Open full-size image
White colonnaded pavilions of the Portail des Nations among trees.
The Portail des Nations pavilions in the park of the Palais des Nations. Photo: Filipe Lopes Pires.Open full-size image

How the platform fits together

One rule shapes the system: the devices render the state they are told; they never decide the flow. The guide’s tablet and show control drive the tour, one State Manager computes each visitor’s state, and every handheld and kiosk simply displays what arrives over MQTT. That rule is what lets 40 devices stay in step. A device that drops out never has to reconstruct the tour: it picks up from the next state it is sent, or the guide forces a resync from the tablet.

The audio guide, guide tablet and voting kiosk serve different roles. Tour services coordinate session and visitor state; the CMS supplies schedules, content and media. Live messages carry tour updates, show cues and kiosk choices alongside the application APIs.

Two external inputs matter to the experience: show control provides presentation state and media cues, while indoor positioning provides visitor-location updates. The backend uses those inputs to compute the state delivered to each audio guide. The kiosk follows its own cue-and-result flow rather than calculating the room’s result locally.

My work covered application and service integration. Colleagues owned show-control configuration, positioning hardware and calibration, device management and site infrastructure.

Tour API context, show-control cues and processed indoor-positioning updates feed state coordination, which sends live state to visitor audio guides. Separately, show-control integration sends cues and results to kiosks and receives visitor choices. CMS supplies content; APIs and MQTT carry requests and live updates.
Tour context, show cues and location updates determine each visitor’s audio state. Kiosks exchange choices, presentation cues and shared results through a separate messaging flow.Open full-size diagram
Detailed system architecture
System overview: indoor positioning, guide-tablet commands and show cues merge in one State Manager, which sends one state per visitor to each audio guide over MQTT; the CMS supplies content; voting kiosks follow show cues on a separate path.
Every input merges in one State Manager, which publishes one state per visitor. Show control, positioning hardware and the kiosks’ show integration were owned by colleagues.Open full-size diagram

Keeping positioning inside the visitor app

The audio guide originally depended on a separate positioning app running in the background. Android could stop that process independently of the visitor application.

I integrated the positioning SDK through a Kotlin module exposed to React Native. The application starts Bluetooth advertising during registration, restarts it during session recovery and stops it during tour cleanup. The integration includes Android Bluetooth permission handling.

This brought the positioning lifecycle into the application using it. It still depends on device permissions and operating-system behaviour; it does not replace the venue’s positioning hardware or calibration.

Keeping audio aligned with the experience

Correcting drift and stale volume changes

An unchanged media reference could leave playback running without applying newer timing information from the show. I added a periodic comparison between the expected position and the audio player’s actual position, seeking when the difference exceeds the correction threshold.

The implementation checks every five seconds and corrects differences above 400 milliseconds. Those values describe the correction policy, not a measured guarantee of synchronisation accuracy.

I also added cancellation for outdated volume fades. A previous fade-to-silence should not continue after a new playback action has set the volume.

Recovering when headphones reconnect

Unplugging headphones can pause Android playback without a matching automatic resume when they are plugged back in. I added a native audio-output detector and connected it to the existing synchronised playback path, so reconnection could resume from the current show position.

The handler avoids restarting audio during a pending recovery, priority audio playback or an already-playing state.

Handling visitors who are already in place

A visitor should not need to move again just because the show has entered its exploration phase. I added backend handling that resolves the visitor’s already-known exhibit zone when that phase begins and publishes the corresponding audio state.

This handles two independent triggers, show progression and visitor movement, without requiring them to arrive in a particular order.

Making tour ownership part of the client–server contract

Two tablets can both appear to control a tour if ownership exists only in their interfaces. I implemented device-aware requests and server-side ownership checks, connecting a guide’s action to the device assigned to the tour.

For a claimed active tour, the checks reject a missing or conflicting device identity. Unclaimed and inactive tours follow compatibility paths. I also added handling to preserve an existing guide-device claim when another create request arrives.

The distinction matters: a local screen can request a change, but the service must decide whether that change is allowed.

Tour takeover sequence showing ownership update, notification to the previous controller and confirmation to the new controller.
The takeover flow updates the controlling device and notifies the previous controller.Open full-size diagram

Guide tablet

Guide tablet showing a Tour Taken Over dialog: another device has taken control of this tour.
What the previous guide sees: control moved to another tablet, so this one disconnects instead of competing.Open full-size image

Carrying language and content through the stack

Group tours needed a shared show language carried consistently from scheduling to playback. I connected that setting across CMS fields, the guide tablet, Go services, database storage and messages sent to show control.

I also extended multilingual content handling and integrated approved translations into the CMS data, shared types and kiosk content path. My contribution covered the engineering and integration of that content, alongside caption behaviour and asset work.

These changes crossed boundaries that are easy to miss when applications are treated separately: a field selected by staff must retain the same meaning in the API, stored tour and presentation system.

A show that works without sound

Deaf visitors needed the full experience, with captions that stay timed to the show. Instead of building a separate caption clock, I kept the audio pipeline running muted, so captions follow exactly the same timeline as everyone else’s audio. A setup question turns the mode on; it skips the sound check, offers caption size and background options, and survives an app restart. Closing a leak where zone audio could still play in deaf mode was part of the same work.

Guide tablet

Guide tablet Device Control panel with eight language options, a captions toggle switched on and a Resync Audio button. Device identifiers are blurred.
Per-visitor control on the guide’s tablet: eight languages, captions, and a forced audio resync. Device identifiers blurred.Open full-size image

The Gathering: position becomes light

In the first pavilion, visitors are drawn towards a central totem. Each handheld turns the indoor-positioning stream into a flash that intensifies as the visitor gets closer, scaling from 5 metres down to 0.5 metres and turning solid white when they arrive. Position updates are throttled to 10 a second and reference-counted across screens.

Two bugs shaped it: the flash stopping at 3 metres, and position messages corrupting the tour server’s state and breaking audio. The first fix for the second bug was reverted and then reworked. The totem’s position now comes from the CMS, and a stress test with simulated positions covers the path.

Chart: flash intensity rises linearly from off at 5 metres to full at 0.5 metres; within 0.5 metres of the totem the screen is solid white.
Distance to the totem drives the flash: linear from 5 m to 0.5 m, solid white on arrival.Open full-size diagram
A long dark pavilion with projected walls and a central lit totem under a circular ceiling light.
A Common Language, the first pavilion, with the central piece visitors gather around. Photo: Filipe Lopes Pires.Open full-size image

Emergency audio: built and tested

Operators needed a way to interrupt every visitor’s audio safely. I built it end to end: database migrations, a Go service and REST API with tests, a CMS collection of pre-recorded messages, MQTT delivery to every handheld, and an emergency button on the guide’s tablet. Operator announcements lower the background to 30% and the foreground to 50%; evacuation messages cut everything and loop. Messages are stored on the device so they play even when the network does not, at the cost of keeping that content in sync.

The feature is complete and tested; when to activate it is the site’s decision.

Giving staff tools to operate the system

I added a device-flag flow that connects an action on the audio guide to a backend update and a visible indicator on the guide’s tablet. It gives staff a way to identify a particular visitor device within the group.

My work also included remote language and caption controls, recovery improvements, persistent device logging and in-app user-guide viewers. Updated guides were subsequently bundled into the application source.

These features support the people running the experience as well as the people taking part in it.

Making the platform understandable after handover

I assembled the technical documentation around how the system actually fits together: application journeys, backend services, API and messaging contracts, verification steps and operating procedures.

That includes the four user manuals the visitor centre’s staff work from, for the audio guide, the guide’s tablet, the voting kiosk and the CMS: 82 pages and 56 annotated screens. I verified each one against the running application and recorded what I checked in a separate verification report, so the manual describes the system as it behaves rather than as it was designed.

The documentation connects source inspection with recorded API checks and application walkthroughs. It distinguishes verified behaviour from remaining checks and identifies where a subsystem belongs to another specialist.

That distinction is part of the handover itself. The next engineer or operator needs to know both how a flow works and where to look when one part stops behaving as expected.

Excerpt from Day in the Life of a Tour documentation explaining the visitor journey and the roles of the audio guide, guide tablet, kiosk and backend.
Technical handover documentation connecting the visitor journey to application behaviour and system responsibilities.Open full-size image

Testing and release

I wrote most of the platform’s automated tests across the audio guide, the tablet and the Go services, plus load-test plans that simulate visitor positions and emergency messages. Release builds are reproducible per site: one script per venue bakes in its configuration and restores the workspace afterwards.

What this work demonstrates

Together has to work for up to 40 people at once, every hour, for an expected 200,000 visitors a year, run day to day by the visitor centre’s own operations team. The hard part was never one screen. It was keeping each visitor’s audio, position, language and the show’s cues in step across handhelds, a guide’s tablet, kiosks and three pavilions, and recovering cleanly when a device or a headset drops.

I took over an established platform from another studio, extended it across the mobile apps and Go services, built the accessibility mode, the Gathering effect and emergency audio, and wrote the manuals and documentation the visitor centre now runs it from.