SlideShare ist ein Scribd-Unternehmen logo
1 von 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

Weitere ähnliche Inhalte

Was ist angesagt?

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
 

Was ist angesagt? (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
 

Ähnlich wie 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
 

Ähnlich wie 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
 

Kürzlich hochgeladen

Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escortsranjana rawat
 
UNIT-V FMM.HYDRAULIC TURBINE - Construction and working
UNIT-V FMM.HYDRAULIC TURBINE - Construction and workingUNIT-V FMM.HYDRAULIC TURBINE - Construction and working
UNIT-V FMM.HYDRAULIC TURBINE - Construction and workingrknatarajan
 
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...Soham Mondal
 
UNIT-III FMM. DIMENSIONAL ANALYSIS
UNIT-III FMM.        DIMENSIONAL ANALYSISUNIT-III FMM.        DIMENSIONAL ANALYSIS
UNIT-III FMM. DIMENSIONAL ANALYSISrknatarajan
 
Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxAsutosh Ranjan
 
Extrusion Processes and Their Limitations
Extrusion Processes and Their LimitationsExtrusion Processes and Their Limitations
Extrusion Processes and Their Limitations120cr0395
 
Porous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingPorous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingrakeshbaidya232001
 
Microscopic Analysis of Ceramic Materials.pptx
Microscopic Analysis of Ceramic Materials.pptxMicroscopic Analysis of Ceramic Materials.pptx
Microscopic Analysis of Ceramic Materials.pptxpurnimasatapathy1234
 
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...RajaP95
 
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICSAPPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICSKurinjimalarL3
 
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130Suhani Kapoor
 
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130Suhani Kapoor
 
KubeKraft presentation @CloudNativeHooghly
KubeKraft presentation @CloudNativeHooghlyKubeKraft presentation @CloudNativeHooghly
KubeKraft presentation @CloudNativeHooghlysanyuktamishra911
 
SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )Tsuyoshi Horigome
 
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...Christo Ananth
 
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...ranjana rawat
 
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 

Kürzlich hochgeladen (20)

Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
 
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
(MEERA) Dapodi Call Girls Just Call 7001035870 [ Cash on Delivery ] Pune Escorts
 
UNIT-V FMM.HYDRAULIC TURBINE - Construction and working
UNIT-V FMM.HYDRAULIC TURBINE - Construction and workingUNIT-V FMM.HYDRAULIC TURBINE - Construction and working
UNIT-V FMM.HYDRAULIC TURBINE - Construction and working
 
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
OSVC_Meta-Data based Simulation Automation to overcome Verification Challenge...
 
UNIT-III FMM. DIMENSIONAL ANALYSIS
UNIT-III FMM.        DIMENSIONAL ANALYSISUNIT-III FMM.        DIMENSIONAL ANALYSIS
UNIT-III FMM. DIMENSIONAL ANALYSIS
 
Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptx
 
Extrusion Processes and Their Limitations
Extrusion Processes and Their LimitationsExtrusion Processes and Their Limitations
Extrusion Processes and Their Limitations
 
Porous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingPorous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writing
 
Microscopic Analysis of Ceramic Materials.pptx
Microscopic Analysis of Ceramic Materials.pptxMicroscopic Analysis of Ceramic Materials.pptx
Microscopic Analysis of Ceramic Materials.pptx
 
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
IMPLICATIONS OF THE ABOVE HOLISTIC UNDERSTANDING OF HARMONY ON PROFESSIONAL E...
 
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICSAPPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
APPLICATIONS-AC/DC DRIVES-OPERATING CHARACTERISTICS
 
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
VIP Call Girls Service Kondapur Hyderabad Call +91-8250192130
 
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
VIP Call Girls Service Hitech City Hyderabad Call +91-8250192130
 
★ CALL US 9953330565 ( HOT Young Call Girls In Badarpur delhi NCR
★ CALL US 9953330565 ( HOT Young Call Girls In Badarpur delhi NCR★ CALL US 9953330565 ( HOT Young Call Girls In Badarpur delhi NCR
★ CALL US 9953330565 ( HOT Young Call Girls In Badarpur delhi NCR
 
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINEDJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
DJARUM4D - SLOT GACOR ONLINE | SLOT DEMO ONLINE
 
KubeKraft presentation @CloudNativeHooghly
KubeKraft presentation @CloudNativeHooghlyKubeKraft presentation @CloudNativeHooghly
KubeKraft presentation @CloudNativeHooghly
 
SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )SPICE PARK APR2024 ( 6,793 SPICE Models )
SPICE PARK APR2024 ( 6,793 SPICE Models )
 
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
Call for Papers - Educational Administration: Theory and Practice, E-ISSN: 21...
 
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
 
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
 

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.