Notes taken at the Render Conference 2016
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
README.md

README.md

Render Conf, Oxford, 2016

Thursday 21st April

Designing Meaningful Animation, Val Head

  • advocates using more animation on the web
  • not annoying animations though
  • great ui animation has purpose and style
  • 12 principles of animation
    • from the book "disney animation: the illusion of life"
    • also summarised at http://the12principles.tumblr.com/
    • they are:
      1. squash and stretch
      2. anticipation
      3. staging
      4. straight-ahead action and pose to pose
      5. follow-through and overlapping action
      6. slow in and slow out
      7. arcs
      8. secondary action
      9. timing
      10. exaggeration
      11. solid drawing
      12. appeal
  • timing & spacing
    • timing: amount of time it takes an action to happen / duration
    • spacing: changes in speed over the duration of the action's timing
    • essentially: timing = duration, spacing = easing
    • make animated objects appear to obey laws of physics
    • establish mood, emotion and reaction
    • css easing keywords are quite limiting: linear, ease, ease-in, ease-out, ease-in-out
    • cubic-bezier() function provides much more control
    • think of cubic-bezier args as x/y co-ordinates on a graph: x1, y1, x2, y2
      • x1, y1 denotes time
      • x2, y2 denotes progression
      • changing the x/y values affects the shape of the bezier curve
    • play with http://cubic-bezier.com/
      • can pick out different bezier curves for easing and compare the animations
  • follow through
    • not everything comes to a stop at once
    • often just means over-shooting the target position
    • can be achieved by picking a bezier curve that goes beyond the end point
  • secondary action
    • supplemental action, reinforces and adds dimension
  • uianimationnewsletter.com

The Landscape of Front-End Testing, Alicia Sedlock

  • visual regression tests
    • use graphicsmagick / imagemagick to diff two screenshots
    • can be done with casper to set up page / phantomcss.screenshot to capture a specific ui component
    • component-based is less brittle than full-page
    • component-based means you can just test the style guide
    • can also run it across different viewport sizes
    • interesting phantomcss options: mismatchTolerance, viewportSize
    • other tools: backstopjs, wraith, percy.io
    • don't have to be screenshot based, percy interrogates the html and css

SVG in Motion, Sara Soueidan

  • 6 different ways to embed svg
    • img element
      • can be cached
      • no css interactions
      • no scripting
      • css animations only work if embedded inside svg
    • picture element
      • same pros and cons as img
    • css background-image
      • same pros and cons
      • can be cached as part of stylesheet
    • object tag
      • scripting allowed
      • can be cached
      • has a default mechanism, but also flexible, can specify e.g. a table instead
      • css animations and interactions work if defined inside svg element
      • to access from js:
        1. get object element
        2. get its contentDocument
        3. get svg element from that
    • iframe element
      • pretty much the same as object
      • different behaviour cross-origin to object
    • inline svg element
      • not cached (unless html is cached)
      • no extra http requests
      • scriptable from anywhere
      • css animations and interactions always work
  • always optimize
    • tooling: svgo
    • unless the optimized structure screws up your animation
  • animation via smil is deprecated
  • css is fine for simple animations
    • color, simple transitions
    • css can only animate attributes that are available in css
      • that list is extended in svg2
    • default rotation origin is different to html, 0 0 instead of 50% 50%
      • set transform-origin to fix
  • use js for complex animations
    • transforms, path morphing, line drawing
  • greensock.com/svg-tips
  • snap.svg is the jquery of svg
  • greensock good for chaining animations
    • can stack tweens, create precise timelines, control tween delays, specify moments in time to start animations, start animations relative each other using relative labels, nest timelines
  • svg viewBox
    • area of the canvas that is visible inside the svg viewport
    • defined by x, y, width, height
    • can be animated to allow panning and zooming on a larger image
    • depends on bounding box (bbox), the smallest bounding rectangle for an element
      • e.g. set viewBox to an elements bbox will zoom into specific element

