Building Products
A brief overview on modern web apps, tech stacks,
languages, frameworks, services, APIs and more.
Hayden Bleasel
Product Designer, Full-Stack
Developer, Entrepreneur.
Currently working on Presumi,
previously working at Palantir,
Sumry and Zookal.
@haydenbleasel on the
internet.
Nice to meet you.
Quick Question
What do you think a “Product” refers to?
Overview
1. Products
2. Web vs Mobile
3. Languages
4. Frameworks
5. Content Management Systems
6. Architecture
7. Services
8. Case Studies
Let’s just get started
I can’t stall much longer. Time to get into it.
1. Products
• Working on a website that you personally own and
focuses more on your needs? Project
• Working on a website that you or a few others own
and focuses on user needs? Product
• Working on a website that is owned by an entity
(company) and focuses users, investors and
growth? Startup
What is a Product?
• Tech startups and larger companies usually focus
on a single entity as their business operations.
• Slack, Facebook, Twitter, Spotify - all companies
focus on a single piece of ecosystem / platform
(usually released on multiple devices)
• This ecosystem is called a Product.
Tech Products
• There’s a whole new range of jobs coming out that
focus on this, namely Product Design (my job title)
• A new spin on Industrial Product Design, this sort
of Product Design focuses on the end-to-end
creation of an entity.
• Facebook, for example, is a massive product.
Visualising, understanding and designing for the
entire ecosystem at once is usually my work.
Distribution methods
• Products can come in many forms, but they’re all
part of the same ecosystem.
• Facebook released a website, an iOS app, an
Android app and a Windows Phone app (plus more)
• Which of these are the most important? Where do
you start? This entirely depends on the context.
2. Web vs Mobile
• What works best for your idea?
• What skills does your team have?
• What is your platform preference?
• Do you have the resources to do both?
• There are some ways around this…
Mobile Apps
• Efficient geolocation
• Touch and gestures
• Push notifications.
• Portability
• Fingerprint recognition
• Focus isolation
Web Apps
• Multitasking
• Screen size
• Information density
• Work environment
How do I choose?
• Are you making Uber? Mobile apps.
• Are you making Atlassian? Desktop apps.
• Are you making Facebook? Probably both.
Which do I choose?
• You’ve got a few options:
1. Create a responsive website (no native apps)
2. Hire a developer per-platform (web, iOS,
Android)
3. Wrap your website in an app frame (Cordova,
UIWebView)
4. Bind web code to native handlers (React Native)
3. Languages
• Picking a language is one of the hardest parts. Everyone
wants to jump on the new hotness.
• Go with what your team knows best. It’s better to build a
MVP in PHP that actually works, as opposed to a MVP in
Node.js that runs like shit. You can always rebuild later on.
• Some languages are reserved for back-end development,
some for front-end development. The languages you use
depend on your platform. What are your options?
• And why are there so many coming out recently?
Hipster code
iOS App
• Objective-C (Old School)
• Swift (New Hotness)
• Sometimes C++ if necessary
Android App
• XML
• Java
• Sometimes C and C++
Web App
• Back-end: PHP, Ruby, Python,
Java, JavaScript (anything can
be used to write a website
back-end basically)
• Front-end: HTML, CSS,
JavaScript (but you can
preprocess these with a bunch
of other languages)
Web App
• Back-end: PHP, Ruby, Python,
Java, JavaScript (anything can
be used to write a website
back-end basically)
• Front-end: HTML, CSS,
JavaScript (but you can
preprocess these with a bunch
of other languages)
What? I thought you said languages are separated?!
JavaScript hotness
• There’s a reason JS is the new hotness.
• TL;DR: JS was originally a web browser scripting language written
in 10 days by a guy at Netscape. Google made their own JS engine
some time later to run Chrome, called the JavaScript V8 engine.
• Some yung money™ a few years ago decided it’d be a great idea
to pull that engine out of Chrome and make it into a server side
compiler called Node.js. Same language on the server and client?
Ridiculous.
• Node.js now runs GoDaddy, Groupon, IBM, LinkedIn, Microsoft,
Netflix, PayPal, Walmart, Yahoo! and Cisco Systems.
But then…
Side note on machines
• I’m not going to argue for Mac or Windows - that
arguments been going on far too long. And also because
Mac is naturally superior.
• There’s plenty of reasons (unix-based commercial
software, build quality, cross-platform compatibility, etc.)
• I actually made the switch because of development.
Running any programming environment (Node, Rails,
PHP, etc) is super easy on Mac and super painful on
Windows because Mac is based on Unix.
4. Frameworks
• Frameworks make creating web apps easier. Native apps
don’t need them most of the time (you can make smaller
framework-module-things yourself though)
• The framework depends on the language you pick and
what you want to accomplish.
• Every language usually has a few popular frameworks
that “everyone” uses.
• You can create your own framework of course (really not
recommended) or just not use one at all.
Picking a framework
• PHP: Laravel, CodeIgniter, CakePHP, Symfony, Zend
• Ruby: Rails, Sinatra, Cuba, Volt, Lotus
• Python: Django, Flask, Pyramid, Turbogears
• Node.js: Express, Meteor, Socket, MEAN, Koa
• JavaScript: React, Angular, Ember, Meteor, jQuery,
Backbone, Knockout, Cappuccino, Chaplin, Echo, Enyo, Ext
JS, Google Web Toolkit, JavaScriptMVC, Mojito, MooTools,
Prototype, Rialto Toolkit, SproutCore, Wakanda Framework…
Why a framework?
function router (request, response) {
if(request.url === ‘/index.html’ || request.url === ‘/‘) {
response.writeHead(200, {
'Content-Type': 'text/plain'
});
response.write('Hello World!')
response.end();
}
var http = require(“http”);
var server = http.createServer(router);
server.listen(3000);
Why a framework?
var app = require(‘express’)();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000);
Plus…
• Better wrappers to the request and response
• Support for view-engines
• Routing mechanism
• Cookies manipulation
• Basic authentication
• Much much more…
5. Content Management Systems
• Sometimes you don’t need to build a product from
ground up.
• If you want to make a store, a blog or a simple website,
you could use a CMS
• A CMS helps you manage your content on your website
and usually the website itself
• Usually really easy to install (click to install) and don’t
require much (or any) code to operate. A lot like off-the-
shelf software for websites.
Popular CMS’
• E-Commerce: Squarespace, Shopify, Magento,
WooCommerce
• Blogging: Squarespace, Wordpress, Ghost
• Marketing Site: Squarespace, Wix, Weebly
• Pieces of junk: Drupal, Joomla
FindMyPlan
• The value proposition for FindMyPlan is getting a
Sim Card to you from any country in the world to
avoid expensive roaming bills when you travel.
• There isn’t a huge tech focus - they need a system
that works for them and allows them to create
value and manage clients easily.
• They’ve moved to from a custom Angular/PHP
web-app to a Shopify site. Why?
Do what works for you
• Don’t pick a damn language because it’s hot. Pick it because you love it
and know it (or at least want to know it eventually).
• Too many startups get told what technology to use and end up
regretting it, some are next door. Don’t be pressured into building a
product a certain way, or even building a product at all.
• A tech startup should be using technology to enable the startup to
reach it’s goals, not building a custom product with super hot code for
their own satisfaction.
• Your tech doesn’t matter to the customer. What matters is how easy it
is to reach their goal.
• JavaScript is the best tho.
6. Architecture
• Picking a language, framework and/or CMS is
great but we need to talk about how these things
work.
• Back in the day it used to be super clear, but
modern technology is enabling crazy things that
don’t seem normal to traditional developers but
they work in amazing ways.
TL;DR: How apps work
Request a page Fetch things for page
Return thingsSend webpage to browser
Figure out what’s needed
Render HTML, CSS, JS,
return all the requests
HTTP Requests API requests to DB
Find things for pageReload page
Over time…
Why client-side JS is hot
Request first page Fetch things for page
Return thingsSend webpage to browser
Just grab everything
Render every page
scaffold and controllers
and return
HTTP Requests API requests to DB
Find things for pageReload page
Over time…
Sometimes you can even…
This means what exactly
• Firstly, the server’s getting a lot less hits. This means
server usage could drop dramatically causing less crashes.
• Secondly, the server isn’t doing any processing for clients.
This means everything is done on the client’s computer,
again causing less server usage.
• Third, EVERYTHING IS SO FAST BECAUSE WE DON’T
NEED TO RELOAD EVERY PAGE.
• It also means all our code is on the client’s computer to
potentially steal but I dunno, c’est la vie I suppose.
One more thing…
One more thing…
7. Services
• Services and APIs are the most useful thing when
you’re building a product.
• Basically, you don’t have to do all the work yourself.
• Products typically have a lot of things in common.
Live chat, payment gateway, error reporting.
• Smart companies identify these needs, build an
entire product out of the one focus, turn them into
drop-in widgets or APIs and monetise on them.
Examples
• Customer Support: Intercom, UserVoice, Drift
• Error Reporting: Rollbar, Sentry, Bugsnag, Airbrake
• Payment Gateway: Paypal, Stripe, Braintree
• Transactional Email: Mandrill, SendGrid, Mailgun
• Analytics: Google Analytics, Mixpanel, Kissmetrics
• A/B Testing: Optimizely, VWO, Performable
Why invest in services
• There’s a reason these services are so successful
and you should look into using them.
• They take a pain point of building products and do
it really, really well.
• You can chuck out the trash code you wrote to
handle user’s error reports and replace it with a
Rollbar installation for free!
“I’ll just write it myself”
<script>
var YOUR_API_KEY = “XXXXXXXX”;
!function(){var t;return t=window.driftt=window.drift=window.driftt||
[],t.init?void 0:t.invoked?
void(window.console&&console.error&&console.error("Drift snippet
included twice.")):(t.invoked=!
0,t.methods=["identify","track","reset","debug","show","ping","page","hi
de","off","on"],t.factory=function(e){return function(){var n;return
n=Array.prototype.slice.call(arguments),n.unshift(e),t.push(n),t}},t.met
hods.forEach(function(e){t[e]=t.factory(e)}),t.load=function(t){var
e,n,o,r;e=3e5,r=Math.ceil(new Date/
e)*e,o=document.createElement(“script”),o.type=“text/
javascript”,o.async=!0,o.crossorigin="anonymous",o.src="https://
js.driftt.com/
include/"+r+"/"+t+".js",n=document.getElementsByTagName("script")
[0],n.parentNode.insertBefore(o,n)})}
(),drift.SNIPPET_VERSION="0.2.0",drift.load(YOUR_API_KEY);
</script>
!function(t){function e(c){if(n[c])return n[c].exports;var o=n[c]={i:c,l:!1,exports:{}};return t[c].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};return e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,e,n){Object.defineProperty(t,e,{configurable:!
1,enumerable:!0,get:n})},e.n=function(t){var n=t&&t.__esModule?function(){return t["default"]}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="https://js.driftt.com/dist/",e(e.s=316)}
([function(t,e,n){"use strict";var c=Array.isArray;e["default"]=c},function(t,e,n){"use strict";function c(t){var e="undefined"==typeof t?"undefined":r()(t);return!!t&&("object"==e||"function"==e)}var o=n(2),r=n.n(o);e.a=c},function(t,e,n){"use strict";function
c(t){return t&&t.__esModule?t:{"default":t}}e.__esModule=!0;var o=n(238),r=c(o),i=n(237),a=c(i),M="function"==typeof a["default"]&&"symbol"==typeof r["default"]?function(t){return typeof t}:function(t){return t&&"function"==typeof
a["default"]&&t.constructor===a["default"]?"symbol":typeof t};e["default"]="function"==typeof a["default"]&&"symbol"===M(r["default"])?function(t){return"undefined"==typeof t?"undefined":M(t)}:function(t){return t&&"function"==typeof
a["default"]&&t.constructor===a["default"]?"symbol":"undefined"==typeof t?"undefined":M(t)}},function(t,e,n){"use strict";var c=n(2),o=n.n(c),r=n(86),i="object"==("undefined"==typeof self?"undefined":o()(self))&&self&&self.Object===Object&&self,a=r.a||i||
Function("return this")();e.a=a},function(t,e){var n=t.exports={version:"2.4.0"};"number"==typeof __e&&(__e=n)},function(t,e){var n=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return
this")();"number"==typeof __g&&(__g=n)},function(t,e,n){"use strict";function c(t){return n.i(i.a)(t)?n.i(o.a)(t):n.i(r.a)(t)}var o=n(76),r=n(146),i=n(11);e.a=c},function(t,e,n){var c,o,r;o=n(304),r=function(t,e){if(null==e&&(e={}),o.isSetup()&&!window.Raven&&!
window.RavenConfig)return o.captureException(t,e)},c={info:function(){var t;if(window.__DRIFTT_DEBUG__)return t=Array.prototype.slice.call(arguments),t.unshift("Drift - "),console.info.apply(console,t)},log:function(){var t;if(window.__DRIFTT_DEBUG__)return
t=Array.prototype.slice.call(arguments),t.unshift("Drift - "),console.log.apply(console,t)},warn:function(){var t;if(window.__DRIFTT_DEBUG__)return t=Array.prototype.slice.call(arguments),t.unshift("Drift - "),console.warn.apply(console,t)},error:function(t,e)
{return null==e&&(e={}),r(t,e),console.error("Drift - ",t)}},t.exports=c},function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},function(t,e,n){var c=n(104),o=n(61);t.exports=function(t){return c(o(t))}},function(t,e,n){"use
strict";function c(t,e){var c=n.i(r.a)(t,e);return n.i(o.a)(c)?c:void 0}var o=n(143),r=n(171);e.a=c},function(t,e,n){"use strict";function c(t){return null!=t&&n.i(r.a)(t.length)&&!n.i(o.a)(t)}var o=n(55),r=n(56);e.a=c},function(t,e,n){t.exports=!n(13)(function()
{return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},function(t,e,n){var c=n(15),o=n(39);t.exports=n(12)?function(t,e,n){return c.f(t,e,o(1,n))}:function(t,e,n){return
t[e]=n,t}},function(t,e,n){var c=n(36),o=n(103),r=n(71),i=Object.defineProperty;e.f=n(12)?Object.defineProperty:function(t,e,n){if(c(t),e=r(e,!0),c(n),o)try{return i(t,e,n)}catch(a){}if("get"in n||"set"in n)throw TypeError("Accessors not
supported!");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){var c=n(108),o=n(62);t.exports=Object.keys||function(t){return c(t,o)}},function(t,e,n){var c=n(69)("wks"),o=n(41),r=n(5).Symbol,i="function"==typeof r,a=t.exports=function(t){return c[t]||
(c[t]=i&&r[t]||(i?r:o)("Symbol."+t))};a.store=c},function(t,e,n){"use strict";function c(t,e){return t===e||t!==t&&e!==e}e.a=c},function(t,e,n){"use strict";function c(t){return!!t&&"object"==("undefined"==typeof t?"undefined":r()(t))}var
o=n(2),r=n.n(o);e.a=c},function(t,e,n){var c=n(5),o=n(4),r=n(257),i=n(14),a="prototype",M=function(t,e,n){var s,u,p,l=t&M.F,f=t&M.G,d=t&M.S,b=t&M.P,A=t&M.B,z=t&M.W,h=f?o:o[e]||(o[e]={}),O=h[a],T=f?c:d?c[e]:(c[e]||{})[a];f&&(n=e);for(s in n)u=!l&&T&&void 0!
==T[s],u&&s in h||(p=u?T[s]:n[s],h[s]=f&&"function"!=typeof T[s]?n[s]:A&&u?r(p,c):z&&T[s]==p?function(t){var e=function(e,n,c){if(this instanceof t){switch(arguments.length){case 0:return new t;case 1:return new t(e);case 2:return new t(e,n)}return new t(e,n,c)}
return t.apply(this,arguments)};return e[a]=t[a],e}(p):b&&"function"==typeof p?r(Function.call,p):p,b&&((h.virtual||(h.virtual={}))[s]=p,t&M.R&&O&&!O[s]&&i(O,s,p)))};M.F=1,M.G=2,M.S=4,M.P=8,M.B=16,M.W=32,M.U=64,M.R=128,t.exports=M},function(t,e,n){"use
strict";function c(t){var e=-1,n=t?t.length:0;for(this.clear();++e<n;){var c=t[e];this.set(c[0],c[1])}}var
o=n(184),r=n(185),i=n(186),a=n(187),M=n(188);c.prototype.clear=o.a,c.prototype["delete"]=r.a,c.prototype.get=i.a,c.prototype.has=a.a,c.prototype.set=M.a,e.a=c},function(t,e,n){"use strict";function c(t){this.__data__=new o.a(t)}var
o=n(21),r=n(199),i=n(200),a=n(201),M=n(202),s=n(203);c.prototype.clear=r.a,c.prototype["delete"]=i.a,c.prototype.get=a.a,c.prototype.has=M.a,c.prototype.set=s.a,e.a=c},function(t,e,n){"use strict";function c(t,e){for(var c=t.length;c--;)if(n.i(o.a)(t[c]
[0],e))return c;return-1}var o=n(18);e.a=c},function(t,e,n){"use strict";function c(t,e,c,r){c||(c={});for(var i=-1,a=e.length;++i<a;){var M=e[i],s=r?r(c[M],t[M],M,c,t):void 0;n.i(o.a)(c,M,void 0===s?t[M]:s)}return c}var o=n(48);e.a=c},function(t,e,n){"use
strict";function c(t,e){var c=t.__data__;return n.i(o.a)(e)?c["string"==typeof e?"string":"hash"]:c.map}var o=n(182);e.a=c},function(t,e,n){"use strict";function c(t){var e=!1;if(null!=t&&"function"!=typeof t.toString)try{e=!!(t+"")}catch(n){}return e}
e.a=c},function(t,e,n){"use strict";function c(t,e){if(n.i(i["default"])(t))return!1;var c="undefined"==typeof t?"undefined":r()(t);return!("number"!=c&&"symbol"!=c&&"boolean"!=c&&null!=t&&!n.i(a.a)(t))||(s.test(t)||!M.test(t)||null!=e&&t in Object(e))}var
o=n(2),r=n.n(o),i=n(0),a=n(31),M=/.|[(?:[^[]]*|(["'])(?:(?!1)[^]|.)*?1)]/,s=/^w*$/;e.a=c},function(t,e,n){"use strict";function c(t){var e=t&&t.constructor,n="function"==typeof e&&e.prototype||o;return t===n}var o=Object.prototype;e.a=c},function(t,e,n)
{"use strict";var c=n(10),o=n.i(c.a)(Object,"create");e.a=o},function(t,e,n){"use strict";function c(t){if("string"==typeof t||n.i(o.a)(t))return t;var e=t+"";return"0"==e&&1/t==-r?"-0":e}var o=n(31),r=1/0;e.a=c},function(t,e,n){"use strict";function c(t)
{return"symbol"==("undefined"==typeof t?"undefined":r()(t))||n.i(i.a)(t)&&s.call(t)==a}var o=n(2),r=n.n(o),i=n(19),a="[object Symbol]",M=Object.prototype,s=M.toString;e.a=c},function(t,e,n){"use strict";var c=n(149),o=n(84),r=n.i(o.a)(function(t,e,o){n.i(c.a)
(t,e,o)});e["default"]=r},function(t,e,n){"use strict";function c(t){return t&&t.__esModule?t:{"default":t}}e.__esModule=!0;var o=n(232),r=c(o);e["default"]=r["default"]||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var c in
n)Object.prototype.hasOwnProperty.call(n,c)&&(t[c]=n[c])}return t}},function(t,e,n){var
c;c=n(287),t.exports=c({INITIALIZE_LAYER:null,INITIALIZE_LAYER_SUCCESS:null,INITIALIZE_LAYER_FAIL:null,INITIALIZE_API:null,DISCONNECT_LAYER:null,RECEIVE_PACKET:null,FETCH_BOOTSTRAP:null,FETCH_BOOTSTRAP_SUCCESS:null,FETCH_BOOTSTRAP_FAIL:null,FETCH_EMBED_CONFIGURATI
ON_PENDING:null,FETCH_EMBED_CONFIGURATION_SUCCESS:null,FETCH_EMBED_CONFIGURATION_FAILURE:null,OVERRIDE_EMBED_CONFIGURATION:null,FETCH_DRIFTT_ORG:null,FETCH_DRIFTT_ORG_SUCCESS:null,FETCH_DRIFTT_ORG_FAIL:null,READY:null,GO_TO_NEW_CONVERSATION:null,GO_TO_LIST:null,GO
_TO_SELECTED_CONVERSATION:null,GO_TO_OFFLINE_FEEDBACK:null,SET_SIDERBAR_VIEW:null,FETCH_DRIFTT_USERS:null,FETCH_DRIFTT_USERS_SUCCESS:null,FETCH_DRIFTT_USERS_FAIL:null,AUTHENTICATE_END_USER:null,AUTHENTICATE_END_USER_SUCCESS:null,AUTHENTICATE_END_USER_FAIL:null,FET
CH_SEGMENT_MEMBERSHIP_PENDING:null,FETCH_SEGMENT_MEMBERSHIP_SUCCESS:null,FETCH_SEGMENT_MEMBERSHIP_FAILURE:null,FETCH_GEOLOCATION_PENDING:null,FETCH_GEOLOCATION_SUCCESS:null,FETCH_GEOLOCATION_FAILURE:null,ENROLL_IN_CAMPAIGN_PENDING:null,ENROLL_IN_CAMPAIGN_SUCCESS:n
ull,ENROLL_IN_CAMPAIGN_FAILURE:null,OPEN_SIDEBAR:null,CLOSE_SIDEBAR:null,CLOSE_SIDEBAR_WITH_TWEEN:null,CHANGE_SIDEBAR_VIEW:null,SHOW_WIDGET:null,HIDE_WIDGET:null,SHOW_WELCOME_MESSAGE:null,HIDE_WELCOME_MESSAGE:null,EXPAND_WIDGET:null,COLLAPSE_WIDGET:null,IFRAME_RES
IZE_DONE:null,IFRAME_RESIZE:null,IFRAME_OVERRIDE_SIZE:null,SHOW_TYPING_INDICATOR_BUTTON_ICON:null,OPEN_ACTIVATION_TAKEOVER:null,CLOSE_ACTIVATION_TAKEOVER:null,LIST:null,CONVERSATION:null,NEW_CONVERSATION:null,SET_IDENTIFIED_CONVERSATION:null,OFFLINE_FEEDBACK:null,
LOADING:null,LAZY_CAMPAIGN_EVALUATION:null,HANDLE_POST_MESSAGE:null,HANDLE_WINDOW_SCROLL:null,HANDLE_WINDOW_MOUSE_OUT:null,HANDLE_WINDOW_MOUSE_OVER:null,REFRESH_TARGETING:null,REFRESH_TIME_ON_PAGE:null,SUBMIT_OFFLINE_FEEDBACK:null,SUBMIT_OFFLINE_FEEDBACK_SUCCESS:n
ull,SUBMIT_OFFLINE_FEEDBACK_FAIL:null,DRIFT_ENQUEUE_MESSAGE:null,DRIFT_CREATE_MESSAGE_PENDING:null,DRIFT_CREATE_MESSAGE_SUCCESS:null,DRIFT_CREATE_MESSAGE_FAILURE:null,DRIFT_CREATE_CONVERSATION_PENDING:null,DRIFT_CREATE_CONVERSATION_SUCCESS:null,DRIFT_CREATE_CONVER
SATION_FAILURE:null,WIDGET_STATS_PENDING:null,WIDGET_STATS_SUCCESS:null,WIDGET_STATS_FAILURE:null})},function(t,e,n){var c;c={CUSTOMER_API_BASE:"https://customer.api.drift.com",CONVERSATION_API_BASE:"https://conversation.api.drift.com",EVENT_API_BASE:"https://
event.api.drift.com",EMBED_API_BASE:"https://js.driftt.com",CLIENT_ID:"f6zuizdyhxrm7r",LAYER_APP_ID:"layer:///apps/production/15806ab6-607f-11e5-817e-98d908000a42"},c.COOKIE_PATH="/",c.LAYER_API_BASE="https://api.layer.com",c.SENTRY_DSN="https://
816fa28dc7cf492ba8ffa277d90f0345@app.getsentry.com/61707",t.exports=c},function(t,e,n){var c=n(37);t.exports=function(t){if(!c(t))throw TypeError(t+" is not an object!");return t}},function(t,e){t.exports=function(t){return"object"==typeof t?null!
==t:"function"==typeof t}},function(t,e){e.f={}.propertyIsEnumerable},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var c=n(61);t.exports=function(t){return
Object(c(t))}},function(t,e){var n=0,c=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++n+c).toString(36))}},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(c)
{"object"==typeof window&&(n=window)}t.exports=n},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,configurable:!1,get:function(){return
t.l}}),Object.defineProperty(t,"id",{enumerable:!0,configurable:!1,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,n){"use strict";var c=n(10),o=n(3),r=n.i(c.a)(o.a,"Map");e.a=r},function(t,e,n){"use strict";function c(t){var e=-1,n=t?t.length:
0;for(this.clear();++e<n;){var c=t[e];this.set(c[0],c[1])}}var o=n(189),r=n(190),i=n(191),a=n(192),M=n(193);c.prototype.clear=o.a,c.prototype["delete"]=r.a,c.prototype.get=i.a,c.prototype.has=a.a,c.prototype.set=M.a,e.a=c},function(t,e,n){"use strict";var
c=n(3),o=c.a.Symbol;e.a=o},function(t,e,n){"use strict";function c(t,e){for(var n=-1,c=t?t.length:0;++n<c&&e(t[n],n,t)!==!1;);return t}e.a=c},function(t,e,n){"use strict";function c(t,e,c){var r=t[e];i.call(t,e)&&n.i(o.a)(r,c)&&(void 0!==c||e in t)||(t[e]=c)}var
o=n(18),r=Object.prototype,i=r.hasOwnProperty;e.a=c},function(t,e,n){"use strict";function c(t,e,a,M,s){return t===e||(null==t||null==e||!n.i(r.a)(t)&&!n.i(i.a)(e)?t!==t&&e!==e:n.i(o.a)(t,e,c,a,M,s))}var o=n(141),r=n(1),i=n(19);e.a=c},function(t,e,n){"use
strict";function c(t){var e=new t.constructor(t.byteLength);return new o.a(e).set(new o.a(t)),e}var o=n(75);e.a=c},function(t,e,n){"use strict";function c(t,e){return e=null==e?o:e,!!e&&("number"==typeof t||r.test(t))&&t>-1&&t%1==0&&t<e}var o=9007199254740991,r=/
^(?:0|[1-9]d*)$/;e.a=c},function(t,e,n){"use strict";function c(t,e){return function(n){return t(e(n))}}e.a=c},function(t,e,n){"use strict";function c(t,e){var c=n.i(a["default"])(t)?o.a:r.a;return c(t,n.i(i.a)(e,3))}var
o=n(47),r=n(135),i=n(145),a=n(0);e["default"]=c},function(t,e,n){"use strict";function c(t){return n.i(o.a)(t)&&a.call(t,"callee")&&(!s.call(t,"callee")||M.call(t)==r)}var o=n(95),r="[object
Arguments]",i=Object.prototype,a=i.hasOwnProperty,M=i.toString,s=i.propertyIsEnumerable;e.a=c},function(t,e,n){"use strict";function c(t){var e=n.i(o.a)(t)?M.call(t):"";return e==r||e==i}var o=n(1),r="[object Function]",i="[object
GeneratorFunction]",a=Object.prototype,M=a.toString;e.a=c},function(t,e,n){"use strict";function c(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=o}var o=9007199254740991;e.a=c},function(t,e,n){"use strict";var
c=n(144),o=n(155),r=n(196),i=r.a&&r.a.isTypedArray,a=i?n.i(o.a)(i):c.a;e.a=a},function(t,e,n){var c,o,r,i,a,M,s;s=n(53)["default"],M=n(205)["default"],r=n(35).COOKIE_PATH,a=n(7),c=void
0,i="",o={ORG_ID_COOKIE_NAME:"DFTT_ORG_ID"+i,INBOX_ID_COOKIE_NAME:"DFTT_INBOX_ID"+i,END_USER_ID_COOKIE_NAME:"DFTT_END_USER_ID"+i,END_USER_EMAIL_COOKIE_NAME:"DFTT_END_USER_EMAIL"+i,END_USER_AUTH_TOKEN_COOKIE_NAME:"DFTT_END_USER_AUTH_TOKEN"+i,END_USER_PREV_BOOTSTRAP
PED_COOKIE_NAME:"DFTT_END_USER_PREV_BOOTSTRAPPED"+i,LAYER_SESSION_TOKEN_COOKIE_NAME:"DFTT_REALTIME_SESSION_TOKEN"+i,END_USER_EXTERNAL_ID_COOKIE_NAME:"driftt_eid",ANONYMOUS_ID_COOKIE_NAME:"driftt_aid",LEAD_HAS_PREV_IDENTIFIED_COOKIE_NAME:"DFTT_LEAD_HAS_PREV_IDENTIF
IED"+i,LEAD_EMAIL_COOKIE_NAME:"DFTT_LEAD_EMAIL"+i,WELCOME_MESSAGE_DISMISSED_COOKIE_NAME:"driftt_wmd"+i},t.exports=M({},o,{cookiePath:r,getIsConfigured:function(){return null!=c},cookie:function(){if(!this.getIsConfigured())throw new Error("You need to make sure
that the cookie library is configured");return c},setCookiePath:function(t){return this.cookiePath=t},getCookie:function(t){return this.cookie().get(t)},clearAllCookies:function(){s(o,function(t){return function(e){return t.cookie().remove(e,{path:t.cookiePath})}}
(this))},setCookie:function(t,e,n){return null==e?void a.warn("Tried to write an undefined value to cookie: "+t):(n=n||{},null==n.path&&(n.path=this.cookiePath),this.cookie().set(t,e,n))},clearCookie:function(t,e){return e=e||
{},null==e.path&&(e.path=this.cookiePath),this.cookie().remove(t,e)},setCookieLib:function(t){return c=t},getLeadHasPreviouslyIdentified:function(){var t,e,n,c;if(n=!1,c=this.getCookie(o.LEAD_HAS_PREV_IDENTIFIED_COOKIE_NAME))try{n=JSON.parse(c)}catch(e)
{t=e,this.setCookie(o.LEAD_HAS_PREV_IDENTIFIED_COOKIE_NAME,!1)}return n},getUserHasPreviouslyBootstrapped:function(){var t,e,n,c;if(n=!1,c=this.getCookie(o.END_USER_PREV_BOOTSTRAPPED_COOKIE_NAME))try{n=JSON.parse(c)}catch(e)
{t=e,this.setCookie(o.END_USER_PREV_BOOTSTRAPPED_COOKIE_NAME,!1)}return n}})},function(t,e,n){var c,o,r,i,a,M,s=[].slice;r=n(53)["default"],i=n(0)["default"],a=n(32)["default"],c=n(7),t.exports.combineHeaders=function(t){return a.apply(null,
[{}].concat(s.call(t)))},t.exports.getJSONContentTypeHeader=function(){return{"Content-Type":"application/json"}},t.exports.getFormContentTypeHeader=function(){return{"Content-Type":"application/x-www-form-urlencoded"}},t.exports.getLayerHeader=function()
{return{Accept:"application/vnd.layer+json; version=1.0"}},t.exports.encodeQueryData=function(t){var e,n,c;n=[];for(e in t)c=t[e],i(c)?r(c,function(t){return n.push(encodeURIComponent(e)+"="+encodeURIComponent(t))}):null!=c&&n.push(encodeURIComponent(e)
+"="+encodeURIComponent(c));return n.join("&")},o=function(t){var e,n;if(200<=(n=t.status)&&n<300)return t;throw e=new Error(t.statusText),e.response=t,e},M=function(t){switch(t.status){case 101:case 204:case 205:case 304:return;default:return
t.json()}},t.exports.createFetch=function(t,e){return fetch(t,e).then(o).then(M)["catch"](function(n){throw c.error(n,{request:{url:t,options:e},response:n.response}),n})},t.exports.throwIfFailed=function(t){if("TypeError"===(null!=t?t.name:void 0))throw new
TypeError(t.statusText)}},function(t,e,n){var c,o,r,i,a,M,s,u,p,l,f,d,b,A,z,h,O,T,L,N,m,q,v,W,g,_,S,E;L=n(113),m=n(294),v=n(74),o=n(7),N=n(292),T=n(97).mergeWithInitialState,r=n(215)["default"],c="Drift.Targeting",l=function(){var t;return
g(),W(document.referrer||"",p(location.hostname)),t=z(),T({visits:O(),referrer:t,ad:f(),device:d(),page:A(t.previousPage),scroll:h(),os:b(),timezone:N.tz.guess(),locale:(navigator.language||navigator.browserLanguage).split("-")
[0],userAgent:navigator.userAgent,query:q(document.location.href||"")})},O=function(){return{first:M("firstVisit")||0,last:M("lastVisit")||0,count:M("numberOfVisits")||0,sessionCount:M("numberOfSessions")||0}},g=function(){var t,e;if(e=Math.round((new
Date).getTime()/1e3),M("firstVisit")||_("firstVisit",e),t=M("lastVisit"),_("lastVisit",e),_("numberOfVisits",(M("numberOfVisits")||0)+1),null==t||L().diff(1e3*t,"hours")>1)return _("numberOfSessions",(M("numberOfSessions")||0)+1)},f=function(){var t;return
t=q(document.location.href),s(t)},s=function(t){return{source:t.utm_source,name:t.utm_campaign,medium:t.utm_medium,content:t.utm_content,term:t.utm_term}},z=function()
{return{original:M("originalReferrer"),previous:M("previousPage"),current:M("currentReferrer"),currentDomain:M("currentReferrerDomain"),currentSearch:M("referrerSearchTerm")}},W=function(t,e){var n,c,o;return n=t.replace(/.*?:///,"").replace(/www./
i,"").toLowerCase().substr(0,150),c=n.replace(/(.*?)/.*/,"$1"),o=q(t),t?(-1===c.indexOf(e)&&(M("originalReferrer")||_("originalReferrer",n),_("currentReferrer",n),_("currentReferrerDomain",c),_("searchTerm",o.query||o.q||o.search)),_("previousPage",n)):
(_("currentReferrer",""),_("referrerDomain",""),_("previousPage",""))},d=function(){return u(navigator.userAgent)},u=function(t){return t.match(/ipad/i)?"tablet":t.match(/(mobi|phone|ipod|blackberry|docomo)/i)?"mobile":t.match(/(ipad|kindle|android)/
i)?"tablet":"desktop"},A=function(t)
{return{path:a(document.location.pathname||""),hostname:document.location.hostname||"",url:a(document.location.href||""),title:document.title||"",search:document.location.search||"",referrer:t,href:document.location.href||""}},b=function(){return v?
{architecture:v.os.architecture,family:v.os.family,version:v.os.version,name:v.os.toString()}:{name:void 0,version:void 0,architecture:void 0,family:void 0}},h=function(){var t,e,n,c;try{return
c=window.innerHeight,t=document.body.scrollHeight,n=document.body.scrollTop,e=(n+c)/t,{windowHeight:c,scrollHeight:t,scrollTop:n,scrollPct:e}}catch(r){return o.warn("Unable to scroll values from window")}},M=function(t){if("undefined"==typeof document||
null===document||"undefined"==typeof localStorage||null===localStorage)return void o.log("Unable to get from localStorage "+t);try{return JSON.parse(localStorage.getItem(c+"."+t))}catch(e){return o.log("Error getting/parsing targeting -> "+t)}},_=function(t,e)
{if("undefined"==typeof document||null===document||"undefined"==typeof localStorage||null===localStorage)return void o.log("Unable to set from localStorage "+t+" -> "+e);if(null!=e)try{localStorage.setItem(c+"."+t,JSON.stringify(e))}catch(n){o.log("Error storing
targeting "+t+" -> "+e)}return e},i=function(){var t,e,n,i,a,M,s,u;if("undefined"==typeof document||null===document||"undefined"==typeof localStorage||null===localStorage)return void o.log("Unable to clear localStorage");for(a=[],t=e=0,s=localStorage.length;0<=s?
e<s:e>s;t=0<=s?++e:--e)a.push(localStorage.key(t));for(u=[],n=0,M=a.length;n<M;n++)i=a[n],r(i,c)?u.push(localStorage.removeItem(i)):u.push(void 0);return u},q=function(t){var e,n,c,o,r,i,a,M,s;if(r={},!t)return r;if(t+="",i=-1===t.indexOf("?")?t:t.split("?")[1],!
i)return r;for(a=i.split("&"),e=0,n=a.length;e<n;e++)o=a[e],M=o.split("="),c=decodeURIComponent(M[0]).toLowerCase(),s=decodeURIComponent(M[1]),r[c]=s;return r},p=function(t){var
e,n,c,o,r,i;for(e="dc=tld",c=t.split("."),o=r=c.length-1;r>=0;o=r+=-1)if(i=c[o],n=c.slice(o).join("."),document.cookie=e+";domain=."+n+";",document.cookie.indexOf(e)>-1)return document.cookie=e.split("=")[0]+"=;domain=."+n+";expires=Thu, 01 Jan 1970 00:00:01
GMT;",n;return t},a=function(t){var e,n;try{t=m(t)}catch(n){e=n,o.warn("Could not parse URL '"+t+"'"),t=""}return t.replace(/https?:///,"").replace(/^www./,"")},S=function(t){return parseInt(t)},E=function(t){return parseInt(t)/
100},t.exports={normalizeUrl:a,toInt:S,toPct:E,load:l,clear:i,parseQuery:q}},function(t,e){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},function(t,e)
{t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,e){t.exports={}},function(t,e){t.exports=!0},function(t,e,n){var c=n(36),o=n(266),r=n(62),i=n(68)("IE_PROTO"),a=function()
{},M="prototype",s=function(){var t,e=n(102)("iframe"),c=r.length,o="<",i=">";for(e.style.display="none",n(259).appendChild(e),e.src="javascript:",t=e.contentWindow.document,t.open(),t.write(o+"script"+i+"document.F=Object"+o+"/
script"+i),t.close(),s=t.F;c--;)delete s[M][r[c]];return s()};t.exports=Object.create||function(t,e){var n;return null!==t?(a[M]=c(t),n=new a,a[M]=null,n[i]=t):n=s(),void 0===e?n:o(n,e)}},function(t,e){e.f=Object.getOwnPropertySymbols},function(t,e,n){var
c=n(15).f,o=n(8),r=n(17)("toStringTag");t.exports=function(t,e,n){t&&!o(t=n?t:t.prototype,r)&&c(t,r,{configurable:!0,value:e})}},function(t,e,n){var c=n(69)("keys"),o=n(41);t.exports=function(t){return c[t]||(c[t]=o(t))}},function(t,e,n){var c=n(5),o="__core-
js_shared__",r=c[o]||(c[o]={});t.exports=function(t){return r[t]||(r[t]={})}},function(t,e){var n=Math.ceil,c=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?c:n)(t)}},function(t,e,n){var c=n(37);t.exports=function(t,e){if(!c(t))return t;var
n,o;if(e&&"function"==typeof(n=t.toString)&&!c(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!c(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!c(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive
value")}},function(t,e,n){var c=n(5),o=n(4),r=n(64),i=n(73),a=n(15).f;t.exports=function(t){var e=o.Symbol||(o.Symbol=r?{}:c.Symbol||{});"_"==t.charAt(0)||t in e||a(e,t,{value:i.f(t)})}},function(t,e,n){e.f=n(17)},function(t,e,n){(function(t,c){var o;(function()
{"use strict";function r(t){return t=String(t),t.charAt(0).toUpperCase()+t.slice(1)}function i(t,e,n){var c={"10.0":"10",6.4:"10 Technical Preview",6.3:"8.1",6.2:"8",6.1:"7 / Server 2008 R2","6.0":"Vista / Server 2008",5.2:"XP 64-bit / Server 2003",5.1:"XP",
5.01:"2000 SP1","5.0":"2000","4.0":"NT","4.90":"ME"};return e&&n&&/^Win/i.test(t)&&!/^Windows Phone /i.test(t)&&(c=c[/[d.]+$/.exec(t)])&&(t="Windows "+c),t=String(t),e&&n&&(t=t.replace(RegExp(e,"i"),n)),t=M(t.replace(/ ce$/i," CE").replace(/bhpw/
i,"web").replace(/bMacintoshb/,"Mac OS").replace(/_PowerPCb/i," OS").replace(/b(OS X) [^ d]+/i,"$1").replace(/bMac (OS X)b/,"$1").replace(//(d)/," $1").replace(/_/g,".").replace(/(?: BePC|[ .]*fc[ d.]+)$/i,"").replace(/bx86.64b/gi,"x86_64").replace(/
8. Case Studies
• Every product is built differently.
• Every product has had complete rebuilds.
• Every product has a storied history.
• Here’s a couple of them…
Facebook
• Back-end originally built with PHP, likely with a basic WAMP setup (Windows,
Apache, MySQL, PHP). Front-end naturally rendered HTML (rendered by
PHP), CSS and JS. No sense of business logic separation (too much effort).
• Now, front-end is still written in PHP-backed HTML but runs through their
weird crazy “HipHop” compiler: PHP -> AST -> C++ -> G++ -> x64. Business
logic exposed through Thrift in PHP, C++ or Java based on service. Also
running Java on custom application servers. Database is MySQL, caching is
done through memcached (300TB at a time) and HBase. Offline processing
done through Hadoop and Hive. Data logging through Scribe, stored in HDFS
through MapReduce. Page acceleration through BigPipe (pipelining logic).
Varnish Cache for HTTP proxying. User storage through Haystack.
• Messenger is another thing entirely with all sorts of insane shit like
infrastructure sharding, dynamic cluster management and cell structures.
Based on Epoll server developed in Erlang and Thrift.
Twitter
• Twitter has always run on Rails but originally based on
regular Ruby. MySQL database, temporarily sharded.
• “Search” replaced Rails with Java server called Blender.
• “Messages” replaced Rails with Starling (Ruby) then
replaced with Scala.
• Database replaces MySQL with Gizzard and FlockDB
• Lots of custom stuff - Snowflake, Rockdove, Firehose.
Presumi
• Back-end in Express and Handlebars (hybrid rendering engine), front-
end originally in Handlebars and jQuery. Database on MongoDB.
• Live chat with Drift, error reporting with Rollbar, analytics with Google
Analytics, payments with Stripe, email with Sendgrid, A/B with
Optimizely.
• Replaced front-end with jQuery with React, Handlebars with JSX.
• Actual build process takes my JSX, transpiles through Babel (+React
plugin) and Webpack and spits out JS. Basically I write super hot
futuristic code and it converts it to pleb browser code.
• Currently replacing internal app hybrid-rendering with full JS rendering
and implementing React properly, reducing server usage by >50%.
That’s all I’ve got
Thanks for listening. I’m here for questions :)

Tech Thursdays: Building Products

  • 1.
    Building Products A briefoverview on modern web apps, tech stacks, languages, frameworks, services, APIs and more.
  • 2.
    Hayden Bleasel Product Designer,Full-Stack Developer, Entrepreneur. Currently working on Presumi, previously working at Palantir, Sumry and Zookal. @haydenbleasel on the internet. Nice to meet you.
  • 3.
    Quick Question What doyou think a “Product” refers to?
  • 4.
    Overview 1. Products 2. Webvs Mobile 3. Languages 4. Frameworks 5. Content Management Systems 6. Architecture 7. Services 8. Case Studies
  • 5.
    Let’s just getstarted I can’t stall much longer. Time to get into it.
  • 6.
    1. Products • Workingon a website that you personally own and focuses more on your needs? Project • Working on a website that you or a few others own and focuses on user needs? Product • Working on a website that is owned by an entity (company) and focuses users, investors and growth? Startup
  • 7.
    What is aProduct? • Tech startups and larger companies usually focus on a single entity as their business operations. • Slack, Facebook, Twitter, Spotify - all companies focus on a single piece of ecosystem / platform (usually released on multiple devices) • This ecosystem is called a Product.
  • 8.
    Tech Products • There’sa whole new range of jobs coming out that focus on this, namely Product Design (my job title) • A new spin on Industrial Product Design, this sort of Product Design focuses on the end-to-end creation of an entity. • Facebook, for example, is a massive product. Visualising, understanding and designing for the entire ecosystem at once is usually my work.
  • 9.
    Distribution methods • Productscan come in many forms, but they’re all part of the same ecosystem. • Facebook released a website, an iOS app, an Android app and a Windows Phone app (plus more) • Which of these are the most important? Where do you start? This entirely depends on the context.
  • 10.
    2. Web vsMobile • What works best for your idea? • What skills does your team have? • What is your platform preference? • Do you have the resources to do both? • There are some ways around this…
  • 11.
    Mobile Apps • Efficientgeolocation • Touch and gestures • Push notifications. • Portability • Fingerprint recognition • Focus isolation
  • 12.
    Web Apps • Multitasking •Screen size • Information density • Work environment
  • 13.
    How do Ichoose? • Are you making Uber? Mobile apps. • Are you making Atlassian? Desktop apps. • Are you making Facebook? Probably both.
  • 14.
    Which do Ichoose? • You’ve got a few options: 1. Create a responsive website (no native apps) 2. Hire a developer per-platform (web, iOS, Android) 3. Wrap your website in an app frame (Cordova, UIWebView) 4. Bind web code to native handlers (React Native)
  • 15.
    3. Languages • Pickinga language is one of the hardest parts. Everyone wants to jump on the new hotness. • Go with what your team knows best. It’s better to build a MVP in PHP that actually works, as opposed to a MVP in Node.js that runs like shit. You can always rebuild later on. • Some languages are reserved for back-end development, some for front-end development. The languages you use depend on your platform. What are your options? • And why are there so many coming out recently?
  • 16.
  • 17.
    iOS App • Objective-C(Old School) • Swift (New Hotness) • Sometimes C++ if necessary
  • 18.
    Android App • XML •Java • Sometimes C and C++
  • 19.
    Web App • Back-end:PHP, Ruby, Python, Java, JavaScript (anything can be used to write a website back-end basically) • Front-end: HTML, CSS, JavaScript (but you can preprocess these with a bunch of other languages)
  • 20.
    Web App • Back-end:PHP, Ruby, Python, Java, JavaScript (anything can be used to write a website back-end basically) • Front-end: HTML, CSS, JavaScript (but you can preprocess these with a bunch of other languages) What? I thought you said languages are separated?!
  • 21.
    JavaScript hotness • There’sa reason JS is the new hotness. • TL;DR: JS was originally a web browser scripting language written in 10 days by a guy at Netscape. Google made their own JS engine some time later to run Chrome, called the JavaScript V8 engine. • Some yung money™ a few years ago decided it’d be a great idea to pull that engine out of Chrome and make it into a server side compiler called Node.js. Same language on the server and client? Ridiculous. • Node.js now runs GoDaddy, Groupon, IBM, LinkedIn, Microsoft, Netflix, PayPal, Walmart, Yahoo! and Cisco Systems.
  • 22.
  • 23.
    Side note onmachines • I’m not going to argue for Mac or Windows - that arguments been going on far too long. And also because Mac is naturally superior. • There’s plenty of reasons (unix-based commercial software, build quality, cross-platform compatibility, etc.) • I actually made the switch because of development. Running any programming environment (Node, Rails, PHP, etc) is super easy on Mac and super painful on Windows because Mac is based on Unix.
  • 24.
    4. Frameworks • Frameworksmake creating web apps easier. Native apps don’t need them most of the time (you can make smaller framework-module-things yourself though) • The framework depends on the language you pick and what you want to accomplish. • Every language usually has a few popular frameworks that “everyone” uses. • You can create your own framework of course (really not recommended) or just not use one at all.
  • 25.
    Picking a framework •PHP: Laravel, CodeIgniter, CakePHP, Symfony, Zend • Ruby: Rails, Sinatra, Cuba, Volt, Lotus • Python: Django, Flask, Pyramid, Turbogears • Node.js: Express, Meteor, Socket, MEAN, Koa • JavaScript: React, Angular, Ember, Meteor, jQuery, Backbone, Knockout, Cappuccino, Chaplin, Echo, Enyo, Ext JS, Google Web Toolkit, JavaScriptMVC, Mojito, MooTools, Prototype, Rialto Toolkit, SproutCore, Wakanda Framework…
  • 26.
    Why a framework? functionrouter (request, response) { if(request.url === ‘/index.html’ || request.url === ‘/‘) { response.writeHead(200, { 'Content-Type': 'text/plain' }); response.write('Hello World!') response.end(); } var http = require(“http”); var server = http.createServer(router); server.listen(3000);
  • 27.
    Why a framework? varapp = require(‘express’)(); app.get('/', function (req, res) { res.send('Hello World!'); }); app.listen(3000);
  • 28.
    Plus… • Better wrappersto the request and response • Support for view-engines • Routing mechanism • Cookies manipulation • Basic authentication • Much much more…
  • 29.
    5. Content ManagementSystems • Sometimes you don’t need to build a product from ground up. • If you want to make a store, a blog or a simple website, you could use a CMS • A CMS helps you manage your content on your website and usually the website itself • Usually really easy to install (click to install) and don’t require much (or any) code to operate. A lot like off-the- shelf software for websites.
  • 30.
    Popular CMS’ • E-Commerce:Squarespace, Shopify, Magento, WooCommerce • Blogging: Squarespace, Wordpress, Ghost • Marketing Site: Squarespace, Wix, Weebly • Pieces of junk: Drupal, Joomla
  • 31.
    FindMyPlan • The valueproposition for FindMyPlan is getting a Sim Card to you from any country in the world to avoid expensive roaming bills when you travel. • There isn’t a huge tech focus - they need a system that works for them and allows them to create value and manage clients easily. • They’ve moved to from a custom Angular/PHP web-app to a Shopify site. Why?
  • 32.
    Do what worksfor you • Don’t pick a damn language because it’s hot. Pick it because you love it and know it (or at least want to know it eventually). • Too many startups get told what technology to use and end up regretting it, some are next door. Don’t be pressured into building a product a certain way, or even building a product at all. • A tech startup should be using technology to enable the startup to reach it’s goals, not building a custom product with super hot code for their own satisfaction. • Your tech doesn’t matter to the customer. What matters is how easy it is to reach their goal. • JavaScript is the best tho.
  • 33.
    6. Architecture • Pickinga language, framework and/or CMS is great but we need to talk about how these things work. • Back in the day it used to be super clear, but modern technology is enabling crazy things that don’t seem normal to traditional developers but they work in amazing ways.
  • 34.
    TL;DR: How appswork Request a page Fetch things for page Return thingsSend webpage to browser Figure out what’s needed Render HTML, CSS, JS, return all the requests HTTP Requests API requests to DB Find things for pageReload page
  • 35.
  • 36.
    Why client-side JSis hot Request first page Fetch things for page Return thingsSend webpage to browser Just grab everything Render every page scaffold and controllers and return HTTP Requests API requests to DB Find things for pageReload page
  • 37.
  • 38.
  • 39.
    This means whatexactly • Firstly, the server’s getting a lot less hits. This means server usage could drop dramatically causing less crashes. • Secondly, the server isn’t doing any processing for clients. This means everything is done on the client’s computer, again causing less server usage. • Third, EVERYTHING IS SO FAST BECAUSE WE DON’T NEED TO RELOAD EVERY PAGE. • It also means all our code is on the client’s computer to potentially steal but I dunno, c’est la vie I suppose.
  • 40.
  • 41.
  • 42.
    7. Services • Servicesand APIs are the most useful thing when you’re building a product. • Basically, you don’t have to do all the work yourself. • Products typically have a lot of things in common. Live chat, payment gateway, error reporting. • Smart companies identify these needs, build an entire product out of the one focus, turn them into drop-in widgets or APIs and monetise on them.
  • 43.
    Examples • Customer Support:Intercom, UserVoice, Drift • Error Reporting: Rollbar, Sentry, Bugsnag, Airbrake • Payment Gateway: Paypal, Stripe, Braintree • Transactional Email: Mandrill, SendGrid, Mailgun • Analytics: Google Analytics, Mixpanel, Kissmetrics • A/B Testing: Optimizely, VWO, Performable
  • 44.
    Why invest inservices • There’s a reason these services are so successful and you should look into using them. • They take a pain point of building products and do it really, really well. • You can chuck out the trash code you wrote to handle user’s error reports and replace it with a Rollbar installation for free!
  • 45.
    “I’ll just writeit myself” <script> var YOUR_API_KEY = “XXXXXXXX”; !function(){var t;return t=window.driftt=window.drift=window.driftt|| [],t.init?void 0:t.invoked? void(window.console&&console.error&&console.error("Drift snippet included twice.")):(t.invoked=! 0,t.methods=["identify","track","reset","debug","show","ping","page","hi de","off","on"],t.factory=function(e){return function(){var n;return n=Array.prototype.slice.call(arguments),n.unshift(e),t.push(n),t}},t.met hods.forEach(function(e){t[e]=t.factory(e)}),t.load=function(t){var e,n,o,r;e=3e5,r=Math.ceil(new Date/ e)*e,o=document.createElement(“script”),o.type=“text/ javascript”,o.async=!0,o.crossorigin="anonymous",o.src="https:// js.driftt.com/ include/"+r+"/"+t+".js",n=document.getElementsByTagName("script") [0],n.parentNode.insertBefore(o,n)})} (),drift.SNIPPET_VERSION="0.2.0",drift.load(YOUR_API_KEY); </script>
  • 46.
    !function(t){function e(c){if(n[c])return n[c].exports;varo=n[c]={i:c,l:!1,exports:{}};return t[c].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};return e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,e,n){Object.defineProperty(t,e,{configurable:! 1,enumerable:!0,get:n})},e.n=function(t){var n=t&&t.__esModule?function(){return t["default"]}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="https://js.driftt.com/dist/",e(e.s=316)} ([function(t,e,n){"use strict";var c=Array.isArray;e["default"]=c},function(t,e,n){"use strict";function c(t){var e="undefined"==typeof t?"undefined":r()(t);return!!t&&("object"==e||"function"==e)}var o=n(2),r=n.n(o);e.a=c},function(t,e,n){"use strict";function c(t){return t&&t.__esModule?t:{"default":t}}e.__esModule=!0;var o=n(238),r=c(o),i=n(237),a=c(i),M="function"==typeof a["default"]&&"symbol"==typeof r["default"]?function(t){return typeof t}:function(t){return t&&"function"==typeof a["default"]&&t.constructor===a["default"]?"symbol":typeof t};e["default"]="function"==typeof a["default"]&&"symbol"===M(r["default"])?function(t){return"undefined"==typeof t?"undefined":M(t)}:function(t){return t&&"function"==typeof a["default"]&&t.constructor===a["default"]?"symbol":"undefined"==typeof t?"undefined":M(t)}},function(t,e,n){"use strict";var c=n(2),o=n.n(c),r=n(86),i="object"==("undefined"==typeof self?"undefined":o()(self))&&self&&self.Object===Object&&self,a=r.a||i|| Function("return this")();e.a=a},function(t,e){var n=t.exports={version:"2.4.0"};"number"==typeof __e&&(__e=n)},function(t,e){var n=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(t,e,n){"use strict";function c(t){return n.i(i.a)(t)?n.i(o.a)(t):n.i(r.a)(t)}var o=n(76),r=n(146),i=n(11);e.a=c},function(t,e,n){var c,o,r;o=n(304),r=function(t,e){if(null==e&&(e={}),o.isSetup()&&!window.Raven&&! window.RavenConfig)return o.captureException(t,e)},c={info:function(){var t;if(window.__DRIFTT_DEBUG__)return t=Array.prototype.slice.call(arguments),t.unshift("Drift - "),console.info.apply(console,t)},log:function(){var t;if(window.__DRIFTT_DEBUG__)return t=Array.prototype.slice.call(arguments),t.unshift("Drift - "),console.log.apply(console,t)},warn:function(){var t;if(window.__DRIFTT_DEBUG__)return t=Array.prototype.slice.call(arguments),t.unshift("Drift - "),console.warn.apply(console,t)},error:function(t,e) {return null==e&&(e={}),r(t,e),console.error("Drift - ",t)}},t.exports=c},function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},function(t,e,n){var c=n(104),o=n(61);t.exports=function(t){return c(o(t))}},function(t,e,n){"use strict";function c(t,e){var c=n.i(r.a)(t,e);return n.i(o.a)(c)?c:void 0}var o=n(143),r=n(171);e.a=c},function(t,e,n){"use strict";function c(t){return null!=t&&n.i(r.a)(t.length)&&!n.i(o.a)(t)}var o=n(55),r=n(56);e.a=c},function(t,e,n){t.exports=!n(13)(function() {return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,e){t.exports=function(t){try{return!!t()}catch(e){return!0}}},function(t,e,n){var c=n(15),o=n(39);t.exports=n(12)?function(t,e,n){return c.f(t,e,o(1,n))}:function(t,e,n){return t[e]=n,t}},function(t,e,n){var c=n(36),o=n(103),r=n(71),i=Object.defineProperty;e.f=n(12)?Object.defineProperty:function(t,e,n){if(c(t),e=r(e,!0),c(n),o)try{return i(t,e,n)}catch(a){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){var c=n(108),o=n(62);t.exports=Object.keys||function(t){return c(t,o)}},function(t,e,n){var c=n(69)("wks"),o=n(41),r=n(5).Symbol,i="function"==typeof r,a=t.exports=function(t){return c[t]|| (c[t]=i&&r[t]||(i?r:o)("Symbol."+t))};a.store=c},function(t,e,n){"use strict";function c(t,e){return t===e||t!==t&&e!==e}e.a=c},function(t,e,n){"use strict";function c(t){return!!t&&"object"==("undefined"==typeof t?"undefined":r()(t))}var o=n(2),r=n.n(o);e.a=c},function(t,e,n){var c=n(5),o=n(4),r=n(257),i=n(14),a="prototype",M=function(t,e,n){var s,u,p,l=t&M.F,f=t&M.G,d=t&M.S,b=t&M.P,A=t&M.B,z=t&M.W,h=f?o:o[e]||(o[e]={}),O=h[a],T=f?c:d?c[e]:(c[e]||{})[a];f&&(n=e);for(s in n)u=!l&&T&&void 0! ==T[s],u&&s in h||(p=u?T[s]:n[s],h[s]=f&&"function"!=typeof T[s]?n[s]:A&&u?r(p,c):z&&T[s]==p?function(t){var e=function(e,n,c){if(this instanceof t){switch(arguments.length){case 0:return new t;case 1:return new t(e);case 2:return new t(e,n)}return new t(e,n,c)} return t.apply(this,arguments)};return e[a]=t[a],e}(p):b&&"function"==typeof p?r(Function.call,p):p,b&&((h.virtual||(h.virtual={}))[s]=p,t&M.R&&O&&!O[s]&&i(O,s,p)))};M.F=1,M.G=2,M.S=4,M.P=8,M.B=16,M.W=32,M.U=64,M.R=128,t.exports=M},function(t,e,n){"use strict";function c(t){var e=-1,n=t?t.length:0;for(this.clear();++e<n;){var c=t[e];this.set(c[0],c[1])}}var o=n(184),r=n(185),i=n(186),a=n(187),M=n(188);c.prototype.clear=o.a,c.prototype["delete"]=r.a,c.prototype.get=i.a,c.prototype.has=a.a,c.prototype.set=M.a,e.a=c},function(t,e,n){"use strict";function c(t){this.__data__=new o.a(t)}var o=n(21),r=n(199),i=n(200),a=n(201),M=n(202),s=n(203);c.prototype.clear=r.a,c.prototype["delete"]=i.a,c.prototype.get=a.a,c.prototype.has=M.a,c.prototype.set=s.a,e.a=c},function(t,e,n){"use strict";function c(t,e){for(var c=t.length;c--;)if(n.i(o.a)(t[c] [0],e))return c;return-1}var o=n(18);e.a=c},function(t,e,n){"use strict";function c(t,e,c,r){c||(c={});for(var i=-1,a=e.length;++i<a;){var M=e[i],s=r?r(c[M],t[M],M,c,t):void 0;n.i(o.a)(c,M,void 0===s?t[M]:s)}return c}var o=n(48);e.a=c},function(t,e,n){"use strict";function c(t,e){var c=t.__data__;return n.i(o.a)(e)?c["string"==typeof e?"string":"hash"]:c.map}var o=n(182);e.a=c},function(t,e,n){"use strict";function c(t){var e=!1;if(null!=t&&"function"!=typeof t.toString)try{e=!!(t+"")}catch(n){}return e} e.a=c},function(t,e,n){"use strict";function c(t,e){if(n.i(i["default"])(t))return!1;var c="undefined"==typeof t?"undefined":r()(t);return!("number"!=c&&"symbol"!=c&&"boolean"!=c&&null!=t&&!n.i(a.a)(t))||(s.test(t)||!M.test(t)||null!=e&&t in Object(e))}var o=n(2),r=n.n(o),i=n(0),a=n(31),M=/.|[(?:[^[]]*|(["'])(?:(?!1)[^]|.)*?1)]/,s=/^w*$/;e.a=c},function(t,e,n){"use strict";function c(t){var e=t&&t.constructor,n="function"==typeof e&&e.prototype||o;return t===n}var o=Object.prototype;e.a=c},function(t,e,n) {"use strict";var c=n(10),o=n.i(c.a)(Object,"create");e.a=o},function(t,e,n){"use strict";function c(t){if("string"==typeof t||n.i(o.a)(t))return t;var e=t+"";return"0"==e&&1/t==-r?"-0":e}var o=n(31),r=1/0;e.a=c},function(t,e,n){"use strict";function c(t) {return"symbol"==("undefined"==typeof t?"undefined":r()(t))||n.i(i.a)(t)&&s.call(t)==a}var o=n(2),r=n.n(o),i=n(19),a="[object Symbol]",M=Object.prototype,s=M.toString;e.a=c},function(t,e,n){"use strict";var c=n(149),o=n(84),r=n.i(o.a)(function(t,e,o){n.i(c.a) (t,e,o)});e["default"]=r},function(t,e,n){"use strict";function c(t){return t&&t.__esModule?t:{"default":t}}e.__esModule=!0;var o=n(232),r=c(o);e["default"]=r["default"]||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var c in n)Object.prototype.hasOwnProperty.call(n,c)&&(t[c]=n[c])}return t}},function(t,e,n){var c;c=n(287),t.exports=c({INITIALIZE_LAYER:null,INITIALIZE_LAYER_SUCCESS:null,INITIALIZE_LAYER_FAIL:null,INITIALIZE_API:null,DISCONNECT_LAYER:null,RECEIVE_PACKET:null,FETCH_BOOTSTRAP:null,FETCH_BOOTSTRAP_SUCCESS:null,FETCH_BOOTSTRAP_FAIL:null,FETCH_EMBED_CONFIGURATI ON_PENDING:null,FETCH_EMBED_CONFIGURATION_SUCCESS:null,FETCH_EMBED_CONFIGURATION_FAILURE:null,OVERRIDE_EMBED_CONFIGURATION:null,FETCH_DRIFTT_ORG:null,FETCH_DRIFTT_ORG_SUCCESS:null,FETCH_DRIFTT_ORG_FAIL:null,READY:null,GO_TO_NEW_CONVERSATION:null,GO_TO_LIST:null,GO _TO_SELECTED_CONVERSATION:null,GO_TO_OFFLINE_FEEDBACK:null,SET_SIDERBAR_VIEW:null,FETCH_DRIFTT_USERS:null,FETCH_DRIFTT_USERS_SUCCESS:null,FETCH_DRIFTT_USERS_FAIL:null,AUTHENTICATE_END_USER:null,AUTHENTICATE_END_USER_SUCCESS:null,AUTHENTICATE_END_USER_FAIL:null,FET CH_SEGMENT_MEMBERSHIP_PENDING:null,FETCH_SEGMENT_MEMBERSHIP_SUCCESS:null,FETCH_SEGMENT_MEMBERSHIP_FAILURE:null,FETCH_GEOLOCATION_PENDING:null,FETCH_GEOLOCATION_SUCCESS:null,FETCH_GEOLOCATION_FAILURE:null,ENROLL_IN_CAMPAIGN_PENDING:null,ENROLL_IN_CAMPAIGN_SUCCESS:n ull,ENROLL_IN_CAMPAIGN_FAILURE:null,OPEN_SIDEBAR:null,CLOSE_SIDEBAR:null,CLOSE_SIDEBAR_WITH_TWEEN:null,CHANGE_SIDEBAR_VIEW:null,SHOW_WIDGET:null,HIDE_WIDGET:null,SHOW_WELCOME_MESSAGE:null,HIDE_WELCOME_MESSAGE:null,EXPAND_WIDGET:null,COLLAPSE_WIDGET:null,IFRAME_RES IZE_DONE:null,IFRAME_RESIZE:null,IFRAME_OVERRIDE_SIZE:null,SHOW_TYPING_INDICATOR_BUTTON_ICON:null,OPEN_ACTIVATION_TAKEOVER:null,CLOSE_ACTIVATION_TAKEOVER:null,LIST:null,CONVERSATION:null,NEW_CONVERSATION:null,SET_IDENTIFIED_CONVERSATION:null,OFFLINE_FEEDBACK:null, LOADING:null,LAZY_CAMPAIGN_EVALUATION:null,HANDLE_POST_MESSAGE:null,HANDLE_WINDOW_SCROLL:null,HANDLE_WINDOW_MOUSE_OUT:null,HANDLE_WINDOW_MOUSE_OVER:null,REFRESH_TARGETING:null,REFRESH_TIME_ON_PAGE:null,SUBMIT_OFFLINE_FEEDBACK:null,SUBMIT_OFFLINE_FEEDBACK_SUCCESS:n ull,SUBMIT_OFFLINE_FEEDBACK_FAIL:null,DRIFT_ENQUEUE_MESSAGE:null,DRIFT_CREATE_MESSAGE_PENDING:null,DRIFT_CREATE_MESSAGE_SUCCESS:null,DRIFT_CREATE_MESSAGE_FAILURE:null,DRIFT_CREATE_CONVERSATION_PENDING:null,DRIFT_CREATE_CONVERSATION_SUCCESS:null,DRIFT_CREATE_CONVER SATION_FAILURE:null,WIDGET_STATS_PENDING:null,WIDGET_STATS_SUCCESS:null,WIDGET_STATS_FAILURE:null})},function(t,e,n){var c;c={CUSTOMER_API_BASE:"https://customer.api.drift.com",CONVERSATION_API_BASE:"https://conversation.api.drift.com",EVENT_API_BASE:"https:// event.api.drift.com",EMBED_API_BASE:"https://js.driftt.com",CLIENT_ID:"f6zuizdyhxrm7r",LAYER_APP_ID:"layer:///apps/production/15806ab6-607f-11e5-817e-98d908000a42"},c.COOKIE_PATH="/",c.LAYER_API_BASE="https://api.layer.com",c.SENTRY_DSN="https:// 816fa28dc7cf492ba8ffa277d90f0345@app.getsentry.com/61707",t.exports=c},function(t,e,n){var c=n(37);t.exports=function(t){if(!c(t))throw TypeError(t+" is not an object!");return t}},function(t,e){t.exports=function(t){return"object"==typeof t?null! ==t:"function"==typeof t}},function(t,e){e.f={}.propertyIsEnumerable},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var c=n(61);t.exports=function(t){return Object(c(t))}},function(t,e){var n=0,c=Math.random();t.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++n+c).toString(36))}},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(c) {"object"==typeof window&&(n=window)}t.exports=n},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,configurable:!1,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,configurable:!1,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,n){"use strict";var c=n(10),o=n(3),r=n.i(c.a)(o.a,"Map");e.a=r},function(t,e,n){"use strict";function c(t){var e=-1,n=t?t.length: 0;for(this.clear();++e<n;){var c=t[e];this.set(c[0],c[1])}}var o=n(189),r=n(190),i=n(191),a=n(192),M=n(193);c.prototype.clear=o.a,c.prototype["delete"]=r.a,c.prototype.get=i.a,c.prototype.has=a.a,c.prototype.set=M.a,e.a=c},function(t,e,n){"use strict";var c=n(3),o=c.a.Symbol;e.a=o},function(t,e,n){"use strict";function c(t,e){for(var n=-1,c=t?t.length:0;++n<c&&e(t[n],n,t)!==!1;);return t}e.a=c},function(t,e,n){"use strict";function c(t,e,c){var r=t[e];i.call(t,e)&&n.i(o.a)(r,c)&&(void 0!==c||e in t)||(t[e]=c)}var o=n(18),r=Object.prototype,i=r.hasOwnProperty;e.a=c},function(t,e,n){"use strict";function c(t,e,a,M,s){return t===e||(null==t||null==e||!n.i(r.a)(t)&&!n.i(i.a)(e)?t!==t&&e!==e:n.i(o.a)(t,e,c,a,M,s))}var o=n(141),r=n(1),i=n(19);e.a=c},function(t,e,n){"use strict";function c(t){var e=new t.constructor(t.byteLength);return new o.a(e).set(new o.a(t)),e}var o=n(75);e.a=c},function(t,e,n){"use strict";function c(t,e){return e=null==e?o:e,!!e&&("number"==typeof t||r.test(t))&&t>-1&&t%1==0&&t<e}var o=9007199254740991,r=/ ^(?:0|[1-9]d*)$/;e.a=c},function(t,e,n){"use strict";function c(t,e){return function(n){return t(e(n))}}e.a=c},function(t,e,n){"use strict";function c(t,e){var c=n.i(a["default"])(t)?o.a:r.a;return c(t,n.i(i.a)(e,3))}var o=n(47),r=n(135),i=n(145),a=n(0);e["default"]=c},function(t,e,n){"use strict";function c(t){return n.i(o.a)(t)&&a.call(t,"callee")&&(!s.call(t,"callee")||M.call(t)==r)}var o=n(95),r="[object Arguments]",i=Object.prototype,a=i.hasOwnProperty,M=i.toString,s=i.propertyIsEnumerable;e.a=c},function(t,e,n){"use strict";function c(t){var e=n.i(o.a)(t)?M.call(t):"";return e==r||e==i}var o=n(1),r="[object Function]",i="[object GeneratorFunction]",a=Object.prototype,M=a.toString;e.a=c},function(t,e,n){"use strict";function c(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=o}var o=9007199254740991;e.a=c},function(t,e,n){"use strict";var c=n(144),o=n(155),r=n(196),i=r.a&&r.a.isTypedArray,a=i?n.i(o.a)(i):c.a;e.a=a},function(t,e,n){var c,o,r,i,a,M,s;s=n(53)["default"],M=n(205)["default"],r=n(35).COOKIE_PATH,a=n(7),c=void 0,i="",o={ORG_ID_COOKIE_NAME:"DFTT_ORG_ID"+i,INBOX_ID_COOKIE_NAME:"DFTT_INBOX_ID"+i,END_USER_ID_COOKIE_NAME:"DFTT_END_USER_ID"+i,END_USER_EMAIL_COOKIE_NAME:"DFTT_END_USER_EMAIL"+i,END_USER_AUTH_TOKEN_COOKIE_NAME:"DFTT_END_USER_AUTH_TOKEN"+i,END_USER_PREV_BOOTSTRAP PED_COOKIE_NAME:"DFTT_END_USER_PREV_BOOTSTRAPPED"+i,LAYER_SESSION_TOKEN_COOKIE_NAME:"DFTT_REALTIME_SESSION_TOKEN"+i,END_USER_EXTERNAL_ID_COOKIE_NAME:"driftt_eid",ANONYMOUS_ID_COOKIE_NAME:"driftt_aid",LEAD_HAS_PREV_IDENTIFIED_COOKIE_NAME:"DFTT_LEAD_HAS_PREV_IDENTIF IED"+i,LEAD_EMAIL_COOKIE_NAME:"DFTT_LEAD_EMAIL"+i,WELCOME_MESSAGE_DISMISSED_COOKIE_NAME:"driftt_wmd"+i},t.exports=M({},o,{cookiePath:r,getIsConfigured:function(){return null!=c},cookie:function(){if(!this.getIsConfigured())throw new Error("You need to make sure that the cookie library is configured");return c},setCookiePath:function(t){return this.cookiePath=t},getCookie:function(t){return this.cookie().get(t)},clearAllCookies:function(){s(o,function(t){return function(e){return t.cookie().remove(e,{path:t.cookiePath})}} (this))},setCookie:function(t,e,n){return null==e?void a.warn("Tried to write an undefined value to cookie: "+t):(n=n||{},null==n.path&&(n.path=this.cookiePath),this.cookie().set(t,e,n))},clearCookie:function(t,e){return e=e|| {},null==e.path&&(e.path=this.cookiePath),this.cookie().remove(t,e)},setCookieLib:function(t){return c=t},getLeadHasPreviouslyIdentified:function(){var t,e,n,c;if(n=!1,c=this.getCookie(o.LEAD_HAS_PREV_IDENTIFIED_COOKIE_NAME))try{n=JSON.parse(c)}catch(e) {t=e,this.setCookie(o.LEAD_HAS_PREV_IDENTIFIED_COOKIE_NAME,!1)}return n},getUserHasPreviouslyBootstrapped:function(){var t,e,n,c;if(n=!1,c=this.getCookie(o.END_USER_PREV_BOOTSTRAPPED_COOKIE_NAME))try{n=JSON.parse(c)}catch(e) {t=e,this.setCookie(o.END_USER_PREV_BOOTSTRAPPED_COOKIE_NAME,!1)}return n}})},function(t,e,n){var c,o,r,i,a,M,s=[].slice;r=n(53)["default"],i=n(0)["default"],a=n(32)["default"],c=n(7),t.exports.combineHeaders=function(t){return a.apply(null, [{}].concat(s.call(t)))},t.exports.getJSONContentTypeHeader=function(){return{"Content-Type":"application/json"}},t.exports.getFormContentTypeHeader=function(){return{"Content-Type":"application/x-www-form-urlencoded"}},t.exports.getLayerHeader=function() {return{Accept:"application/vnd.layer+json; version=1.0"}},t.exports.encodeQueryData=function(t){var e,n,c;n=[];for(e in t)c=t[e],i(c)?r(c,function(t){return n.push(encodeURIComponent(e)+"="+encodeURIComponent(t))}):null!=c&&n.push(encodeURIComponent(e) +"="+encodeURIComponent(c));return n.join("&")},o=function(t){var e,n;if(200<=(n=t.status)&&n<300)return t;throw e=new Error(t.statusText),e.response=t,e},M=function(t){switch(t.status){case 101:case 204:case 205:case 304:return;default:return t.json()}},t.exports.createFetch=function(t,e){return fetch(t,e).then(o).then(M)["catch"](function(n){throw c.error(n,{request:{url:t,options:e},response:n.response}),n})},t.exports.throwIfFailed=function(t){if("TypeError"===(null!=t?t.name:void 0))throw new TypeError(t.statusText)}},function(t,e,n){var c,o,r,i,a,M,s,u,p,l,f,d,b,A,z,h,O,T,L,N,m,q,v,W,g,_,S,E;L=n(113),m=n(294),v=n(74),o=n(7),N=n(292),T=n(97).mergeWithInitialState,r=n(215)["default"],c="Drift.Targeting",l=function(){var t;return g(),W(document.referrer||"",p(location.hostname)),t=z(),T({visits:O(),referrer:t,ad:f(),device:d(),page:A(t.previousPage),scroll:h(),os:b(),timezone:N.tz.guess(),locale:(navigator.language||navigator.browserLanguage).split("-") [0],userAgent:navigator.userAgent,query:q(document.location.href||"")})},O=function(){return{first:M("firstVisit")||0,last:M("lastVisit")||0,count:M("numberOfVisits")||0,sessionCount:M("numberOfSessions")||0}},g=function(){var t,e;if(e=Math.round((new Date).getTime()/1e3),M("firstVisit")||_("firstVisit",e),t=M("lastVisit"),_("lastVisit",e),_("numberOfVisits",(M("numberOfVisits")||0)+1),null==t||L().diff(1e3*t,"hours")>1)return _("numberOfSessions",(M("numberOfSessions")||0)+1)},f=function(){var t;return t=q(document.location.href),s(t)},s=function(t){return{source:t.utm_source,name:t.utm_campaign,medium:t.utm_medium,content:t.utm_content,term:t.utm_term}},z=function() {return{original:M("originalReferrer"),previous:M("previousPage"),current:M("currentReferrer"),currentDomain:M("currentReferrerDomain"),currentSearch:M("referrerSearchTerm")}},W=function(t,e){var n,c,o;return n=t.replace(/.*?:///,"").replace(/www./ i,"").toLowerCase().substr(0,150),c=n.replace(/(.*?)/.*/,"$1"),o=q(t),t?(-1===c.indexOf(e)&&(M("originalReferrer")||_("originalReferrer",n),_("currentReferrer",n),_("currentReferrerDomain",c),_("searchTerm",o.query||o.q||o.search)),_("previousPage",n)): (_("currentReferrer",""),_("referrerDomain",""),_("previousPage",""))},d=function(){return u(navigator.userAgent)},u=function(t){return t.match(/ipad/i)?"tablet":t.match(/(mobi|phone|ipod|blackberry|docomo)/i)?"mobile":t.match(/(ipad|kindle|android)/ i)?"tablet":"desktop"},A=function(t) {return{path:a(document.location.pathname||""),hostname:document.location.hostname||"",url:a(document.location.href||""),title:document.title||"",search:document.location.search||"",referrer:t,href:document.location.href||""}},b=function(){return v? {architecture:v.os.architecture,family:v.os.family,version:v.os.version,name:v.os.toString()}:{name:void 0,version:void 0,architecture:void 0,family:void 0}},h=function(){var t,e,n,c;try{return c=window.innerHeight,t=document.body.scrollHeight,n=document.body.scrollTop,e=(n+c)/t,{windowHeight:c,scrollHeight:t,scrollTop:n,scrollPct:e}}catch(r){return o.warn("Unable to scroll values from window")}},M=function(t){if("undefined"==typeof document|| null===document||"undefined"==typeof localStorage||null===localStorage)return void o.log("Unable to get from localStorage "+t);try{return JSON.parse(localStorage.getItem(c+"."+t))}catch(e){return o.log("Error getting/parsing targeting -> "+t)}},_=function(t,e) {if("undefined"==typeof document||null===document||"undefined"==typeof localStorage||null===localStorage)return void o.log("Unable to set from localStorage "+t+" -> "+e);if(null!=e)try{localStorage.setItem(c+"."+t,JSON.stringify(e))}catch(n){o.log("Error storing targeting "+t+" -> "+e)}return e},i=function(){var t,e,n,i,a,M,s,u;if("undefined"==typeof document||null===document||"undefined"==typeof localStorage||null===localStorage)return void o.log("Unable to clear localStorage");for(a=[],t=e=0,s=localStorage.length;0<=s? e<s:e>s;t=0<=s?++e:--e)a.push(localStorage.key(t));for(u=[],n=0,M=a.length;n<M;n++)i=a[n],r(i,c)?u.push(localStorage.removeItem(i)):u.push(void 0);return u},q=function(t){var e,n,c,o,r,i,a,M,s;if(r={},!t)return r;if(t+="",i=-1===t.indexOf("?")?t:t.split("?")[1],! i)return r;for(a=i.split("&"),e=0,n=a.length;e<n;e++)o=a[e],M=o.split("="),c=decodeURIComponent(M[0]).toLowerCase(),s=decodeURIComponent(M[1]),r[c]=s;return r},p=function(t){var e,n,c,o,r,i;for(e="dc=tld",c=t.split("."),o=r=c.length-1;r>=0;o=r+=-1)if(i=c[o],n=c.slice(o).join("."),document.cookie=e+";domain=."+n+";",document.cookie.indexOf(e)>-1)return document.cookie=e.split("=")[0]+"=;domain=."+n+";expires=Thu, 01 Jan 1970 00:00:01 GMT;",n;return t},a=function(t){var e,n;try{t=m(t)}catch(n){e=n,o.warn("Could not parse URL '"+t+"'"),t=""}return t.replace(/https?:///,"").replace(/^www./,"")},S=function(t){return parseInt(t)},E=function(t){return parseInt(t)/ 100},t.exports={normalizeUrl:a,toInt:S,toPct:E,load:l,clear:i,parseQuery:q}},function(t,e){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},function(t,e) {t.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(t,e){t.exports={}},function(t,e){t.exports=!0},function(t,e,n){var c=n(36),o=n(266),r=n(62),i=n(68)("IE_PROTO"),a=function() {},M="prototype",s=function(){var t,e=n(102)("iframe"),c=r.length,o="<",i=">";for(e.style.display="none",n(259).appendChild(e),e.src="javascript:",t=e.contentWindow.document,t.open(),t.write(o+"script"+i+"document.F=Object"+o+"/ script"+i),t.close(),s=t.F;c--;)delete s[M][r[c]];return s()};t.exports=Object.create||function(t,e){var n;return null!==t?(a[M]=c(t),n=new a,a[M]=null,n[i]=t):n=s(),void 0===e?n:o(n,e)}},function(t,e){e.f=Object.getOwnPropertySymbols},function(t,e,n){var c=n(15).f,o=n(8),r=n(17)("toStringTag");t.exports=function(t,e,n){t&&!o(t=n?t:t.prototype,r)&&c(t,r,{configurable:!0,value:e})}},function(t,e,n){var c=n(69)("keys"),o=n(41);t.exports=function(t){return c[t]||(c[t]=o(t))}},function(t,e,n){var c=n(5),o="__core- js_shared__",r=c[o]||(c[o]={});t.exports=function(t){return r[t]||(r[t]={})}},function(t,e){var n=Math.ceil,c=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?c:n)(t)}},function(t,e,n){var c=n(37);t.exports=function(t,e){if(!c(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!c(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!c(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!c(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}},function(t,e,n){var c=n(5),o=n(4),r=n(64),i=n(73),a=n(15).f;t.exports=function(t){var e=o.Symbol||(o.Symbol=r?{}:c.Symbol||{});"_"==t.charAt(0)||t in e||a(e,t,{value:i.f(t)})}},function(t,e,n){e.f=n(17)},function(t,e,n){(function(t,c){var o;(function() {"use strict";function r(t){return t=String(t),t.charAt(0).toUpperCase()+t.slice(1)}function i(t,e,n){var c={"10.0":"10",6.4:"10 Technical Preview",6.3:"8.1",6.2:"8",6.1:"7 / Server 2008 R2","6.0":"Vista / Server 2008",5.2:"XP 64-bit / Server 2003",5.1:"XP", 5.01:"2000 SP1","5.0":"2000","4.0":"NT","4.90":"ME"};return e&&n&&/^Win/i.test(t)&&!/^Windows Phone /i.test(t)&&(c=c[/[d.]+$/.exec(t)])&&(t="Windows "+c),t=String(t),e&&n&&(t=t.replace(RegExp(e,"i"),n)),t=M(t.replace(/ ce$/i," CE").replace(/bhpw/ i,"web").replace(/bMacintoshb/,"Mac OS").replace(/_PowerPCb/i," OS").replace(/b(OS X) [^ d]+/i,"$1").replace(/bMac (OS X)b/,"$1").replace(//(d)/," $1").replace(/_/g,".").replace(/(?: BePC|[ .]*fc[ d.]+)$/i,"").replace(/bx86.64b/gi,"x86_64").replace(/
  • 47.
    8. Case Studies •Every product is built differently. • Every product has had complete rebuilds. • Every product has a storied history. • Here’s a couple of them…
  • 48.
    Facebook • Back-end originallybuilt with PHP, likely with a basic WAMP setup (Windows, Apache, MySQL, PHP). Front-end naturally rendered HTML (rendered by PHP), CSS and JS. No sense of business logic separation (too much effort). • Now, front-end is still written in PHP-backed HTML but runs through their weird crazy “HipHop” compiler: PHP -> AST -> C++ -> G++ -> x64. Business logic exposed through Thrift in PHP, C++ or Java based on service. Also running Java on custom application servers. Database is MySQL, caching is done through memcached (300TB at a time) and HBase. Offline processing done through Hadoop and Hive. Data logging through Scribe, stored in HDFS through MapReduce. Page acceleration through BigPipe (pipelining logic). Varnish Cache for HTTP proxying. User storage through Haystack. • Messenger is another thing entirely with all sorts of insane shit like infrastructure sharding, dynamic cluster management and cell structures. Based on Epoll server developed in Erlang and Thrift.
  • 49.
    Twitter • Twitter hasalways run on Rails but originally based on regular Ruby. MySQL database, temporarily sharded. • “Search” replaced Rails with Java server called Blender. • “Messages” replaced Rails with Starling (Ruby) then replaced with Scala. • Database replaces MySQL with Gizzard and FlockDB • Lots of custom stuff - Snowflake, Rockdove, Firehose.
  • 50.
    Presumi • Back-end inExpress and Handlebars (hybrid rendering engine), front- end originally in Handlebars and jQuery. Database on MongoDB. • Live chat with Drift, error reporting with Rollbar, analytics with Google Analytics, payments with Stripe, email with Sendgrid, A/B with Optimizely. • Replaced front-end with jQuery with React, Handlebars with JSX. • Actual build process takes my JSX, transpiles through Babel (+React plugin) and Webpack and spits out JS. Basically I write super hot futuristic code and it converts it to pleb browser code. • Currently replacing internal app hybrid-rendering with full JS rendering and implementing React properly, reducing server usage by >50%.
  • 51.
    That’s all I’vegot Thanks for listening. I’m here for questions :)