SlideShare uma empresa Scribd logo
1 de 45
Rapidlyiteratingacross
platformsusing
server-drivenUI
LAURA KELLY
• Android Engineer
• Previously front-end web
• Trips team
• Itinerary, reservations, and trip planning
• Powerlifter
• Whiskey connoisseur
WhoIam
Airbnbisaddingnewproductsallthetime
Homes
Airbnbisaddingnewproductsallthetime
Homes Experiences
Airbnbisaddingnewproductsallthetime
Homes Experiences Restaurants
Airbnbisaddingnewproductsallthetime
Homes Experiences Restaurants Coworking Spaces
Homes Experiences Restaurants Coworking Spaces
Wewererebuildingnearlythe
samescreen,
multiplyingoureffortsacross
thecodebase
…andacrossplatforms
There’sgottobeabetterway.
Whatwouldanidealsystembe?
Easytounderstand
Flexibletoadapttodesigners
Abletolaunchwithoutanew
PlayStore/AppStorerelease
Minimizerepetition
Easytomaintain
?
Server-drivenUI
Whatisserver-drivenUI?
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_title_subtitle“,

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
ExampleAPIresponse
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
APIResponse
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
APIResponse
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
APIResponse
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name = “row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

})
APIResponse
AndroidCode
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name = “row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

})
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
APIResponse
AndroidCode
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name = “row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

})
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
APIResponse
AndroidCode
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name = “row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

})
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
APIResponse
AndroidCode
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
export default {
'row:header_subtitle_title': HeaderSubtitleTitleRow,
'row:action': ActionRow,
'row:poi_map': MapRow,
. . .

}
ReactWebCode
APIResponse
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
export default {
'row:header_subtitle_title': HeaderSubtitleTitleRow,
'row:action': ActionRow,
'row:poi_map': MapRow,
. . .

}
APIResponse
ReactWebCode
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name= “row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

})
APIResponse
AndroidCode
UIRendering
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name= “row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

})
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
APIResponse
AndroidCode
UIRendering
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name= “row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

})
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
APIResponse
AndroidCode
UIRendering
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name= “row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

})
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
APIResponse
AndroidCode
UIRendering
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
API RESPONSE
Howitworks
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name=“row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

}
UI RENDERING
FRAMEWORK
(React or Epoxy)
Howitworks
{

 "type": "place",

 "id": "123",

 "marquee": {

   "type": "marquee:image",

   "image_urls": [ "sightglassImage.png” ]

 },

 "rows": [

   {

     "type": “row:header_subtitle_title",

     "title": "Sightglass Coffee",

     "starts_at": “Sun, Sept 24, 7:00 PM"

   },

   {

     "type": "row:action",

     "actions": [ /* ... actions here */ ]

   },

   {

     "type": "row:poi_map",

     "address": "1234 Main Street"

   }

 ]

}
API RESPONSE
@JsonSubTypes({
@JsonSubTypes.Type(
value = HeaderSubtitleTitleRowDataModel.class,
name = “row:header_subtitle_title"
),
@JsonSubTypes.Type(
value = ActionRowDataModel.class,
name=“row:action"
),
@JsonSubTypes.Type(
value = POIMapRowDataModel.class,
name = “row:poi_map”
),
. . .

}
UI RENDERING
FRAMEWORK
(React or Epoxy)
Bonusesthatcamewiththissystem
Buildonce
Easilyaccommodateschangingminds
ReuseexistingUIcomponentlibraries
Iterate,reconfigure,andexperiment
onourowntime
• Think about your use case
• Think about platform differences early on
• Know your limits
Tipsforbuildingouta
server-drivenUIsystem
• Mobile-forward companies keen on visual
consistency
• Repetition, and lots of it!
• Limited client-side engineers
• You want to launch on all platforms at the
same time
• Teams that communicate well
Whoshould Whoshouldn’t
Whoshould
• No native app
• Product looks different across platforms and
devices
• Unique screens, minimal visual overlap
Whoshouldn’t
• Mobile-forward companies keen on visual
consistency
• Repetition, and lots of it!
• Limited client-side engineers
• You want to launch on all platforms at the
same time
• Teams that communicate well
THANKS
LAURA KELLY

Mais conteúdo relacionado

Mais procurados

HTML5 after the hype - JFokus2015
HTML5 after the hype - JFokus2015HTML5 after the hype - JFokus2015
HTML5 after the hype - JFokus2015Christian Heilmann
 
Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Remy Sharp
 
An in-depth look at jQuery UI
An in-depth look at jQuery UIAn in-depth look at jQuery UI
An in-depth look at jQuery UIPaul Bakaus
 
jQuery Foot-Gun Features
jQuery Foot-Gun FeaturesjQuery Foot-Gun Features
jQuery Foot-Gun Featuresdmethvin
 
Yearning jQuery
Yearning jQueryYearning jQuery
Yearning jQueryRemy Sharp
 
jQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't KnowjQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't Knowgirish82
 
Responsive Web Design e a Ubiquidade da Web
Responsive Web Design e a Ubiquidade da WebResponsive Web Design e a Ubiquidade da Web
Responsive Web Design e a Ubiquidade da WebEduardo Shiota Yasuda
 
Agile Adoption Anti Patterns
Agile Adoption Anti PatternsAgile Adoption Anti Patterns
Agile Adoption Anti PatternsJames Lewis
 
Илья Пухальский (EPAM Systems)
Илья Пухальский (EPAM Systems)Илья Пухальский (EPAM Systems)
Илья Пухальский (EPAM Systems)Ontico
 
Write Less Do More
Write Less Do MoreWrite Less Do More
Write Less Do MoreRemy Sharp
 
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09Frédéric Harper
 
Jacob Waller: Webifying Titanium Development
Jacob Waller: Webifying Titanium DevelopmentJacob Waller: Webifying Titanium Development
Jacob Waller: Webifying Titanium DevelopmentAxway Appcelerator
 

Mais procurados (17)

HTML5 after the hype - JFokus2015
HTML5 after the hype - JFokus2015HTML5 after the hype - JFokus2015
HTML5 after the hype - JFokus2015
 
Intro to HTML5
Intro to HTML5Intro to HTML5
Intro to HTML5
 
jQuery: Events, Animation, Ajax
jQuery: Events, Animation, AjaxjQuery: Events, Animation, Ajax
jQuery: Events, Animation, Ajax
 
JQuery UI
JQuery UIJQuery UI
JQuery UI
 
Prototype UI
Prototype UIPrototype UI
Prototype UI
 
Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)Is HTML5 Ready? (workshop)
Is HTML5 Ready? (workshop)
 
An in-depth look at jQuery UI
An in-depth look at jQuery UIAn in-depth look at jQuery UI
An in-depth look at jQuery UI
 
jQuery Foot-Gun Features
jQuery Foot-Gun FeaturesjQuery Foot-Gun Features
jQuery Foot-Gun Features
 
Yearning jQuery
Yearning jQueryYearning jQuery
Yearning jQuery
 
jQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't KnowjQuery - 10 Time-Savers You (Maybe) Don't Know
jQuery - 10 Time-Savers You (Maybe) Don't Know
 
Responsive Web Design e a Ubiquidade da Web
Responsive Web Design e a Ubiquidade da WebResponsive Web Design e a Ubiquidade da Web
Responsive Web Design e a Ubiquidade da Web
 
Jquery 5
Jquery 5Jquery 5
Jquery 5
 
Agile Adoption Anti Patterns
Agile Adoption Anti PatternsAgile Adoption Anti Patterns
Agile Adoption Anti Patterns
 
Илья Пухальский (EPAM Systems)
Илья Пухальский (EPAM Systems)Илья Пухальский (EPAM Systems)
Илья Пухальский (EPAM Systems)
 
Write Less Do More
Write Less Do MoreWrite Less Do More
Write Less Do More
 
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
Firefox OS, une plateforme à découvrir - IO Saglac - 2014-09-09
 
Jacob Waller: Webifying Titanium Development
Jacob Waller: Webifying Titanium DevelopmentJacob Waller: Webifying Titanium Development
Jacob Waller: Webifying Titanium Development
 

Semelhante a Rapidly Iterating Across Platforms with Server-Driven UI

Rapidly Iterating Across Platforms using Server-Driven UI
Rapidly Iterating Across Platforms using Server-Driven UIRapidly Iterating Across Platforms using Server-Driven UI
Rapidly Iterating Across Platforms using Server-Driven UILaura Kelly
 
ELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboardELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboardGeorg Sorst
 
Custom Visualizations: What, How and Why
Custom Visualizations: What, How and WhyCustom Visualizations: What, How and Why
Custom Visualizations: What, How and WhyJeroen Van Der A
 
SFScon17 - Patrick Puecher: "Exploring data with Elasticsearch and Kibana"
SFScon17 - Patrick Puecher: "Exploring data with Elasticsearch and Kibana"SFScon17 - Patrick Puecher: "Exploring data with Elasticsearch and Kibana"
SFScon17 - Patrick Puecher: "Exploring data with Elasticsearch and Kibana"South Tyrol Free Software Conference
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说Ting Lv
 
JSON Everywhere
JSON EverywhereJSON Everywhere
JSON EverywhereRaj Singh
 
Rich Results and Structured Data
Rich Results and Structured DataRich Results and Structured Data
Rich Results and Structured DataSMA Marketing
 
Paperjs presentation
Paperjs presentationPaperjs presentation
Paperjs presentationsharp-blade
 
Couchbase N1QL: Index Advisor
Couchbase N1QL: Index AdvisorCouchbase N1QL: Index Advisor
Couchbase N1QL: Index AdvisorKeshav Murthy
 
SDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - JapanSDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - Japantristansokol
 
Building serverless applications on azure
Building serverless applications on azureBuilding serverless applications on azure
Building serverless applications on azureJoe Raio
 
Modernizes your objective C - Oliviero
Modernizes your objective C - OlivieroModernizes your objective C - Oliviero
Modernizes your objective C - OlivieroCodemotion
 
Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...
Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...
Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...RobotDeathSquad
 
APIdays Zurich 2019 - Specification Driven Development for REST APIS Alexande...
APIdays Zurich 2019 - Specification Driven Development for REST APIS Alexande...APIdays Zurich 2019 - Specification Driven Development for REST APIS Alexande...
APIdays Zurich 2019 - Specification Driven Development for REST APIS Alexande...apidays
 
APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...
APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...
APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...apidays
 
Computer vision Nebraska (Nebraska Code)
Computer vision Nebraska (Nebraska Code)Computer vision Nebraska (Nebraska Code)
Computer vision Nebraska (Nebraska Code)Andrew Rangel
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneRafael Felix da Silva
 

Semelhante a Rapidly Iterating Across Platforms with Server-Driven UI (20)

Rapidly Iterating Across Platforms using Server-Driven UI
Rapidly Iterating Across Platforms using Server-Driven UIRapidly Iterating Across Platforms using Server-Driven UI
Rapidly Iterating Across Platforms using Server-Driven UI
 
Drupal Mobile
Drupal MobileDrupal Mobile
Drupal Mobile
 
ELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboardELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboard
 
Custom Visualizations: What, How and Why
Custom Visualizations: What, How and WhyCustom Visualizations: What, How and Why
Custom Visualizations: What, How and Why
 
SFScon17 - Patrick Puecher: "Exploring data with Elasticsearch and Kibana"
SFScon17 - Patrick Puecher: "Exploring data with Elasticsearch and Kibana"SFScon17 - Patrick Puecher: "Exploring data with Elasticsearch and Kibana"
SFScon17 - Patrick Puecher: "Exploring data with Elasticsearch and Kibana"
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说
 
JSON Everywhere
JSON EverywhereJSON Everywhere
JSON Everywhere
 
Rich Results and Structured Data
Rich Results and Structured DataRich Results and Structured Data
Rich Results and Structured Data
 
Prototype UI Intro
Prototype UI IntroPrototype UI Intro
Prototype UI Intro
 
Paperjs presentation
Paperjs presentationPaperjs presentation
Paperjs presentation
 
Couchbase N1QL: Index Advisor
Couchbase N1QL: Index AdvisorCouchbase N1QL: Index Advisor
Couchbase N1QL: Index Advisor
 
SDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - JapanSDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - Japan
 
Building serverless applications on azure
Building serverless applications on azureBuilding serverless applications on azure
Building serverless applications on azure
 
Modernizes your objective C - Oliviero
Modernizes your objective C - OlivieroModernizes your objective C - Oliviero
Modernizes your objective C - Oliviero
 
Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...
Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...
Dr. Strangelove or: How I learned to stop worrying and love HTML, CSS and Jav...
 
20150822 osc-shimane
20150822 osc-shimane20150822 osc-shimane
20150822 osc-shimane
 
APIdays Zurich 2019 - Specification Driven Development for REST APIS Alexande...
APIdays Zurich 2019 - Specification Driven Development for REST APIS Alexande...APIdays Zurich 2019 - Specification Driven Development for REST APIS Alexande...
APIdays Zurich 2019 - Specification Driven Development for REST APIS Alexande...
 
APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...
APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...
APIdays Helsinki 2019 - Specification-Driven Development of REST APIs with Al...
 
Computer vision Nebraska (Nebraska Code)
Computer vision Nebraska (Nebraska Code)Computer vision Nebraska (Nebraska Code)
Computer vision Nebraska (Nebraska Code)
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 

Último

scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...HenryBriggs2
 
457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx
457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx
457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptxrouholahahmadi9876
 
COST-EFFETIVE and Energy Efficient BUILDINGS ptx
COST-EFFETIVE  and Energy Efficient BUILDINGS ptxCOST-EFFETIVE  and Energy Efficient BUILDINGS ptx
COST-EFFETIVE and Energy Efficient BUILDINGS ptxJIT KUMAR GUPTA
 
Thermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.pptThermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.pptDineshKumar4165
 
💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...
💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...
💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...vershagrag
 
Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...
Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...
Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...drmkjayanthikannan
 
Work-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptxWork-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptxJuliansyahHarahap1
 
Thermal Engineering-R & A / C - unit - V
Thermal Engineering-R & A / C - unit - VThermal Engineering-R & A / C - unit - V
Thermal Engineering-R & A / C - unit - VDineshKumar4165
 
Design For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the startDesign For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the startQuintin Balsdon
 
A Study of Urban Area Plan for Pabna Municipality
A Study of Urban Area Plan for Pabna MunicipalityA Study of Urban Area Plan for Pabna Municipality
A Study of Urban Area Plan for Pabna MunicipalityMorshed Ahmed Rahath
 
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptxOrlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptxMuhammadAsimMuhammad6
 
Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...
Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...
Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...Call Girls Mumbai
 
Unleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leapUnleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leapRishantSharmaFr
 
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdfAldoGarca30
 
AIRCANVAS[1].pdf mini project for btech students
AIRCANVAS[1].pdf mini project for btech studentsAIRCANVAS[1].pdf mini project for btech students
AIRCANVAS[1].pdf mini project for btech studentsvanyagupta248
 
Standard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power PlayStandard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power PlayEpec Engineered Technologies
 
"Lesotho Leaps Forward: A Chronicle of Transformative Developments"
"Lesotho Leaps Forward: A Chronicle of Transformative Developments""Lesotho Leaps Forward: A Chronicle of Transformative Developments"
"Lesotho Leaps Forward: A Chronicle of Transformative Developments"mphochane1998
 

Último (20)

scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
 
457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx
457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx
457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx
 
COST-EFFETIVE and Energy Efficient BUILDINGS ptx
COST-EFFETIVE  and Energy Efficient BUILDINGS ptxCOST-EFFETIVE  and Energy Efficient BUILDINGS ptx
COST-EFFETIVE and Energy Efficient BUILDINGS ptx
 
Thermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.pptThermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.ppt
 
💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...
💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...
💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...
 
Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...
Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...
Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...
 
Work-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptxWork-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptx
 
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak HamilCara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
 
Thermal Engineering-R & A / C - unit - V
Thermal Engineering-R & A / C - unit - VThermal Engineering-R & A / C - unit - V
Thermal Engineering-R & A / C - unit - V
 
Design For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the startDesign For Accessibility: Getting it right from the start
Design For Accessibility: Getting it right from the start
 
A Study of Urban Area Plan for Pabna Municipality
A Study of Urban Area Plan for Pabna MunicipalityA Study of Urban Area Plan for Pabna Municipality
A Study of Urban Area Plan for Pabna Municipality
 
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptxOrlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
 
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
 
Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...
Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...
Bhubaneswar🌹Call Girls Bhubaneswar ❤Komal 9777949614 💟 Full Trusted CALL GIRL...
 
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced LoadsFEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
 
Unleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leapUnleashing the Power of the SORA AI lastest leap
Unleashing the Power of the SORA AI lastest leap
 
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
 
AIRCANVAS[1].pdf mini project for btech students
AIRCANVAS[1].pdf mini project for btech studentsAIRCANVAS[1].pdf mini project for btech students
AIRCANVAS[1].pdf mini project for btech students
 
Standard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power PlayStandard vs Custom Battery Packs - Decoding the Power Play
Standard vs Custom Battery Packs - Decoding the Power Play
 
"Lesotho Leaps Forward: A Chronicle of Transformative Developments"
"Lesotho Leaps Forward: A Chronicle of Transformative Developments""Lesotho Leaps Forward: A Chronicle of Transformative Developments"
"Lesotho Leaps Forward: A Chronicle of Transformative Developments"
 

Rapidly Iterating Across Platforms with Server-Driven UI

  • 2. • Android Engineer • Previously front-end web • Trips team • Itinerary, reservations, and trip planning • Powerlifter • Whiskey connoisseur WhoIam
  • 7. Homes Experiences Restaurants Coworking Spaces Wewererebuildingnearlythe samescreen, multiplyingoureffortsacross thecodebase
  • 8.
  • 17.
  • 18. ?
  • 20. Whatisserver-drivenUI? {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_title_subtitle“,
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } ExampleAPIresponse
  • 21. {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } APIResponse
  • 22. {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } APIResponse
  • 23. {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } APIResponse
  • 24. {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name = “row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 }) APIResponse AndroidCode
  • 25. @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name = “row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 }) {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } APIResponse AndroidCode
  • 26. @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name = “row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 }) {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } APIResponse AndroidCode
  • 27. @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name = “row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 }) {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } APIResponse AndroidCode
  • 28. {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } export default { 'row:header_subtitle_title': HeaderSubtitleTitleRow, 'row:action': ActionRow, 'row:poi_map': MapRow, . . .
 } ReactWebCode APIResponse
  • 29. {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } export default { 'row:header_subtitle_title': HeaderSubtitleTitleRow, 'row:action': ActionRow, 'row:poi_map': MapRow, . . .
 } APIResponse ReactWebCode
  • 30. {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name= “row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 }) APIResponse AndroidCode UIRendering
  • 31. @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name= “row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 }) {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } APIResponse AndroidCode UIRendering
  • 32. @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name= “row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 }) {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } APIResponse AndroidCode UIRendering
  • 33. @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name= “row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 }) {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } APIResponse AndroidCode UIRendering
  • 34. {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } API RESPONSE Howitworks @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name=“row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 } UI RENDERING FRAMEWORK (React or Epoxy)
  • 35. Howitworks {
  "type": "place",
  "id": "123",
  "marquee": {
    "type": "marquee:image",
    "image_urls": [ "sightglassImage.png” ]
  },
  "rows": [
    {
      "type": “row:header_subtitle_title",
      "title": "Sightglass Coffee",
      "starts_at": “Sun, Sept 24, 7:00 PM"
    },
    {
      "type": "row:action",
      "actions": [ /* ... actions here */ ]
    },
    {
      "type": "row:poi_map",
      "address": "1234 Main Street"
    }
  ]
 } API RESPONSE @JsonSubTypes({ @JsonSubTypes.Type( value = HeaderSubtitleTitleRowDataModel.class, name = “row:header_subtitle_title" ), @JsonSubTypes.Type( value = ActionRowDataModel.class, name=“row:action" ), @JsonSubTypes.Type( value = POIMapRowDataModel.class, name = “row:poi_map” ), . . .
 } UI RENDERING FRAMEWORK (React or Epoxy)
  • 41. • Think about your use case • Think about platform differences early on • Know your limits Tipsforbuildingouta server-drivenUIsystem
  • 42. • Mobile-forward companies keen on visual consistency • Repetition, and lots of it! • Limited client-side engineers • You want to launch on all platforms at the same time • Teams that communicate well Whoshould Whoshouldn’t
  • 43. Whoshould • No native app • Product looks different across platforms and devices • Unique screens, minimal visual overlap Whoshouldn’t • Mobile-forward companies keen on visual consistency • Repetition, and lots of it! • Limited client-side engineers • You want to launch on all platforms at the same time • Teams that communicate well
  • 44.