Drawing on Canvas, Mariko Kosaka

  • knitting is array manipulation, map, reduce etc
  • created programming language for knitting patterns and web app to render them
  • knitting patterns are limited
    • low res, 200 pixels maybe
    • few colours
    • needs image processing
  • image-processing math is complicated, wanted to use js instead
    • element
  • create with document.createElement, set width and height
  • two contexts available
    • canvas.getContext('webgl')
    • canvas.getContext('2d')
  • context determines the api you use to interact with the element
  • for knitting patterns, 2d context is sufficient
  • copy data onto canvas from img element
    • context.drawImage(imgEl, 0, 0)
  • get image data from canvas element
    • context.getImageData(0, 0, 100, 100)
  • then do some image processing on the data
  • put processed image data back on to canvas element
    • context.putImageData(imageData, 0, 0)
  • imageData is an ImageData object
    • { width: 2, height: 2, data: [ 255, 255, 255, 255, // 0,0: R, G, B, A (opacity) 255, 255, 255, 255, // 0,1: R, G, B, A 255, 255, 255, 255, // 1,0: R, G, B, A 255, 255, 255, 255 // 1,1: R, G, B, A ] }
  • from image data you can do whatever you want
    • crazy example: turn array into css for box shadow, so you can create a box-shadow that looks like the input image
    • more practical is functions for image filters
      • no filter: colour => colour
      • inverse: colour => 255 - colour
      • darken: colour => n - colour < 0 ? 0 : n - colour
      • lighten: colour => n + colour > 255 ? 0 : n + colour
      • less contrast: darken light colours by n, lighten dark colours by n
      • more contrast: darken dark colours by n, lighten light colours by n
      • threshold: colour => colour < n ? 0 : 255
        • can be used for pixel-perfect image maps
          • create canvas element in memory
          • interesting area set to white pixels
          • rest of the image black pixels
          • user clicks on actual image, event has x/y coords
          • check pixel on canvas element at x/y, is it white or black?
      • posterization: multiple stepped thresholds at different values of n
        • colour => colour < n ? 0 : (colour < n2 ? n : (colour < n3 ? n2 : ... ) )
      • solarization: high/low contrast at higher/lower values, invert the middle values
      • greyscale: set all three colours to the same value
      • effects can be changed for different colours to produce different effects
        • can be useful, e.g. in data analysis for highlighting trends/differences
      • blur or sharpen
        • "social graph for pixels"
        • for blur you want to blur target pixel with its neighbours
          • get colours of surrounding pixels
          • calculate average colour
          • set target pixel colour to average
          • box blur gives each neighbour equal weighting
          • gaussian blur values closer neighbours higher to preserve edges more
        • sharpen is opposite of blur, neighbours have negative weighting
        • tilt shift can be achieved by repeatedly applying gaussian blur over wider and wider area each time
  • don't do image processing in foreground, use web workers
    • communicate with workers via postMessage/onmessage
  • can export data from canvas element in two ways
    • canvas.toDataURL('image/png')
      • returns base-64 encoded data URI
      • only good for smallish images, max URL length ~2000 characters
    • canvas.toBlob(fn, 'image/jpeg', 0.95)
      • fn calls window.URL.createObjectURL(blob)
      • needs polyfilling in old browsers

Technology: The Power and the Promise, Robin Christopherson

  • mobile computing is like extreme computing
  • on mobile, everyone is disabled occasionally
    • maybe there is bright sunshine
    • maybe you only have one hand free
    • maybe you're driving
    • maybe you're heavily time-constrained
    • maybe you just have fat fingers
    • temporary motor impairments, temporary visual impairments
    • smart tv users are effectively keyboard-only users
  • helping people with disabilities is no different to helping "normal" people in extreme environment
  • ux should take these situations into account
  • smartphones are incredibly valuable to disabled users, they help in a way no previous technology has
    • deaf people can sign to each other via facetime
    • blind people can use wordlens to speak written signs back to them
    • google translate can translate foreign signposts in real time
  • seeing ai is an app that reads a description of a photo taken via glasess, for blind people
  • facial emotion recognition is useful for people with visual impairments or autism
  • moto hint is a nut-size earpiece that has voice recognition, accepts commands via speech and speaks the response back
  • if you're building a site or app consider how it would work in a headless environment
    • if it is neutral about user agent capabilities you're on the right track
  • driverless cars give blind people more mobility
    • with driverless cars pedestrians might not need to stick to pavements
  • captcha is terrible for accessibility
    • the audio alternative is deliberately distorted
    • better is "text captcha", which asks logic questions, or "no captcha"
  • felix baumgartner's hud failed
    • meant he pulled the cord early and missed world record for longest freefall
    • if there had been backup/redundant signals he'd have known where he was
  • accessibility can be a life or death issue
    • it should not be optional
    • provide redundancy / alternatives in case the first option fails or is no use for somebody

Rendering the Obvious, Frederik Vanhoutte

  • creativity is hard to measure
  • rainbow seems like an obvious thing
    • optical geometry taught at school, simple maths
    • like a prism, just different shapes (spheres instead of triangles)
  • people used to think colours came from inside a prism
  • newton proved it wrong by adding a second prism, refracting colours back to white
  • modelling how raindrops produce a rainbow is more complex than modelling a prism
  • a spherical prism does not produce a rainbow, the triangular shape is important
  • not all angles of light on a triangular prism produce a rainbow
  • with rainbows, the sun is at your back, with prisms you look at the source of light
  • treating refraction and reflection as two discrete phenomena hides the complexity of what is really happening
    • they're imposed by the way we tend to think about reality
    • we prefer boxes to put things in
  • discrete states, classigications, species, entities etc are artificial constructs
  • process and continuity are key, not state and labels
  • there are certain angles for light to hit a spherical prism (raindrop) at, which causes it to bounce around inside the drop (reflection)
  • tweaking the angles can introduce different patterns inside and outside the raindrop
  • the position of the observer affects how those patterns are perceived
    • at certain angles, light exits raindrop as a spectrum
    • observers in other positions do not see the spectrum
    • in certain positions a spectrum of light is visible, but in other positions it isn't
  • lots of raindrops in combination cause a rainbow
  • every observer sees their own rainbow
  • when the sun is low rainbows are bigger
  • when the sun is high rainbows are smaller
  • when the sun is above 42 degrees, it is impossible to see a rainbow
  • no rainbows at midday
  • there is always a dark area above the rainbow, band of alexander
  • there is always a second rainbow above the band of alexander
  • if you are high enough and ground is not in the way, rainbow is a perfect circle
  • point of the rainbow is to illustrate that simple explanations obscure truths
  • when you discover that a prism doesn't explain a rainbow there are several responses possible:
    • "i want to find out more, what is going on?"
    • "somebody else will know about it, i don't need to."
    • "i have discovered that a prism does not explain a rainbow, ergo rainbows do not exist. there is obviously a conspiracy of western science that is hiding something which is going on." (the nutcase response)
      • dangerous
      • common in, e.g., healthcare
    • "i know it is a simplification but i don't need to know more, i have enough information and enough skill to base decisions on this wrong model."
      • even more dangerous
      • common in policy-makers
  • simple models used for everyday explanations inhibit us from seeing what is really there
  • quote by antoine de sant-exupéry:
    • "if you want to build a ship, don't drum up the men and women to gather wood, divide the work and give orders. instead, teach them to yearn for the vast and endless sea."
    • not the real quote, it has been translated, massaged, invented by a motivational speaker trying to make a point
    • the real quote is in french and is taken from a story, is much longer and more complex
    • the fake quote implies "if you want you to create something, make your workforce care / motivate them"
    • the real quote implies "if you want to achieve something, care about it yourself and make other peopel care"

Friday 22nd April

Show Them What You Got, Jake Archibald

  • use service workers to build progressive web apps
    • if (navigator.serviceWorker) { navigator.serviceWorker.register('/foo.js') }
    • then, in registered worker:
      • window.addEventListener('install', event => event.waitUntil(promise))
        • won't be interrupted by fetch events
        • allows you to get everything you need from the network up front
        • then use cache api to store offline content
          • caches.open('foo').then(cache => cache.addAll(resources))
      • window.addEventListener('fetch', event => {})
        • get events for every request, e.g. can call preventDefault()
        • can respond with cached content from above
          • event.respondWith(caches.match(event.request).then(r => r || fetch(event.request)).catch(if (event.request.mode === 'navigate') { return caches.match('/offline-content.html')))
          • or can respond with previously fetched content so user can still see last state
    • above is great for offline, not great for very slow connections
    • can't depend on navigator.onLine because it only checks if e.g. router is on
      • router itself may not be connected but navigator.onLine won't report that
    • by putting more stuff in the cache, you can improve the experience in poor connections
  • cache api doesn't work well for e.g. continual feed of items arriving over a websocket
  • use indexeddb for that
    • "worst api ever developed in the history of computer science"
    • uses events, not promises
    • idb module on npm, mirrors indexeddb api but uses promises instead of events
    • assuming schema: [ { id, user, time, value } ]
    • to create a db:
      • const dbPromise = idb.open('foo', 1, db => db.createObjectStore('items', { keyPath: 'id' }).createIndex('by-time', 'time'))
    • to add items:
      • dbPromise.then(db => db.transaction('items', 'readwrite').objectStore('items').add(item))
    • to get items:
      • dbPromise.then(db => db.transaction('items').objectStore('items').index('by-time').getAll()).then(items => ...)
  • above has given network resilience, works online, offline and with slow connections
  • for resilient sending of data, use background sync api
    • fall back to normal send if sync.register() fails
    • otherwise service worker gets a sync event
      • then you can try to send items from service worker and they can stay in your work queue until you know they've sent
  • progressively enhance all of the above so that your site still works in older browsers
    • will just mean your site runs faster / more reliably in newer browsers, still works as it used to in old browsers
  • service workers isn't finished, it's still progressing
  • in chrome it exposes an api for the html stream so that you can render as soon as you receive data

How to Ask About Gender, Chad Gowler

  • common beliefs
    • everybody has one and only one gender
    • it's either male or female
    • male and female are discrete and non-overlapping
    • gender doesn't change over time
  • hence the standard male/female drop-down select on web forms
  • can analyse gender by using five scales: chromosomes, sexual characteristics, expression, role, identity
    • chromosomes
      • not as simple as xx=female, xy=male, there are chromosomal variations
      • e.g. klinefelter syndrome, xxy, 1 in 1000 male births
      • e.g. some women have 3 x chromosomes
      • e.g. in 2008 a woman with xy chromosomes gave birth to a daughter with xy chromosomes
    • sexual characteristics
      • genitalia, breasts, facial hair, adam's apple
      • "penis is male, vagina is female"
      • intersex people have appearance that doesn't fit in either of those two boxes
        • e.g. girls born without a womb
        • e.g. boys born without testicles
    • gender expression
      • "women wear dresses, men wear trousers"
      • hair, makeup, clothingA
    • gender roles
      • society considers some roles to be masculine, some feminine
    • gender identity
      • gender in your soul
      • can be made up from other attributes or can be completely separate
      • transgender = transitions from male to female or vice versa
      • non-binary = don't identify as either male of female, maybe no gender or both or some combination
      • can change over time
  • maybe you shouldn't be asking about user's gender at all
    • it's fine if you're asking in order to monitor diversity
    • less clear cut for social profiles
      • number 1 rules is don't out anybody, let people specify who can see the information
    • if you need info for 3rd party services, tell users that is what you're doing
      • also tell them what the service is, it will help them to answer the question
    • never okay to ask about gender for advertising
    • never okay to assume gender based on other info / physical attributes
    • never okay to refuse service based on someone's gender
      • likewise can't refuse bases on gender transition
    • never okay to ask about gender just out of convention/tradition
      • why do you need that data?
      • see book, "forms that work: designing web forms for usability"
        • specifically, the section about the question protocol
      • find out why data is needed, who will have access to it, what they want to do with it, whether it is optional/required, what happens if data is wrong
  • proper gender-neutral title is "Mx" (pronounced mix)
    • if you don't have "Mx" on your title drop-down, it's wrong
  • never put "transgender" as an option for someone's gender
    • actual transgender people will either put male or female
    • non-binary people won't use "transgender"
    • transgender is not a gender, it's a separate attribute like, e.g. being left-handed
  • never put "other" as an option for someone's gender
  • "non-binary" is usually okay as an option, but some non-binary people don't like it
  • don't ask what gender someone identifies as, it is what gender are they
  • best thing to do is to offer three options: male, female, or a blank for the user to fill in
  • also provide an explanation of why you're asking for the information

How Fastly Designs for Complexity, Jade Applegate

  • fastly has been renowned for being a good cdn with a poor ui
  • faced many challenges in designing a better one
  • rationale
    • design complexities
      • lack of rich interactions
      • no consistency of experience
      • missing sense of completion
      • outdated, stale site
      • user not kept in mind
      • lack of ux principles
    • engineering complexities
      • hard to quickly make changes
      • no test coverage
      • lack of code consistency
      • needed modern architecture (backbone+coffeescript, nobodoy wanted to work on it)
      • ownership issues
      • many dependencies, slow deployment process
  • approach
    • full rewrite, using ember.js
    • design refresh
    • match fastly.com (different team) for brand consistency
  • process
    • ux interviews
      • inexperienced users, give them a specific small task to carry out
      • advanced users, harder more in-depth task to carry out
      • see how people use flows, where they make mistakes
    • design feedback sessions
      • designers + product + engineering
      • can be visual feedback or functionality-based feedback
      • incorporate feedback into the designs
    • prototyping phase
      • engineer and designer collaborate, build proof of concept
      • lots of questions come up in the development of poc
    • development phase
      • engineer implements final designs
    • small refinement phase
      • engineer demos to product + design
      • get sign-off, make tweaks
    • merge/release cycle
      • engineer + product
      • code reviews, merge, deploy live
      • give release notes to customers
      • interim beta releases for some users
    • whole thing took over a year from start ti finish
  • improvements
    • minor
      • a guide for the meanings of different colours
      • a guide for the different button states
      • standard icon set
      • help text throughout the app
      • link to canonical best-practices documentation from inside the app
    • major
      • sensible defaults in form fields
        • makes highly-technical configuration easier
      • visual hierarchy for related ui components
      • best practice
        • teach users with examples of best practices from within the app
      • sense of completion
        • show an animation after completing a ui operation, to reassure the user that it's done
  • lessons learned
    • user's don't understand your site as well as you do
    • understand the problems you're trying to solve
    • be realistic about the scope of your project
    • always keep your users in mind
      • personas can help with this
    • give users autonomy, but provide help where needed

Immutable User Interfaces, Lee Byron

  • in software, architecture is a metaphor
  • architecture stems from the arch, which has proved to be a highly composable shape
  • marcus vitruvius pollio wrote that good archicture should satisfy 3 principles: firmitas, vtilitas, venvstas
    • firmitas
      • durability
      • a building should stand up robustly and remain in good condition
      • for apps, we're looking for architectural choices that reduce bugs and improve performance
    • utilitas
      • utility
      • a building should be suitable for its purpose
      • for apps, architectual choices depend on whether things are static or dynamic, simple or complex, rely on more networked or live data
    • venustas
      • beauty
      • a building should be aesthetically pleasing
      • for apps, architectural choices should impact how easy or hard it is for teams to improve or iterate on apps over time
  • architecture is about choosing elements of abstraction
  • for building information-rich, user-facing apps, rest and mvc are the dominant architectures
  • big question for building these apps is "what changed?"
    • how can you tell when something has changed so you can keep models, views up to date
    • when models and views both listen to each other for mutation changes, it's easy for small changes to have unpredictable, cascading effects
  • other big question is how to synchronise data with servers
  • networks have problems with latency, intermittency and failure
  • rest can be crippling when there are multiple dependent requests
  • immutability can address these problems
  • immutable app architecture
    • tightly control change
  • views
    • view apis suck, full of mutable operations, forced to store mutable references
    • components are an abstraction on top of views that declare which views should be displayed at which time
      • pure function, state as input, view as output
      • good component library should provide pure functional api, under the hood should manage the mutable native views
      • e.g. two calls with different data will produce two different view trees as output
        • component library will diff the trees and work out the minimal ui updates to render change on the screen
      • react does all this
  • models are immutable, plain objects, getters only
  • components render data from models, easy for models and components to get out of sync
    • fix this by having component describe what data it needs, allowing you to work backwards
      • co-located data dependencies, see graphql
  • graphql lets you perform complex server queries in a single request
    • equivalent rest would require lots of separate requests to the server
    • need this on mixbot*
  • query fragments let you elide specifics of sub-queries to one place
    • e.g. a query fragment for getting profile data
  • actions and state encapsulate changes from user interaction
  • models > components > views > actions > state > models ...
  • server > state ...
  • state should also be immutable
  • action is a pure function that takes state as input, returns new state as output
  • new state feeds into model and the loop goes round again
  • avoid performance problems with immutability by using structural sharing
    • base new instances off previous ones, recycling as much of previous state as possible
    • persistent immutable data structures
    • see immutable.js
  • some moderate overheads to immutability, can mitigate it with memoization
    • cache pure function results by their arguments
    • fast memoization not possible without immutable data structures
  • to give async actions the illusion of immediacy, can make them return a guess state as well as a promise of the actual state
    • introduces the problem of action race conditions, solve them with a queue
      • keeps track of all in-flight actions, returning optimistic response states
      • if an action fails, replay all actions since last known good state
      • hard to build this without immutability
  • overall architecture:
state <----- queue <----- actions
  | ^             /-------/ ^ ^
  | |             v         | |
  | \------- server --------/ |
  |                           |
  v                           |
models ---> components ---> views
  • simplifies app challenges, only possible with immutability

Resilience, Jeremy Keith

  • packet-switching provides resilient network architecture
  • tcp/ip are resilient to top-down network control
  • design of the web is influenced by the design of the internet
  • composed of small, simple parts
  • first version of html had 21 elements, most of which came from sgml
  • html 5 has 121 elements
  • html pages from the first version still work in browsers today
  • key to that backwards compatibility is that browsers ignore unrecognised tags and render their content
  • thus fallback content can be introduced in between new opening and closing tags (this happened for the canvas element)
  • srcset attribute and picture element build on the img element, so backwards compatibility is again provided by design
  • in css, browsers will just skip selectors they don't recognise
  • approaches like oocss, bem, smacss etc possible without lobbying the browser vendors or ww3c, they were always possible from the birth of css
  • postel's law is what facilitates all of the above
    • be conservative in what you send, be liberal in what you accept
    • postel coined this for packet-switching
    • can be applied in many other places, ux, language design
  • easier for declarative languages to implement postel's law, imperative languages less so
    • css, html are declarative
    • js is imperative and also necessarily more fragile than html or css
    • browser has to reject js that it doesn't understand, stop parsing and won't parse following code
  • on the web, things often start at the imperative js layer, before being implemented in html or css by browser vendorsA
  • xhtml 2 would have been the worst of both worlds, used fragile error-handling model from xml, widely rejected by developers
  • javascript has the same fragile error-handling model as xhtml 2
  • google chrome download button was broken by a javascript error
    • nobody in the world could download google chrome at the time
  • murphy's law is as important as postel's law
    • anything that can possibly go wrong will go wrong
    • murphy was an aerospace engineer, never lost anyone on his watch thanks to that philosophy
  • because of the fragile error-handling method of client-side js, it makes sense to apply murphy's law to it
  • other industries hope for the best, prepare for the worst
    • e.g. automobile industry does crash testing, imagine if they decided not to
  • "like cars designed to perform in extreme heat or on icy roads, websites should be built to face the reality of the web's inherent variability"
  • 3-step approach to building resilient websites:
    1. identify core functionality
    2. make that funcitonality available using the simplest technology
    3. enhance from there
  • identifying core functionality
    • what you want every user to be able to accomplish, regardless of network, user agent, location etc
    • for news sites, it means a user can read the news
    • for twitter it is the ability to send and receive messages
    • for instagram it is the ability to view and upload photos
    • for google docs platform it is the ability to write and read documents
  • using the simplest technology
    • will be available to the most people
    • for news sites it is an html file
    • for twitter it is ol/li elements and a form to submit
    • for instagram it is img elements and a form to upload
    • for google docs it is a textarea in a form
  • enhance
    • where the fun is
    • go crazy playing with all the cool new technologies
    • for news site it is responsive design and font-face
      • mobile-first responsive design uses layout as an enhancement
    • for twitter it is xhr and websockets for live updates
    • for instagram it is file api, canvas element, css filters
    • for google docs it is local storage, indexedb, service workers
  • the web is for everyone, not "everyone who has appcache or service workers"
  • enhancements can stack
    • e.g. a text address, enhanced to an image, which is enhanced to a google map, which is enhanced with animations or whatever
  • it is not a choice between basic experience or fancy experience, you can do both at the same time
  • it is a myth that progressive enhancement means spending all your time on old browsers
    • it means the opposite, you can spend all your time on newer browsers because you know the older ones are being served the simpler experience
  • progressive enhancement is the only safe way to play with cool new technology
    • it provides you with technical credit, not technical debt
  • 2 forms of pushback against progressive enhancement
    • too simplistic
      • "it's fine for a blog or a personal site, wouldn't work for my complex app"
      • same argument as when css came out to replace table layouts, was proved wrong then
      • same argument as when responsive design came out, was proved wrong then
    • too hard
      • "it means i have to build everything twice"
      • only the core functionality needs to be simple, everything else can be just done in cool new technologies
      • tools should be able to work in this way
      • if a tool doesn't let you work in the way you want, don't use that tool
      • the more you do progressive enhancement, the easier it gets
        • the first time trying css out instead of tables for layout it was hard
        • the first time trying responsive design was hard
      • srever-side js means effort can be saved in other areas with reduced duplication of code
      • developer convenience should never trump the needs of the user
  • we should build on the best of the web, urls mean we can build things that persist over time