Airbnb server-driven user interface platform

Airbnb’s server-driven user interface (SDUI) departs from the usual approach of implementing client user interfaces for different platforms including web, Android, and iOS. Instead of letting each client platform drive its user interface, SDUI passes both the data and its user interface representation to the client.

Airbnb’s specific SDUI implementation allows our backend to control what data and how that data is displayed on all clients at the same time. Everything from the screen layout to the section layout in this layout, to the data displayed in each section and even the actions taken when users interact with the sections, is controlled by a single main response on our web apps, iOS. and Android.

At the heart of Airbnb’s SDUI is 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 data layer based on GraphQL, as a unified data service mesh to deliver strongly typed responses and models across all platforms.

This schema is powerful enough to take into account reusable sections, dynamic layouts, subpages, actions, etc., and the corresponding GP frameworks in our client applications take advantage of this universal schema to standardize the rendering of user interface.

The Ghost platform provides three types of elements to clients: sections, which are independent groups of related user interface components; screens, which define where and how the sections will appear; and actions, which are used to manage user interaction.

This is an example of how a section declaration can look like. It should be noted that each Section is wrapped in a SectionContainer which also contains a SectionComponentType. This allows 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, as they mainly provide two specifications: whether the screen should appear as a pop-up, sheet, etc., and the layout to be used 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 {
  ...
}


By analyzing the response it receives from the server, GP is able to render all sections of the user interface 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 a robust and flexible schema as well as client-side frameworks to render its user interface components.

If you’re interested in more details, don’t miss Brooks’ article and his talk at Airbnb’s reengineering journey.

Comments are closed.