Airbnb's server-driven UI (SDUI) departs from the usual approach to implement client UIs for different platforms, including Web, Android, and iOS. Instead of letting each client platform drive its UI, SDUI passes both the data and its UI representation to the client.
Airbnb’s specific SDUI implementation enables our backend to control the data and how that data is displayed across all clients at the same time. Everything from the screen’s layout, how sections are arranged in that layout, the data displayed in each section, and even the actions taken when users interact with sections is controlled by a single backend response across our web, iOS, and Android apps.
At the heart of Airbnb's SDUI lies the Ghost Platform (GP), which includes native frameworks for all supported platforms and provides a common collection of sections, layouts, and actions. GP uses Viaduct, a GraphQL-based data layer, as a unified data-service mesh to provide responses and strongly typed models across all platforms.
This schema is powerful enough to account for reusable sections, dynamic layouts, subpages, actions, and more, and the corresponding GP frameworks in our client applications leverage this universal schema to standardize UI rendering.
The Ghost Platform provides three types of elements to clients: sections, which are independent groups of related UI components; screens, which define where and how sections will appear; and actions, which are used to handle user interaction.
This is an example of how a section declaration can look like. It is worth noticing that each Section
is wrapped through a SectionContainer
which also contains a SectionComponentType
. This enables the selection of alternative renderings of the same section depending on the context.
# Example sections
type HeroSection {
# Image urls
images: [String]!
}
type TitleSection {
title: String!,
titleStyle: TextStyle!
# Action to be taken when tapping the optional subtitle
onTitleClickAction: IAction
}
enum SectionComponentType {
HERO,
TITLE,
PLUS_TITLE,
# ...
}
union Section = HeroSection
| TitleSection
| # ...
# The wrapper that wraps each section
type SectionContainer {
id: String!
# The key that determines how to render the section data model
sectionComponentType: SectionComponentType
# The data for this specific section
section: Section
# ... Metadata, logging data & more
}
Screen
declarations are more limited in scope, since they provide mainly two specifications: whether the screen should appear as a popup, sheet, etc., and the layout to use for supported form factors.
type ScreenContainer {
id: String
screenProperties: ScreenProperties
layout: LayoutsPerFormFactor
}
...
type SingleColumnLayout implements ILayout {
nav: SingleSectionPlacement
main: MultipleSectionsPlacement
floatingFooter: SingleSectionPlacement
}
type MultiColumnLayout implements ILayout {
...
}
Parsing the response it receives from the server, GP is able to render all UI sections and place them in their layouts.
Airbnb Ghost Platform is a relatively young project that has found wide adoption within Airbnb, says Airbnb engineer Ryan Brooks. The key to its success is counting on a robust and flexible schema as well as on client-side frameworks to render UI components from it.
If you are interested in more detail, do not miss Brooks' article and his talk at Airbnb’s Re-engineering Travel.