Upgrading CSS Animation With Motion Curves

artificial intelligence 5291510 1920

Upgrading CSS Animation With Motion Curves

There is UI animation, and then there is good UI animation. Good animation makes you go “Wow!” — it’s smooth, beautiful and, most of all, natural, not blocky, rigid or robotic. If you frequent Dribbble or UpLabs1, you’ll know what I am talking about.

Further Reading on Smashing: Link

With so many amazing designers creating such beautiful animations, any developer would naturally want to recreate them in their own projects. Now, CSS does provide some presets for transition-timing-function6, such as ease-in, ease-out and ease-in-out, which add some level of smoothness and realism, but they are very generic, aren’t they? How boring would it be if every animation on the web followed the same three timing functions?

One of the properties of transition-timing-function is cubic-bezier(n1, n2, n3, n4), in which you can pass four numbers to create your very own timing function. Towards the end of this article, you’ll know exactly what these four numbers represent — still, believe me, coming up with four numbers to capture the transition you are imagining in your head is nowhere close to being easy. But thanks to cubic-bezier8 and Ceasar9, you don’t have to. These tools bring motion curves to the web.


(Credit: m-2-h10)

Motion curves are primarily used by animators (for example, in Adobe After Effects11) to create advanced, realistic animations. With cubic-bezier and Ceasar, you can simply manipulate the shape of a curve, and those four numbers (n1, n2, n3, n4) will be filled in for you, which is absolutely great! Still, to use and make the most out of motion curves, you need to understand how they work, and that’s what we’re going to do in this article. Let’s begin.

Understanding Motion Curves Link

A motion curve is nothing but a plot between any animatable property12 and time. A motion curve defines how the speed of an animation running under its influence varies over time.

13
A motion curve is a plot between an animatable property and time. (View large version14)

Let’s take distance (translateX)15 as an example of an animatable property. (The explanation holds true for any other animatable property.)

Calculating speed at time t1 on a distance-time plot.16
Calculating speed at time t1 on the distance-time plot. (View large version17)

If you’ve had any experience with physics and basic calculus, you’ll know that deciphering speed from a distance-time graph is very simple. The first derivative of distance as a function of time, with respect to time, is speed, which means that an object following a distance-time curve would have greater speed in places where the curve is steep and lower in places where the curve is flatter. If you know how that works, great! You’re all set and can skip to the next section.

Now, I am aware that design and development is a diverse field, and not everyone has the same background. Perhaps the two paragraphs above were all jargon to you. Don’t fret. We’ll keep going and make sense of the jargon.

Consider the red box below. Let’s get a little callow here and call the red box “Boxy”; it’ll be easier to refer to it that way. All right, so Boxy is going to move from one edge of the screen to the other in a linear fashion, and we are going to analyze its motion.

One of the presets of transition-timing-function is linear. To make Boxy move, all we do is add the following class.

 .moveForward { transform: translateX(1000px); } 

To control the animation, we would set the transition property for Boxy as follows:

#boxy { width: 200px; height: 200px; background: red; transition-property: transform; transition-duration: 1s; transition-timing-function: linear; }

That’s a very verbose way to specify transition. In reality, you will almost always find transition written in its shorthand form:

#boxy { width: 200px; height: 200px; background: red; transition: transform 1s linear; }

Let’s see it go.

Boxy undergoing linear motion18
Box undergoing linear motion.

Robotic, isn’t it? You could say that this motion feels robotic because it’s linear, which is a perfectly plausible answer. But could you explain why? We can see that setting linear results in robotic motion, but what exactly is happening behind the scene? That’s what we’ll figure out first; we’re going to get to the innards and understand why this motion feels robotic, blocky and not natural.

Let’s start by graphing Boxy’s motion to see if we can gain some insight. Our graph will have two axes, the first being distance, and the second time. Boxy covers a total distance of 1000 pixels (distance) in 1 second (time). Now, don’t get scared by all the math below — it’s very simple.

Here is our very simple graph, with the axes as mentioned.

Empty graph with axes19
Empty graph with axes (View large version20)

Right now, it’s empty. Let’s fill it up with some data.

To start off with, we know that at 0 seconds, when the animation has not yet started, Boxy is in its initial position (0 pixels). And after 1 second has passed, Boxy has travelled a total of 1000 pixels, landing at the opposite edge of the display.

Boxy's initial and final positions21
Boxy’s initial and final positions (View large version22)

Let’s plot this data on the graph.

Graph with Boxy's initial and final positions plotted23
Graph with Boxy’s initial and final positions plotted (View large version24)

So far so good. But two data points are not enough — we need more. The following figure shows the positions of Boxy at different points of time (all thanks to my high-speed camera).

Boxy's positions at different points of time25
Boxy’s positions at different points of time (View large version26)

Let’s add this data to our graph.

Graph with different positions plotted27
Graph with different positions plotted (View large version28)

You could, of course, have many more data points for different times (for example, 0.375 seconds, 0.6 seconds, etc.) but what we have is enough to complete our graph. By joining all of the points, we have completed the graph. High five!

Final graph29
Final graph (View large version30)

Cool, but what does this tell us? Remember that we started our investigation with the goal of understanding why Boxy’s linear motion feels unnatural and robotic? At a glance, this graph we’ve just constructed doesn’t tell us anything about that. We need to go deeper.

Keep the graph in mind and let’s talk for a minute about speed. I know you know what speed is — I’d just like to put it in mathematical terms. As it goes, the formula for speed is this:

Mathematical formula for speed31
Mathematical formula for speed (View large version32)

Therefore, if a car covers a distance of 100 kilometers in 1 hour, we say its speed is 100 kilometers per hour.

Representing speed33
Representing speed (View large version34)

If the car doubles its speed, it will start covering double the distance (200 kilometers) in the same interval (1 hour), or, in other words, it will cover the original distance of 100 kilometers in half the time (0.5 hours). Make sense?

Similarly, if the car halved its speed (that is, slowed down by half), it would start covering a distance of 50 kilometers in the same interval (1 hour), or, in other words, it would cover the original distance of 100 kilometers in twice the time (2 hours).

Great! With that out of the way, let’s pick up where we left off. We were trying to figure out how the graph between distance and time can help us understand why Boxy’s linear motion feels robotic.

Hey, wait a second! We have a graph between distance and time, and speed can be calculated from distance and time, can’t it? Let’s try to calculate Boxy’s speed at different time intervals.

Calculating speed at different intervals35
Calculating speed at different intervals (View large version36)

Here, I’ve chosen three different time intervals: one near the start, one in the middle and one at the end near the final position. As is evident, at all three intervals, Boxy has exactly the same speed (s1 = s2 = s3) of 1000 pixels per second; that is, no matter what interval you choose in the graph above, you will find Boxy moving at 1000 pixels per second. Isn’t that odd? Things in real life don’t move at a constant speed; they start out slowly, gradually increase their speed, move for a while, and then slow down again before stopping, but Boxy abruptly starts with a speed of 1000 pixels per second, moving with the same speed and abruptly stopping at exactly the same speed. This is why Boxy’s movement feels robotic and unnatural. We are going to have to change our graph to fix this. But before diving in, we’ll need to know how changes to the speed will affect the graph drawn between distance and time. Ready? This is going to be fun.

Let’s double Boxy’s speed and see how the appearance of the graph changes in response. Boxy’s original speed, as we calculated above, is 1000 pixels per second. Because we have doubled the speed, Boxy will now be able to cover the distance of 1000 pixels in half the time — that is, in 0.5 seconds. Let’s put that on a graph.

Graph showing double speed37
Graph showing double speed (View large version38)

What if we tripled the speed? Boxy now covers 1000 pixels in one third of the time (a third of a second).

Graph showing triple speed39
Graph showing triple speed (View large version40)

Hmm, notice something? Notice how, when the graph changes, the angle that the line makes with the time axis increases as the speed increases.

All right, let’s go ahead and halve Boxy’s speed. Halving its speed means that Boxy will be able to cover only 500 pixels (half the original distance) in 1 second. Let’s put this on a graph.

Graph showing half speed41
Graph showing half speed (View large version42)

Let’s slow down Boxy a little more, making the speed one third of the original. Boxy will be able to cover one third of the original distance in 1 second.

Graph showing a third of the speed43
Graph showing a third of the speed (View large version44)

See a pattern? The line gets steeper and steeper as we increase Boxy’s speed, and starts to flatten out as we slow Boxy down.

Line gets steeper as speed increases and flattens out as speed decreases45
Line gets steeper as speed increases and flattens out as speed decreases. (View large version46)

This makes sense because, for a steeper line, a little progress in time produces a much higher change in distance, implying greater speed.

A small change in time produces a relatively large change in distance, making for a steeper graph.47
A small change in time produces a relatively large change in distance, making for a steeper graph. (View large version48)
A small change in time produces a relatively large change in distance, making for a steeper graph.49
A small change in time produces a relatively large change in distance, making for a steeper graph. (View large version50)

On the other hand, for a line that is less steep, a large change in time produces only a little change in distance, meaning a lower speed.

Change in time verus change in distance in a graph that is less steep51
Change in time versus change in distance in a graph that is less steep (View large version52)
Change in time versus change in distance in a graph that is less steep53
Change in time versus change in distance in a graph that is less steep (View large version54)

With all of the changes we have made, Boxy is still moving in a linear fashion, just at different speeds. However, with our newly gained knowledge of how changes to distance versus time can affect speed, we can experiment and draw a graph that makes Boxy move in a way that looks natural and realistic.

Let’s take it step by step. First, things in real life start out slow and slowly increase in speed. So, let’s do that.

In all of the iterations of the graph shown below, you will notice that the points at opposite corners remain fixed. This is because we are not changing the duration for which the animation runs, nor are we changing the distance that Boxy travels.

Constructing a custom motion curve55
Constructing a custom motion curve (View large version56)

If Boxy is to follow the graph above, it will move at a slower speed for 0.25 seconds, because the line is less steep starting from 0 to 0.25 seconds, and then it will abruptly switch to a higher speed after 0.25 seconds (the reason being that the line in the graph gets steeper after 0.25 seconds). We will need to smoothen this transition, though; we don’t want any corners — it’s called a motion curve, after all. Let’s convert that corner to a curve.

Constructing a custom motion curve57
Constructing a custom motion curve (View large version58)

Notice the smooth transition that Boxy undergoes from being at rest to gradually increasing in speed.

Boxy following the motion curve above59
Box following the motion curve above (View large version60)

Good! Next, objects in real life progressively slow down before stopping. Let’s change the graph to make that happen. Again, we’ll pick up a point in time after which we would like Boxy to start slowing down. How about around 0.6 seconds? I have smoothened out the transition’s corner to a curve here already.

Final custom motion curve61
Final custom motion curve (View large version62)

Look at Boxy go! A lot more natural, isn’t it?

Boxy following the custom motion curve63
Boxy following the custom motion curve (View large version64)

The curve we drew in place of the corner is actually a collection of many small line segments; and, as you already know, the steeper the line on the graph, the higher the speed, and the flatter the line, the slower the speed. Notice how in the left part of the image, the line segments that make up the curve get steeper and steeper, resulting in a gradual increase in speed, and progressively flatten out on the right side, resulting in the speed progressively decreasing?

A curve is nothing but a collection of many line segments.65
A curve is nothing but a collection of many line segments. (View large version66)

With all of this knowledge, making sense of motion curves becomes much easier. Let’s look at a few examples.

67
(View Large version)68
Example 169
Example 1 (View large version70)
71
(View Large version)72
Example 273
Example 2 (View large version74)
75
(View Large version)76
Example 377
Example 3 (View large version78)

Using Motion Curves In UI Animation Link

The next time you have to animate a UI element, you will have the power of motion curves at your disposal. Whether it’s a slide-out bar, a modal window or a dropdown menu, adding the right amount of animation and making it look smooth and natural will increase the quality of your user interface greatly. It will make the user interface just feel good. Take the slide-out menu below:

See the Pen nJial80 by Nash Vail (@nashvail9681) on CodePen9782.

Clicking on the hamburger menu brings in the menu from left, but the animation feels blocky. Line 51 of the CSS shows that the animation has transition-timing-function set to linear. We can improve this. Let’s head on over to cubic-bezier9183 and create a custom timing function.

If you’re reading this, it’s safe to assume that you’re a designer or a developer or both and, hence, no stranger to cubic bezier curves; there’s a good chance you’ve encountered them at least once. Bezier curves are a marvel. They are used primarily in computer graphics to draw shapes and are used in tools such as Sketch84 and Adobe Illustrator85 to draw vector graphics. The reason why cubic bezier curves are so popular is that they are so easy to use: Just modify the positions of the four different points, and create the kind of curve you need.

Because we always know the initial and final states of the animated object, we can fix two of the points. That leaves just two points whose positions we have to modify. The two fixed points are called anchor points, and the remaning two are control points.

Parts of a bezier curve86
Parts of a bezier curve (View large version87)

As you remember, cubic-bezier accepts four numbers (n1, n2, n3, n4) when you create a custom transition-timing-function. These four numbers represent nothing but the positions of the two control points: n1, n2 represents the x and y coordinates of the first control point, and n3, n4 represents the coordinates of the second control point. Because changing the position of the control points will change the shape of the curve and, hence, our animation overall, the result is the same when any or all of n1, n2, n3, n4 is modified. For example, the figure below represents cubic-bezier(.14, .78, .89, .35):

A cubic bezier curve representing (.14, .78, .89, .35).88
A cubic bezier curve representing (.14, .78, .89, .35) (View large version89)

The math behind these seemingly simple curves90 is fascinating.

All right, all right, let’s get back to where we were going with cubic-bezier9183: creating a custom transition-timing-function. I want the kind of animation in which the menu slides in very quickly and then gracefully slows down and ends:

Adjusting the cubic bezier curve92
Adjusting the cubic bezier curve (View large version93)

This looks good. The animation will start out fast and then slow down, rather than move at a constant speed throughout. I am simply going to copy cubic-bezier(.05, .69, .14, 1) from the top of the page and replace linear with it.

See the Pen nJial95 by Nash Vail (@nashvail9681) on CodePen9782.

See the difference? The second iteration feels much more natural and appealing. Imagine if every animation in your UI followed a natural timing function. How great would that be?

As we’ve seen, motion curves aren’t tricky at all. They are very easy to understand and use. With them, you can take your UI to the next level.

I hope you’ve learned how motion curves work. If you were going through a lot of trial and error to get motion curves to work the way you want, or if you were not using them at all, you should now be comfortable bending them to your will and creating beautiful animations. Because, after all, animation matters.

(al)

Footnotes Link

  1. 1 http://www.uplabs.com
  2. 2 https://www.smashingmagazine.com/2015/12/animating-clipped-elements-svg/
  3. 3 https://www.smashingmagazine.com/2015/06/practical-techniques-on-designing-animation/
  4. 4 https://www.smashingmagazine.com/2015/09/creating-cel-animations-with-svg/
  5. 5 https://www.smashingmagazine.com/2014/11/the-state-of-animation-2014/
  6. 6 https://developer.mozilla.org/en/docs/Web/CSS/transition-timing-function
  7. 7 https://dribbble.com/LukasStranak
  8. 8 http://cubic-bezier.com
  9. 9 https://matthewlein.com/ceaser/
  10. 10 https://dribbble.com/m-2-h
  11. 11 http://www.adobe.com/products/aftereffects.html
  12. 12 https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig26_large-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig26_large-opt.png
  15. 15 https://css-tricks.com/almanac/properties/t/transform/#article-header-id-3
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig27_large-opt.png
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig27_large-opt.png
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/08/TNndMJe.gif
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig1_large-opt.png
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig1_large-opt.png
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig2_large-opt.png
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig2_large-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig3_large-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig3_large-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig4_large-opt.png
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig4_large-opt.png
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig5_large-opt.png
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig5_large-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig6_large-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig6_large-opt.png
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig7_large-opt.png
  32. 32 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig7_large-opt.png
  33. 33 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig8_large-opt.png
  34. 34 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig8_large-opt.png
  35. 35 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig9_large-opt.png
  36. 36 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig9_large-opt.png
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig10_large-opt.png
  38. 38 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig10_large-opt.png
  39. 39 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig11_large-opt.png
  40. 40 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig11_large-opt.png
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig12_large-opt.png
  42. 42 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig12_large-opt.png
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig13_large-opt.png
  44. 44 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig13_large-opt.png
  45. 45 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig14_large-opt.png
  46. 46 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig14_large-opt.png
  47. 47 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig15_large-opt.png
  48. 48 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig15_large-opt.png
  49. 49 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig16_large-opt.png
  50. 50 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig16_large-opt.png
  51. 51 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig17_large-opt.png
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig17_large-opt.png
  53. 53 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig18_large-opt.png
  54. 54 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig18_large-opt.png
  55. 55 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig19_large-opt.png
  56. 56 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig19_large-opt.png
  57. 57 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig20_large-opt.png
  58. 58 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig20_large-opt.png
  59. 59 https://www.smashingmagazine.com/wp-content/uploads/2016/08/xs6l6oW.gif
  60. 60 https://www.smashingmagazine.com/wp-content/uploads/2016/08/xs6l6oW.gif
  61. 61 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig21_large-opt.png
  62. 62 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig21_large-opt.png
  63. 63 https://www.smashingmagazine.com/wp-content/uploads/2016/08/iI5mrff.gif
  64. 64 https://www.smashingmagazine.com/wp-content/uploads/2016/08/iI5mrff.gif
  65. 65 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig22_large-opt.png
  66. 66 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig22_large-opt.png
  67. 67 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig23_large-opt.png
  68. 68 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig23_large-opt.png
  69. 69 https://www.smashingmagazine.com/wp-content/uploads/2016/08/Ij44EBG.gif
  70. 70 https://www.smashingmagazine.com/wp-content/uploads/2016/08/Ij44EBG.gif
  71. 71 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig24_large-opt.png
  72. 72 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig24_large-opt.png
  73. 73 https://www.smashingmagazine.com/wp-content/uploads/2016/08/F4Ve4Xl.gif
  74. 74 https://www.smashingmagazine.com/wp-content/uploads/2016/08/F4Ve4Xl.gif
  75. 75 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig25_large-opt.png
  76. 76 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig25_large-opt.png
  77. 77 https://www.smashingmagazine.com/wp-content/uploads/2016/08/a0YYL8I.gif
  78. 78 https://www.smashingmagazine.com/wp-content/uploads/2016/08/a0YYL8I.gif
  79. 79 http://codepen.io/nashvail
  80. 80 ‘http://codepen.io/nashvail/pen/qNYmLG/’
  81. 81 ‘http://codepen.io/nashvail’
  82. 82 ‘http://codepen.io’
  83. 83 http://cubic-bezier.com
  84. 84 https://www.sketchapp.com/
  85. 85 http://www.adobe.com/in/products/illustrator.html
  86. 86 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig28_large-opt.png
  87. 87 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig28_large-opt.png
  88. 88 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig29_large-opt.png
  89. 89 https://www.smashingmagazine.com/wp-content/uploads/2016/08/css-animations-motion-curves-fig29_large-opt.png
  90. 90 https://medium.freecodecamp.com/nerding-out-with-bezier-curves-6e3c0bc48e2f#.113c4usq9
  91. 91 http://cubic-bezier.com
  92. 92 https://www.smashingmagazine.com/wp-content/uploads/2016/08/bezierDemo.gif
  93. 93 https://www.smashingmagazine.com/wp-content/uploads/2016/08/bezierDemo.gif
  94. 94 http://codepen.io/nashvail
  95. 95 ‘http://codepen.io/nashvail/pen/rLvymO/’
  96. 96 ‘http://codepen.io/nashvail’
  97. 97 ‘http://codepen.io’
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

Sucuri vs CloudFlare (Pros and Cons) – Which One is Better?

artificial intelligence 5291510 1920

Due to an increased emphasis on website security in today’s digital landscape, one of the most common requests we’ve gotten from readers is to do a pros and cons analysis of Sucuri vs CloudFlare to explain which one is better. Sucuri and CloudFlare are online services that offer website firewall, CDN, and DDoS protection services. In this article, we will compare Sucuri vs Cloudflare with pros and cons to find out which one is better.

Even the most secure websites on the internet are vulnerable to distributed denial of service attacks (DDoS), hacking attempts, and malware injection.

As a WordPress site owner you can use some security best practices like password protecting admin directory, limiting login attempts, adding two factor authentication, etc.

However these tips only work on software level which leaves your website mostly open to other types of attacks. These attacks can cause financial damage, data loss, poor search rankings and bad user experience.

Sucuri and CloudFlare offer a website application firewall (WAF).

This means that all your website’s traffic goes through their server scanners. If a request looks malicious, then the firewall would block it before it even reaches your website.

On the surface, these two services look nearly identical, but there are some key differences.

In this comparison, we’ll focus on:

  • Features
  • Pricing
  • Malware Removal Service

By the end, you’ll know exactly which platform is best for you.

Ready? Let’s compare Sucuri vs Cloudflare.

Features

In this section, we will look at the features offered by Sucuri and CloudFlare.

It’s important to note that both services offer different plans that come with different set of features.

As a user, make sure you’re not a victim of their marketing site because not all plans come with all the features.

CloudFlare Features

CloudFlare is best known for their free CDN service. They specialize in mitigating DDOS attacks using their Website Application Firewall product. CloudFlare keep your site available to users during an attack or under heavy traffic when your server is not responsive.

Their website firewall blocks suspicious traffic before it even reaches your website. The firewall also extends to form submissions which protects your website from comment spam and registration spam.

CloudFlare website firewall

CloudFlare also offers free and custom SSL certificates with all their plans. Free and pro plans only allow you to use CloudFlare issued certificate. For custom certificate you will need to upgrade to their Business or Enterprise plan.

While CloudFlare offer a free option that includes CDN, most other features including their Website Application Firewall require a paid plan.

CloudFlare doesn’t offer server scanning service to detect malware. It also doesn’t offer a malware removal guarantee if you were to be hacked on their watch.

Sucuri Features

Sucuri is one of the most reputable website security and monitoring service. They offer comprehensive website monitoring, scanning for malware, DDoS protection, and malware removal services.

Sucuri offers CloudProxy, a website firewall and load balancing service. It blocks suspicious traffic from reaching your website by effectively blocking DDoS attacks, code injection, bad bots, and other website threats. See our case study of how Sucuri helped us block 450,000 attacks in 3 months.

Sucuri offers integration with the free Let’s Encrypt SSL for their basic plan. You can also use custom SSL certificates with their professional and business plans.

Sucuri CloudProxy

Sucuri scans your website regularly for file changes, code injection, and malware. They clean up hacked sites, with support for all popular CMS software like WordPress, Joomla, Drupal, etc.

Winner: Sucuri is a clear winner because they offer a better combination of tools and services (Website Firewall + Load Balancing + Malware Cleanup / Hack Repair).

Pricing

Pricing is an important factor for many small businesses.

Here, we will compare the different pricing plans offered by CloudFlare and Sucuri, so you know exactly what you’re getting for your money.

FREE is not always better

CloudFlare Pricing Plans

CloudFlare offers a free CDN service for all. They don’t charge you for the bandwidth which means you will be able to use their free CDN regardless of your traffic volume.

However, this free plan does not come with the website application firewall. Your website may benefit from CDN, but it will not be properly protected against DDoS attacks, spam, bad traffic, etc.

For their web application firewall, you need the Pro plan which costs $20 / month (this is what you need for improved security).

This pro plan does not include advanced DDoS mitigation and custom SSL. For those features, you will need their Business plan which costs $200 per month.

Sucuri Pricing Plans

Unlike CloudFlare, Sucuri doesn’t offer a free plan. Their website security stack plan starts at $199.99 for an year, which is cheaper than CloudFlare’s pro plan.

This basic plan includes full website monitoring, website application firewall, DDoS protection, malware removal, and free LetsEncrypt SSL certificate.

Instead of excluding features from lower level plans, Sucuri uses priority as an incentive for their higher paying plans.

For example, malware removal estimated time for basic plan is 12 hours, 6 hours for professional plan, and 4 hours for business plan. However, the actual cleanup timings are way faster than that for all customers.

They offer 24/7 support as part of all plans. Their business plan subscribers can also use the Live Chat support.

Winner:Sucuri is an obvious choice for small businesses when it comes to pricing. CloudFlare Pro costs $240 / year vs Sucuri cost $199 / year and offer more features. To unlock same features, you’d have move up to CloudFlare’s $2400 / year plan. Sucuri’s most expensive plan is at $499 / year.

Malware Removal Service

Apart from denial of service attacks, malware and code injections are the most common threats faced by WordPress site owners.

Let’s see how both services protect your website against those common threats.

Website security and malware removal

CloudFlare – Security and Malware Removal

CloudFlare free version is basically a content delivery network which helps make your website fast.

The website security firewall comes with their paid plan. It includes CloudFlare’s ready to use custom rules set. These rules protect your site from common code injection hacks, XSS JavaScript exploits, and form submissions.

However, they do not offer file change detection, malware scanning, blacklist monitoring, and many other security features. You can add third-party apps for malware scanning, but these services will cost you additional fees.

Sucuri – Security and Malware Removal

Sucuri is a security focused company. They specialize in monitoring websites and protecting them against malware and other attacks.

Sucuri’s website application firewall protects you against DDOS, SQL injections, XSS JavaScript injections, comment and contact form spam.

However, if something crosses all those security barriers and somehow reaches your website, then Sucuri offers to clean up your website (for free).

If you already have a website affected with malware, then Sucuri will clean that up as well.

Winner:Sucuri – For combining website application firewall with monitoring, malware protection, and clean up services.

Conclusion

CloudFlare and Sucuri both offer protection against DDoS attacks on your website. CloudFlare does a little better in the content delivery network area.

Sucuri fares better in the overall features, better security monitoring, and lower prices. If you are using a CMS like WordPress, then Sucuri is what you need.

We hope this article helped you compare pros and cons of Sucuri vs CloudFlare. You may also want to see our list of 7 best WordPress backup plugins.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

Diverse Test-Automation Frameworks For React Native Apps

artificial intelligence 5291510 1920

Diverse Test-Automation Frameworks For React Native Apps

The bar is set high for today’s mobile apps. First, apps must meet the standard of quality that app markets expect. Secondly, mobile app users are very demanding. Plenty of alternatives are available to download, so users will not tolerate a buggy app. Because mobile apps have become such a crucial part of people’s lives, users won’t be shy about sharing their love or hate for an app — and that feedback gets in front of millions of users in seconds.

Further Reading on Smashing: Link

Mobile is more important than ever6. But getting an app just right, getting it to work across all possible devices, with different OS versions, display resolutions, chipsets and other hardware characteristics, and making the user experience smooth across all possible configurations, is a challenging task.

7
The increase in mobile platforms and device fragmentation. (View large version8)

A ton of great technologies, tools, frameworks and open-source components are available for building native mobile apps. What value does React Native9 bring to the scene, and how can we make sure that apps built with it are well received by their target audiences?

In this article, we’ll look at what’s available for testing React Native apps10. First, I’ll explain some key features of React Native, before looking at how to implement these tests. Secondly, I’ll categorize testing methods and frameworks on three levels (unit, integration, functional), providing examples for each. Finally, I’ll provide simple examples of how to implement tests using the most popular open-source test-automation frameworks for functional app testing.

The Basic Architecture Of React Native Apps

It all got started with React11 more than three years ago, when Facebook introduced its framework to web developers. It was bound to be popular, not just because it was authored and developed by Facebook, but because of the capabilities it provided to web developers — and especially how it changed the way we build apps.

The concept of this type of “learn once, write anywhere” framework wasn’t new, though; we had already seen JavaScript libraries do similar things (Sencha12, PhoneGap13 and Appcelerator14, among others), but something was better about React that had an impact on developers’ habits and how they break down an application’s UI into discrete components.

React Native does not use the DOM for rendering. Instead, it renders with native UI views, which means you are using the native components provided by the operating system. This sort of product-creation flow, where you replace the DOM API with a more declarative API, gives developers a more cohesive and simplified level of abstraction15.

React Native development flow on Android and iOS16
React Native development flow on Android and iOS. (Image: Testdroid676351422917) (View large version18)

The key thing about React Native is that it brings the React programming model19 to mobile apps, development and testing. It doesn’t actually work directly as a cross-platform tool or framework, but it accelerates the trend of building mobile apps on this new platform. And that’s one of the cornerstones of what makes React Native so powerful, easy to learn and easy to write on this new platform.

The major difference, as well as advantage, of native mobile versus the web is that, instead of running a JavaScript-based implementation in a browser and exposing HTML elements, we are now relying on the embedded JavaScriptCore in apps20, which get platform-specific UI elements.

Test Automation On Different Levels: Unit, Integration, Component And Functional

All mobile software is built using composition. On Android and iOS21, this means that small software components are arranged together to form larger, higher-level components with greater functionality, until the goals and requirements of the application have been met. A good testing practice is to run tests that cover functionality at all levels of the composition.

In this article, I’ll cover test methods and automation frameworks at three levels. The primary focus is on the highest level, functional testing, but React Native apps can be tested — and testing can be automated — on at least the following levels:

  • Unit testing

    This could be even as basic as testing JavaScript objects and methods on the component level.
  • Component testing

    Each component can be tested either visually or functionally. ReactTestUtils2322 provides a simple framework for testing React components.
  • Integration testing

    Integration testing comes next and is a phase when a group of different units are typically tested as an entity.
  • Functional testing

    Functional testing is a type of black-box testing that focuses on user requirements and interactions, and it covers all underlying software, all user interaction and the application as an entity.

In addition to ReactTestUtils2322, React Native provides useful unit-testing methods24, but none of them thoroughly cover the application’s actual logic. Therefore, mobile apps built on React Native benefit more from functional UI testing. A variety of functional test-automation frameworks25 are available, and we’ll look at few of the most popular ones in this article.

While unit testing can be done at the component level, functional test automation provides better capabilities for testing the larger entities in a React Native app. With React Native, component logic unit testing can be done in isolation, using traditional JavaScript libraries and forcing React Native to return regular components instead of native ones. With functional test-automation frameworks, UI components are part of the app and are easy to test as a whole.

I’ll separate these frameworks into cross-platform frameworks26 and platform-specific frameworks4027, as illustrated in the picture below.

Different test-automation options for React Native apps28
Different test-automation options for React Native apps. (Image: Testdroid676351422917) (View large version30)

The best part of React Native apps is that they are fully native for both major mobile platforms (Android and iOS). This means we get more frameworks, tools and native methods for testing purposes. We’ll look at functional test-automation frameworks in the section below titled “Using Functional Test-Automation Frameworks With React Native Apps31.”

Let’s start with unit-testing capabilities32, using a JavaScript test to illustrate.

Unit Testing With Jest and Jasmine Link

By default, React Native provides Jest33 tests for unit testing, and this works for both Android and iOS. Currently, test coverage isn’t perfect, but according to Facebook, more unit-testing capabilities will be introduced in React Native, and users can already build their own.

Jest uses the Jasmine behavior-driven framework34 as the basis for testing JavaScript code. Every test case starts from a describe() function call, similar to how JUnit uses the TestCase class. The describe() function takes two parameters: the description and title of the test case, and the function to be executed. The it() function includes all of the test steps and (similar to JUnit) provides a series of expect() functions.

Here is an example of a Jasmine test script for a player application.

describe("Player", function() { var player; var song; beforeEach(function() { player = new Player(); song = new Song(); }); it("should be able to play a song", function() { player.play(song); expect(player.currentlyPlayingSong).toEqual(song); //demonstrates use of custom matcher expect(player).toBePlaying(song); }); describe("when song has been paused", function() { beforeEach(function() { player.play(song); player.pause(); }); it("should indicate the song is paused", function() { expect(player.isPlaying).toBeFalsy(); // demonstrates use of 'not' with a custom matcher expect(player).not.toBePlaying(song); }); it("should be possible to resume", function() { player.resume(); expect(player.isPlaying).toBeTruthy(); expect(player.currentlyPlayingSong).toEqual(song); }); }); // demonstrates use of spies to intercept and test method calls it("tells the current song whether the user has made it a favorite", function() { spyOn(song, 'persistFavoriteStatus'); player.play(song); player.makeFavorite(); expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true); }); //demonstrates use of expected exceptions describe("#resume", function() { it("should throw an exception if song is already playing", function() { player.play(song); expect(function() { player.resume(); }).toThrow("song is already playing"); }); }); });

This basic example shows how Jasmine can be used to test the functionality of an app, but it keeps the focus on method-level testing. In addition, React Native provides some basic capabilities for testing integrated components. This works for both native and JavaScript components and enables communication between them via a bridge.

Integration Testing Link

At the moment, integration tests highlighted in the React Native community are available only for iOS and are very limited in their ability to test components. The communication goes through the bridge and requires both native and JavaScript components. For this functionality, two components are available to implement customized integration tests, RCTestRunner35 and RCTestModule36.

A basic Objective-C example for building a test skeleton of an iOS app would start like this:

@implementation ExampleTests { RCTTestRunner *_runner; } - (void)setUp { [super setUp]; _runner = RCTInitRunnerForApp(@"IntegrationTestHarnessTest", nil); } - void()testExampleTests { [_runner runTest:_cmd module:@"ExampleTests"] } @end

However, there are other ways to run integration testing and to extend it to Android and iOS. A good alternative for running both unit and integration tests is Mocha37, which provides a feature-rich JavaScript test framework that runs on Node.js38. Mocha also provides behavior-driven development (BDD), test-driven development (TDD) and QUnit interfaces for testing.

For functional UI testing, I’ll be covering the most prominent and most used test-automation frameworks, including Appium, Calabash, XCTest and a few others.

Using Functional Test-Automation Frameworks With React Native Apps

To streamline the app development process and to maximize testing coverage, we have numerous open-source test-automation frameworks to choose from.

The best choice — if your app will run on several OS platforms — is a framework that supports multiple platforms39 and provides a robust foundation for test automation. In mobile, the term “cross-platform” refers to a framework that provides the same API, tools and capabilities for both Android and iOS.

In addition, a range of great platform-specific frameworks4027 are available. Naturally, each framework has been built for a particular platform and, in most cases, is easier to adopt for that platform. In addition to Appium and Calabash, I’ll cover four platform-specific frameworks in this article: Robotium and Espresso for Android, and XCTest and EarlGrey for iOS.

Different test-automation frameworks for functional UI testing41
Different test-automation frameworks for functional UI testing. (Image: Testdroid676351422917) (View large version43)

When it comes to test automation, bear in mind that apps built with React Native are fully native on both iOS and Android; hence, functional test-automation frameworks will work fine with them.

The example I’ll use with each framework is an implementation of a very basic radio button UI.

<Radio onSelect={this.onSelect.bind(this)} defaultSelect={this.state.optionSelected - 1}> <Option color="black" selectedColor="#000000"> <Item title="First option" description="First radio button"/> </Option> <Option color="black" selectedColor="#000000"> <Item title="Second option" description="Second radio button"/> </Option> <Option color="black" selectedColor="#000000"> <Item title="Third option" description="Third radio button"/> </Option> </Radio> 

The test snippet included in each framework section below shows how the test script deals with each UI element and how clicks and other user inputs are handled. The purpose of the examples is not to provide step-by-step instructions, but rather to compare examples and show what is available for test automation today and what programming languages can be used for testing.

Cross-Platform Frameworks

As stated, React Native is not actually a cross-platform framework, but adoption of it across other platforms is easy. In the next two sections, we’ll go through two popular cross-platform test-automation frameworks for mobile testing and mobile test automation.

Appium Link

Appium44 is an open-source test-automation framework, with an inspection tool that works well for native, hybrid and mobile web apps. It uses JSONWireProtocol45 internally to interact with iOS and Android apps, using Selenium WebDriver46. Because of this, Appium works extremely well for the mobile web as well, and the use cases are very similar if Selenium is used for web testing.

In fact, Appium has been a rising star in mobile test automation47 in the last year. Originally, it was built to provide cross-platform support for both major platforms, Android and iOS.

Being cross-platform means that the framework and its scripts work exactly the same on both platforms. In addition, Appium provides fantastic programming language support48 — developers can write tests using their favorite language (for example, Java, Ruby, Python, C#), tools and environment. It’s also easy to get started, to create and maintain reusable tests, and to execute those tests on real physical devices.

When it comes React Native-powered apps, JavaScript isn’t necessarily required; tests can be written in any language. For example, Appium scripts can look like this:

driver.findElement(By.id("com.example.app:id/radio0")).click(); driver.findElement(By.id("com.example.app:id/radio1")).click(); driver.findElement(By.id("com.example.app:id/radio2")).click(); driver.findElement(By.id("com.example.app:id/editText1")).click(); driver.findElement(By.id("com.example.app:id/editText1")).sendKeys("Simple Test"); driver.findElement(By.name("Answer")).click(); // or alternatively like this: driver.findElement(By.id("com.example.app:id/button1")).click();

So, how do these WebDriver functions access apps running on devices? Basically, Appium starts a test script on the device or emulator, which then creates a server and listens for commands from the main Appium server. It is the same as the Selenium server, which gets HTTP requests from Selenium client libraries49. The difference between Android and iOS is illustrated in the picture below:

How Appium works on Android and iOS50
How Appium works on Android and iOS. (Image: Testdroid676351422917) (View large version52)

With iOS, Selenium WebDriver gets a command from the Appium script (for example, click()) and sends it in the form of JSON via an HTTP request to the Appium server53. Appium knows the automation context and sends this command to the Instruments command server, which waits for the Instruments command client to pick it up and execute it with bootstrap.js in the iOS Instruments environment. Once the command is executed, the Instruments command client sends the message back to the Appium server, which logs everything related to the command in its console. This cycle keeps going until the test script has finished.

On Android, things work almost the same way, except that the frameworks used are Selendroid and UiAutomator54. In short, Appium translates WebDriver commands to UiAutomator (API level 17 or higher) or Selendroid (API level 16 or lower) commands. On a physical device, bootstrap.jar launches a TCP server that gets commands from a TCP client. The process is similar on iOS.

If you are interested in getting started with Appium, plenty of material is available, including step-by-step instructions55 and Appium tutorials56.

Calabash Link

Another great cross-platform testing framework is Calabash57, which enables anyone to write tests for mobile applications. The main difference is that Calabash tests are written in Cucumber58. The idea behind using this sort of language for tests is awesome: The test itself is like a specification, and all tests are simple and easy to read yet executable by the automation system.

Compared to Appium, Calabash provides an easier way to create cross-platform tests for Android and iOS. This is due to the straightforward vocabulary and specification-oriented language, which makes Calabash tests identical on both platforms. The actual tests are written in Gherkin59 and run in Cucumber.

Because of these capabilities, the differences between Calabash working on Android60 and on iOS61 applications are minor. Again, there is no implication for React Native apps because all components and user interfaces are fully native to these platforms.

Calabash on Android and iOS62
Calabash on Android and iOS. (Image: Testdroid676351422917) (View large version64)

The basic testing and test-creation flow, however, remains the same. Calabash (and Gherkin) tests comprise features, scenarios and steps. The recommended approach is to complete the highest-level descriptions first: features, followed by scenarios and then the actual steps. A good rule of thumb is to create Calabash features65 first.

Calabash features, scenarios and steps66
Calabash features, scenarios and steps. (Image: Testdroid676351422917) (View large version68)

The example below shows how our application and its UI components (radio buttons, text field and button) would be implemented in Calabash:

Feature: Answer the question feature Scenario: As a valid user, I want to answer app question, I wait for text "What is the best way to test application on a hundred devices?" Then I press radio button 0 Then I press radio button 1 Then I press radio button 2 Then I enter text "Simple Test" into field with id "editText1" Then I press view with id "Button1"

Steps usually begin with one of the keywords given, then, when, and or but. However, they don’t have to; they can use * instead.

Calabash is also widely used by non-developers, and it can be used for product specifications and documentation due to its easy-to-understand language and logic. Eventually, the features and scenarios are wrapped in Ruby code.

Setting up Calabash69 and starting to work with it are easy. If you have Bundler70 and Ruby (or rbenv) installed, just hit these few lines in your console, and a Calabash environment will soon be set up:

$ gem install calabash-android $ gem install calabash-cucumber

This will take care of installing Calabash-Android and Calabash-iOS, and your journey with test automation can begin.

Platform-Specific Frameworks

When it comes to automating tests on Android and iOS apps, there are certain advantages to using platform-specific frameworks over cross-platform ones. For instance, some frameworks are built closely to SDKs and IDEs71, which are readily available while an application is under development. Let’s look at a few examples of these types of frameworks for Android and iOS.

Robotium and ExtSolo (Android) Link

Robotium72 was one of the first testing frameworks to work for native and hybrid Android apps. The UI tests created with Robotium enable functional, system and user-acceptance tests for Android apps, spanning and handling multiple Android activities. In fact, Robotium provides support for very early versions of Android, starting from API level 8.

Recently, Robotium was extended with the ExtSolo library73, which provides various useful features for app testing:

  • automatic scaling of x and y clicks for any display resolution;
  • multi-path drags;
  • automatic screenshot capture at moment of test failure;
  • mock locations (GPS coordinates);
  • change of Android device language;
  • control of Wi-Fi connection;

With Java code, tests are easy to build using any Java SDK and IDE. The primary function used in this example is findViewById, which finds a view that is identified by the id attribute. The UI element could be also identified by a name, class or some other attribute. Our code example with an id attribute would look like this:

solo.clickOnView(solo.findViewById("com.example.app:id/radio0")); solo.clickOnView(solo.findViewById("com.example.app:id/radio1")); solo.clickOnView(solo.findViewById("com.example.app:id/radio2")); solo.enterText((EditText) solo.findViewById("com.example.app:id/editText1"), "Simple Test"); solo.clickOnView(solo.findViewById("com.example.app:id/button1"));

Robotium here is trying to locate UI elements based on the id, description and other characteristics. Unfortunately, this isn’t always the best approach and does not necessarily work well with webview components. However, with the help of the ExtSolo library, users can define clicks and other interactions on UI elements that scale with the resolution. Also, hardcoding coordinates is possible, and these scale when the display resolution changes.

If you are using Robotium, then getting started with Robotium ExtSolo is easy and effortless. Just clone the repository for yourself and build the library:

$ git clone https://github.com/bitbar/robotium-extensions $ ant clean instrument

After this, place the recently built .jar file in the libs folder in your Android Studio project, and make sure your project is linked to it. All of these great additional features and services are now in your workspace.

Espresso (Android) Link

The Espresso74 testing framework provides APIs for writing UI tests to simulate user interactions for an Android app. The Espresso API75 is lightweight and provides three main components: viewMatchers, viewActions and viewAssertions.

The beauty of Espresso is that it provides automatic synchronization of test methods and UI elements that are being tested. For example, if the test script wants to press a button but the button isn’t visible on the screen yet, it will wait until this button can be pressed (i.e. it is visible and a click can happen). This makes test execution very fast because no test scripts need to include any sleep or wait commands. Also, developers do not need additional logic to handle timing-related issues.

// R class ID identifier for radio buttons onView(withId(R.id.radio0)).perform(click()); onView(withId(R.id.radio1)).perform(click()); onView(withId(R.id.radio2)).perform(click()); onView(withId(R.id.EditText1)).perform(click()); // Instead of R, we use getIdentifier onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.example.app:id/EditText1", null, null))).perform((typeText("Simple Test"))); onView(withId(getInstrumentation().getTargetContext().getResources() .getIdentifier("com.example.app:id/Button1", null, null))).perform(click());

Espresso has its own pros and cons, and due to the lightweight API, not many additional services or function calls are available to developers. For instance, you must use alternative methods to take screenshots, manage tests, output test results and more.

At Google IO 201676 Google introduced Espresso Test Recorder as an integral part of Android Studio. While the feature is not yet available, it will definitely be worth the wait.

XCTest and KIF (iOS) Link

XCTest77 is tightly coupled with Xcode but is still usable with both real iOS devices and simulators. XCTest allows developers to write tests for components at any level and also provides a framework for UI testing capabilities. XCTest tests are grouped into subclasses of XCTestCase78. Writing any tests with XCTest should be trivial to iOS developers because XCTest is fully compatible with both Objective-C and Swift.

KIF79 (short for “keep it functional”) is an iOS integration test framework that is closely related to and that uses XCTest test targets. KIF tests can be executed directly in XCTestCase or any subclass. KIF allows for easy automation of iOS applications by leveraging the accessibility attributes that the OS makes available to those with visual disabilities.

Let’s see how our UI components would look with Objective-C:

- (void)testClicksOnRadioButtons { [tester tapViewWithAccessibilityLabel:@”Radio1”]; [tester tapViewWithAccessibilityLabel:@”Radio2”]; [tester tapViewWithAccessibilityLabel:@”Radio3”]; [tester enterText:@”Simple Test” intoViewWithAccessibilityLabel:@”editText1”]; [tester tapViewWithAccessibilityLabel:@”Answer”]; }

Alternatively, with Swift, the test would look as simple as this:

testClicksOnRadioButtons() { let app = XCUIApplication() app.radiobutton[0].tap() app.radiobutton[1].tap() app.radiobutton[2].tap() app.staticTexts[“Simple Test”] app.button[0].tap() }

Note that this high-level pseudo-code requires additional code in order to fully function. If you are looking for more information on XCTest and generally on using Xcode testing capabilities, Apple has you covered80.

EarlGrey (iOS) Link

It was just earlier this year when Google open-sourced81 its functional iOS app-testing framework, named EarlGrey. Being used internally by Google, it has worked relatively well with native iOS apps — YouTube, Google Calendar, Google Photos, Google Play Music, to name a few — and has sparked some serious interest. To get started with EarlGrey82, you’ll need the Xcode environment installed and basic knowledge of iOS development.

There are a lot of similarities between EarlGrey and Espresso (yes, both are developed by Google), and their characteristics make both frameworks work and execute tests quickly. Similar to Espresso, EarlGrey tests automatically wait for events (animations, network requests, etc.) before trying to interact with the UI. This makes writing tests easier because developers do not need to worry about sleep or wait commands. In addition, the code itself is easier to maintain because it provides procedural descriptions of the test steps.

EarlGrey also contains matchers that are available from the GREYMatchers83 class. The documentation recommends using UI elements with the accessibility parameters. To identify UI elements, developers can use grey_accessibilityID() or grey_accessibilityLabel().

- (void)testBasicSelectionAndAction { [[EarlGrey selectElementWithMatcher::grey_accessibilityID(@"ClickHere")] performAction:grey_tap()]; // Example of long press with EarlGrey matchers - (void)testLongPress { [[EarlGrey selectElementWithMatcher::grey_accessibilityLabel(@"Box")] performAction:grey_longPressWithDuration(0.5f)]; [[EarlGrey selectElementWithMatcher::grey_accessibilityLabel(@"One Long Press")] assertWithMatcher:grey_sufficientlyVisible()]; // Example of multi-select, visible click on items - (void)testCollectionMatchers { id visibleSendButtonMatcher = grey_allOf(grey_accessibilityID(@"Box"), grey_sufficientlyVisible(), nil); [[EarlGrey selectElementWithMatcher:visibleSendButtonMatcher] performAction:grey_tap()]; }

Similar to XCTest, our radio button implementation isn’t that straightforward, and buttons for XCTest should be defined as iOS-supported UIElements to enable clicks and user interactions.

Conclusion

We’ve covered the basics of React Native applications and how they can be tested using various methods and frameworks. This comes up quite often, but the industry standards for mobile test automation at the functional UI level will work on React Native apps just as they do with any other native apps. The test-automation frameworks we’ve covered here are widely used for native mobile apps, hybrid apps, the mobile web as well as React Native apps.

In summary, determining the programming language that a mobile application is built on is not critical because it won’t have any influence on the test-automation frameworks that it can be tested with. As discussed, plenty of powerful test-automation frameworks are available today, which React Native apps will work with when wrapped as an APK or IPA.

What are you using for React Native app testing? Weigh in with a comment below!

(al, ml)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2016/04/the-beauty-of-react-native-building-your-first-ios-app-with-javascript-part-1/
  2. 2 https://www.smashingmagazine.com/2016/04/consider-react-native-mobile-app/
  3. 3 https://www.smashingmagazine.com/2015/01/basic-test-automation-for-apps-games-and-mobile-web/
  4. 4 https://www.smashingmagazine.com/2016/03/server-side-rendering-react-node-express/
  5. 5 https://www.smashingmagazine.com/2015/05/client-rendered-accessibility/
  6. 6 http://www.smartinsights.com/mobile-marketing/mobile-marketing-analytics/mobile-marketing-statistics/
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/06/01-fragmentation-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/06/01-fragmentation-opt.png
  9. 9 https://facebook.github.io/react-native/docs/
  10. 10 http://testdroid.com/tech/testing-react-native-apps-on-android-and-ios
  11. 11 https://code.facebook.com/projects/176988925806765/react/
  12. 12 https://www.sencha.com/
  13. 13 http://phonegap.com/
  14. 14 http://www.appcelerator.com/
  15. 15 https://www.smashingmagazine.com/2016/04/the-beauty-of-react-native-building-your-first-ios-app-with-javascript-part-1/
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/06/02-react-native-architecture-opt.png
  17. 17 http://testdroid.com
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/06/02-react-native-architecture-opt.png
  19. 19 https://www.smashingmagazine.com/2016/04/consider-react-native-mobile-app/
  20. 20 http://trac.webkit.org/wiki/JavaScriptCore
  21. 21 https://code.facebook.com/posts/1189117404435352/react-native-for-android-how-we-built-the-first-cross-platform-react-native-app/
  22. 22 http://facebook.github.io/react/docs/test-utils.html
  23. 23 http://facebook.github.io/react/docs/test-utils.html
  24. 24 https://facebook.github.io/react-native/docs/testing.html
  25. 25 https://www.smashingmagazine.com/2015/01/basic-test-automation-for-apps-games-and-mobile-web/#different-ways-to-automate-mobile-testing
  26. 26 #cross-platform-frameworks
  27. 27 #platform-specific-frameworks
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/06/03-testing-react-native-opt.png
  29. 29 http://testdroid.com
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/06/03-testing-react-native-opt.png
  31. 31 #test-automation-frameworks
  32. 32 https://facebook.github.io/react-native/docs/testing.html#jest-tests
  33. 33 http://facebook.github.io/jest/
  34. 34 http://jasmine.github.io/
  35. 35 https://github.com/facebook/react-native/blob/master/Libraries/RCTTest/RCTTestRunner.h
  36. 36 https://github.com/facebook/react-native/blob/master/Libraries/RCTTest/RCTTestModule.h
  37. 37 https://mochajs.org/
  38. 38 https://nodejs.org/en/
  39. 39 #cross-platform-frameworks
  40. 40 #platform-specific-frameworks
  41. 41 https://www.smashingmagazine.com/wp-content/uploads/2016/06/04-test-automation-frameworks-opt.png
  42. 42 http://testdroid.com
  43. 43 https://www.smashingmagazine.com/wp-content/uploads/2016/06/04-test-automation-frameworks-opt.png
  44. 44 http://appium.io/
  45. 45 https://code.google.com/p/selenium/wiki/JsonWireProtocol
  46. 46 http://docs.seleniumhq.org/projects/webdriver/
  47. 47 http://testdroid.com/news/37-things-you-should-know-about-appium
  48. 48 http://testdroid.com/news/appium-tip-1-how-to-get-started-setup-and-run-your-first-tests
  49. 49 https://www.smashingmagazine.com/2015/01/basic-test-automation-for-apps-games-and-mobile-web/#appium-executing-tests-on-real-devices-on-a-cloud-service
  50. 50 https://www.smashingmagazine.com/wp-content/uploads/2016/06/05-appium-architecture-opt.png
  51. 51 http://testdroid.com
  52. 52 https://www.smashingmagazine.com/wp-content/uploads/2016/06/05-appium-architecture-opt.png
  53. 53 http://testdroid.com/tech/how-to-use-selenium-for-cross-browser-testing-on-mobile-devices
  54. 54 http://testdroid.com/news/appium-tip-16-finding-elements-with-appium-automation-engine
  55. 55 https://blogs.technet.microsoft.com/antino/2014/09/22/how-to-set-up-a-basic-working-appium-test-environment/
  56. 56 http://testdroid.com/news/37-things-you-should-know-about-appium
  57. 57 https://github.com/calabash
  58. 58 https://cucumber.io/
  59. 59 https://github.com/cucumber/cucumber/wiki/Gherkin
  60. 60 https://github.com/calabash/calabash-android
  61. 61 https://github.com/calabash/calabash-ios
  62. 62 https://www.smashingmagazine.com/wp-content/uploads/2016/06/06-calabash-diagram-opt.png
  63. 63 http://testdroid.com
  64. 64 https://www.smashingmagazine.com/wp-content/uploads/2016/06/06-calabash-diagram-opt.png
  65. 65 http://testdroid.com/tech/creating-the-right-calabash-tests
  66. 66 https://www.smashingmagazine.com/wp-content/uploads/2016/06/07-calabash-features-scenarios-steps-opt.png
  67. 67 http://testdroid.com
  68. 68 https://www.smashingmagazine.com/wp-content/uploads/2016/06/07-calabash-features-scenarios-steps-opt.png
  69. 69 http://testdroid.com/tech/how-to-setup-and-get-started-with-calabash
  70. 70 http://bundler.io/
  71. 71 http://android-developers.blogspot.fi/2016/05/android-studio-22-preview-new-ui.html
  72. 72 https://github.com/RobotiumTech/robotium
  73. 73 https://github.com/bitbar/robotium-extensions
  74. 74 https://google.github.io/android-testing-support-library/docs/espresso/index.html
  75. 75 https://google.github.io/android-testing-support-library/docs/espresso/cheatsheet/
  76. 76 https://www.youtube.com/watch?v=isihPOY2vS4
  77. 77 https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/testing_with_xcode/
  78. 78 https://developer.apple.com/library/tvos/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/04-writing_tests.html
  79. 79 https://github.com/kif-framework/KIF
  80. 80 https://developer.apple.com/library/tvos/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/03-testing_basics.html
  81. 81 http://google-opensource.blogspot.com/2016/02/earlgrey-ios-functional-ui-testing.html
  82. 82 http://testdroid.com/news/how-to-get-started-with-earlgrey-ios-functional-ui-testing-framework
  83. 83 https://github.com/google/EarlGrey/blob/master/EarlGrey/Matcher/GREYMatchers.m
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

How to Delay Posts From Appearing in WordPress RSS Feed

artificial intelligence 5291510 1920

Recently, one of our readers asked if it’s possible to delay posts from appearing in the WordPress RSS feed? Delaying posts in your RSS feed can save you from accidental publishing and beat content scrapers in SEO. In this article, we will show you how to delay post from appearing in WordPress RSS feed.

Why Delay Feed in WordPress?

Sometimes you may end up with a grammar or spelling mistake in your article. The mistake goes live and is distributed to your RSS feed subscribers. If you have email subscriptions on your WordPress blog, then those subscribers will get it as well.

Spelling mistakes go live to your RSS feed subscribers

By adding a delay between your RSS feed and your live site, you get a little time window to catch an error on a live site and fix it.

RSS feeds are also used by content scraping websites. They use it to monitor your content and copy your posts as soon as they appear live.

If you have a new website with little authority, then a lot of times these content scrapers may end up beating you in the search results.

Content scrapers use RSS feeds to auto-publish your posts

By delaying an article in the feed, you can give search engines enough time to crawl and index your content first.

Having said that, let’s see how to easily delay posts from appearing in WordPress RSS feed.

Delaying Posts in WordPress RSS Feed

This method requires you to add little code into WordPress. If this is your first time adding code manually, then take a look at our beginner’s guide on pasting snippets from web into WordPress.

You need to add the following code to your theme’s functions.php file or in a site-specific plugin.

 function publish_later_on_feed($where) { global $wpdb; if ( is_feed() ) { // timestamp in WP-format $now = gmdate('Y-m-d H:i:s'); // value for wait; + device $wait = '10'; // integer // http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_timestampdiff $device = 'MINUTE'; //MINUTE, HOUR, DAY, WEEK, MONTH, YEAR // add SQL-sytax to default $where $where .= " AND TIMESTAMPDIFF($device, $wpdb->posts.post_date_gmt, '$now') > $wait "; } return $where; } add_filter('posts_where', 'publish_later_on_feed'); 

This code checks to see if a WordPress feed is requested. After that it sets the current time and the time you want to add as delay between post’s original date and the current time.

After that it adds the timestamp difference as the WHERE clause to the original query. The original query will now only return the posts where timestamp difference is greater than the wait time.

In this code we have used 10 minutes as $wait or delay time. Feel free to change that into any number of minutes you want. For example, 60 for 1 hour or 120 for two hours.

We hope this article helped you learn how to easily delay posts from appearing in WordPress RSS feed. You may also want to see our guide on how to show content only to RSS subscribers in WordPress.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

I Contributed To An Open-Source Editor, And So Can You

artificial intelligence 5291510 1920

I Contributed To An Open-Source Editor, And So Can You

A few months ago, Jason Grigsby’s post about autocompletion in forms1 made the rounds. I loved the idea of allowing users to fill in their credit card details by taking a picture of their card. What I didn’t love was learning all of the possible values for autofill by heart2. I’m getting lazy in my old age.

Lately, I’ve gotten spoiled from using an editor that does intelligent autocompletion for me, something that in the past only massive complex IDEs offered. Opening my editor of choice, I created an input element and added an autocomplete attribute, only to find that the code completion offered me the state of on or off. Disappointing.

What I wanted was the following:

All possible values for autocomplete offered by this editor

The great thing about our development environments these days is that we build the tools we use in the technologies that we use them to write. Yes, this sounds confusing — we’ve reached code Inception. Node.js3 allows us to run JavaScript on the back end, and with Electron4 we can create installable applications for all platforms using HTML, CSS and JavaScript.

Atom5 was the first editor to use this technology and to allow for contributions by being open source, closely followed by Microsoft’s Visual Studio Code6.

Almost all of the other editors in use allow us to write extensions, plugins or snippet collections in various formats. I deliberately didn’t want to write a plugin or extension, but rather wanted to add this functionality to the core of the editor. Plugins, extensions and snippets have their merits; for example, they are easy to update. The problem is that they need to be found and installed per user. I considered autocompletion too important and wanted to hack the editor itself instead.

Both Atom and Visual Studio Code are available on GitHub and come with instructions on how to extend them. The challenge is that this can feel daunting. I’m here today to show you that it isn’t as tough as you might think. Visual Studio Code is my current editor, and it features amazing autocompletion. That’s what I wanted to tackle.

Extensible and customizable tools are nothing new. Most of what we use can be extended in one way or another, whether in the form of add-ons, plugins or specialist languages. The first editor I used in anger was Allaire and Macromedia’s HomeSite7, which had funky languages like VTML8, WIZML9 and JScript, the Windows version of JavaScript at the time. I wrote a lot of extensions and toolbars for that editor, which very much boosted the productivity of my company back then.

Thankfully, these days, companies understand that offering specialist languages is time wasted, when the web stack has grown to become much more interesting to build applications with.

If you download Visual Studio Code now, you will see that my autocomplete feature is a part of it. And here is how I did that.

1. Complain Link

My first step was to go to Visual Studio Code’s GitHub repository10 and file an issue11 requesting this feature for the editor. This could also be your final step if you don’t want to do it yourself. Someone else who is looking for something to do for the project might find your complaint and tackle it for you. In my case, I wanted to find out more.

2. Fork The Code Link

Instead of just filing an issue, I went to the GitHub repository and forked the code. I used my personal account for this. You don’t need to be affiliated with Microsoft or get added to a special group. The repository is public and open. Everybody is welcome. There is even a code of conduct for contributions12, which means that people should be playing nice. I downloaded the code to my hard drive and followed the instructions on how to build the editor locally.

3. Get The Development Workflow In Place Link

Visual Studio Code is written in Node.js and TypeScript. The development flow starts with a script provided by the team, which gives me a development version of Visual Studio Code running next to the one I am using. A script running on the command line ensures that my changes are captured and that every time I save my code, the development version of the editor restarts and I can test the changes. All of this is nicely documented, from building and running the code from source13 to setting up the development workflow14. And it is independent of platform — you get instructions for Windows, Linux and Mac OS X.

You can see what this looks like on my computer in the following screenshot. The large-view editor (1) is the one I use to code the other; the one on the right (3) is the development edition; and on the bottom (2) is the script creating the new version of the development edition. Writing an editor in an editor does feel odd, but you get used to it.

Figure 215
(View large version16)

Don’t get discouraged if all of this doesn’t work for you on the first go. I hit a few snags and had to turn to Google and StackOverflow for solutions. The Node.js community was very helpful.

4. Write The Functionality Link

Next, I was ready to go all in and use TypeScript to write some clever code. I understood that this is where a lot of people throw in the towel, considering it too tough to continue.

My biggest issue was that I had no idea where to begin with this functionality. So, I did what we all do: I did a full text search for autocomplete in the whole project. Using this highly scientific approach, I found an htmlTags.ts file17 full of tag definitions and arrays of attribute values. I looked up the input element and found this:

input: new HTMLTagSpecification( nls.localize('tags.input', 'The input element represents a typed data field, usually with a form control to allow the user to edit the data.'), ['accept', 'alt', 'autocomplete:o', 'autofocus:v', 'checked:v', 'dirname', 'disabled:v', 'form', 'formaction', 'formenctype:et', 'formmethod:fm', 'formnovalidate:v', 'formtarget', 'height', 'inputmode:im', 'list', 'max', 'maxlength', 'min', 'minlength', 'multiple:v', 'name', 'pattern', 'placeholder', 'readonly:v', 'required:v', 'size', 'src', 'step', 'type:t', 'value', 'width']), 

That autocomplete:o looked interesting, so I checked where o is defined. Here’s what I found:

var valueSets: IValueSets = { … o: ['on', 'off'], … } 

That looked like what was happening when I added an autocomplete attribute. To change that, I went to the standard definition of possible autocomplete values18 and copied them.

I created a new value set named inputautocomplete and pasted in the values:

var valueSets: IValueSets = { … inputautocomplete: ['additional-name', 'address-level1', 'address-level2', 'address-level3', 'address-level4', 'address-line1', 'address-line2', 'address-line3', 'bday', 'bday-year', 'bday-day', 'bday-month', 'billing', 'cc-additional-name', 'cc-csc', 'cc-exp', 'cc-exp-month', 'cc-exp-year', 'cc-family-name', 'cc-given-name', 'cc-name', 'cc-number', 'cc-type', 'country', 'country-name', 'current-password', 'email', 'family-name', 'fax', 'given-name', 'home', 'honorific-prefix', 'honorific-suffix', 'impp', 'language', 'mobile', 'name', 'new-password', 'nickname', 'organization', 'organization-title', 'pager', 'photo', 'postal-code', 'sex', 'shipping', 'street-address', 't].sort()el-area-code', 'tel', 'tel-country-code', 'tel-extension', 'tel-local', 'tel-local-prefix', 'tel-local-suffix', 'tel-national', 'transaction-amount', 'transaction-currency', 'url', 'username', 'work'], … } 

I then went to all of the definitions of elements that support autocomplete and replaced the o with my own inputautocomplete:

input: new HTMLTagSpecification( nls.localize('tags.input', 'The input element represents a typed data field, usually with a form control to allow the user to edit the data.'), ['accept', 'alt', 'autocomplete:inputautocomplete' … ]), 

I saved my changes; the script rebuilt the editor; I tried the development version of the editor; and autocomplete worked the way I wanted it to.

5. Send A Pull Request Link

That was that. I committed my changes to Git (inside Visual Studio Code19), went to GitHub and added a pull request. A few days later, I got a comment saying that my pull request went through and that what I did would be part of the next build.

6. Be Baffled Link

Frankly, I didn’t think this was amazing enough to warrant a change to the core of the editor. I just wanted to play around. Many of you might think the same about the work you do. And that’s the thing: We’re wrong. Contributing to open-source projects doesn’t require you to be an amazing developer. Nor does it require you to be famous or part of the in-crowd. Sometimes all you need to do is look at something, analyze it and find a way to improve it.

It is up to us to make the tools we use better. If you see a way to contribute to an open-source project, don’t be shy. You might be the one who comes up with an idea so obvious and so simple that others have overlooked it. You might be the one who makes something more usable or nicer to look at. We all have skills to contribute. Let’s do more of that.

(al)

Footnotes Link

  1. 1 https://cloudfour.com/thinks/autofill-what-web-devs-should-know-but-dont/
  2. 2 https://html.spec.whatwg.org/multipage/forms.html#autofill
  3. 3 https://nodejs.org/en/
  4. 4 http://electron.atom.io/
  5. 5 https://atom.io/
  6. 6 http://code.visualstudio.com/
  7. 7 https://en.wikipedia.org/wiki/Macromedia_HomeSite
  8. 8 https://en.wikipedia.org/wiki/VTML
  9. 9 http://www.ulitzer.com/node/41695
  10. 10 https://github.com/Microsoft/vscode/
  11. 11 https://github.com/Microsoft/vscode/issues/7142
  12. 12 https://opensource.microsoft.com/codeofconduct/
  13. 13 https://github.com/Microsoft/vscode/wiki/How-to-Contribute#build-and-run-from-source
  14. 14 https://github.com/Microsoft/vscode/wiki/How-to-Contribute#development-workflow
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/08/editor-large-preview-opt.png
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/08/editor-large-preview-opt.png
  17. 17 https://github.com/Microsoft/vscode/blob/master/src/vs/languages/html/common/htmlTags.ts
  18. 18 https://html.spec.whatwg.org/multipage/forms.html#autofill
  19. 19 https://code.visualstudio.com/docs/editor/versioncontrol
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Advertisement

How to Change the Author of a Post in WordPress

artificial intelligence 5291510 1920

Do you want to change the author of a post in WordPress? Sometimes you may need to display a different author, then the person who added the post in WordPress. You do not need to copy and paste the entire WordPress post with a different user account. In this article, we will show you how to easily change the author of a post in WordPress with just a few clicks.

Before You Change The Author of a Post in WordPress

If you just want to show your own name on a post written by some other user on your WordPress site, then you are ready to follow the instructions in this article.

On the other hand, if you want to show a different user as author, then first you need to make sure that this user exists on your WordPress site. See our guide on how to add new users and authors in WordPress for detailed instructions.

You can see and manage all users on your WordPress site by visiting the Users page when logged in with your WordPress administrator account.

Managing users in WordPress

If you just want to change the way your name is displayed, then check out our guide on how to add or change your full name in WordPress.

Having said that, let’s see how to quickly and easily change the author of a post in WordPress.

Changing Author of a WordPress Post

First you need to edit the post or page where you want to change the author name. On the post edit screen, you need to click on the Screen Options menu at the top right corner of the screen.

Screen Options button

This will show a flydown menu on the screen with a bunch of options. You need to check the box next to ‘Author’ option.

Enable author box on posts screen

After that, you need to scroll down on the post edit screen just below the post editor. You will see the Author box there.

Simply click on the drop down menu and select a different author.

Select an author for the post

Don’t forget to click on the Save Draft or Update button to save your changes.

Save your changes by clicking on update or save draft button

That’s all, you have successfully changed the author of a post in WordPress.

Quickly Change Author for Multiple Posts in WordPress

Changing author by editing a post is easy. However, if you have to do this for multiple posts, then it would take quite a lot of time to do that.

There is an easier way to quickly change author for multiple WordPress posts at once. To bulk update authors, click on the Posts menu from your WordPress admin bar. This will list all the posts on your WordPress site.

By default, WordPress shows 20 posts per page. If you want to display more posts, then you need to click on the Screen Options and change the number of posts you want to display.

Show more posts in admin area

Now you need to select the posts where you want to change the author. After selecting posts, select ‘Edit’ from ‘Bulk Actions’ dropdown menu and then click the ‘Apply Button’.

Bulk edit posts in WordPress

WordPress will now show you Bulk Edit metabox. You need to select the new author by clicking on the dropdown menu next to Author option.

Bulk edit author for multiple posts in WordPress

Don’t forget to click on the ‘Update’ button to store your changes.

That’s all, you have successfully changed the author for multiple WordPress posts without editing them individually.

We hope this article helped you learn how to change the author of a post in WordPress. You may also want to see our comparison of the best WordPress backup plugins.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

Five Rules Of App Localization In China: Money, Dating And App Store

artificial intelligence 5291510 1920

Five Rules Of App Localization In China: Money, Dating And App Store

I recently sat down with Rock Zhang, a Chinese mobile entrepreneur. Rock is my classmate from business school, and we have both worked in the mobile industry for a while. In an age when the best marketing is good product management, Rock knows how to make millions of Chinese users fall in love with an app. I asked him to share his thoughts on app localization.

1
Screenshots from the most popular apps on China’s iOS App Store show some of the best practices to follow when localizing for the Chinese mobile market. (Large preview2)

For me, China has always been a hard market to crack. I’ve marketed several mobile apps in European and US markets, and my apps have been featured many times in the App Stores in Russia, Israel, Spain, Germany and the US. But in China, our growth was stalling, and I don’t think we ever got a request for promotional artwork to be featured in the App Store. Truth be told, my “Asian expansion strategy” usually boiled down to hiring freelance translators through Elance to help me localize App Store pages in Chinese, Korean and Japanese.

Soh Nee, Kevin and Eriko, the freelancers who I hired to work on several apps, would log into Weblate, a free open-source web-based translation system, and translate strings of text for in-app content. To localize App Store pages, I would send them screenshot designs and copy via email and Google Docs. The translators charged per source word count. It was cheap, but the approach was faulty at best. I feel the pain of many app developers and marketers who want to branch out to the East (especially now that Chinese App Store revenue has doubled over the last year) but lack resources, money, knowledge or other.

I’m not an expert in China. I’m a marketer and a Belarus-born European transplant in California. But I wanted to put together some kind of a beginner’s guide to localization in China for someone in design, marketing and product management who, like me, has little knowledge of Asia but a lot of ambition to grow their product overseas. Together with my good friend Bruce Wong, who is a cultural expert in Asia and has years of design thinking and user experience grooming at Stanford’s d.school, we’ve done research and come up with several simple localization tips. And we consulted Rock Zhang, the industry expert, to sketch out a general overview of the mobile market in China.

In this article, we’ll look at the top Chinese apps, including local market leaders such as Dianping, the Yelp of China, and the few US apps that are successful in China, such as the NBA app and Uber, and discuss how content, graphics and tone can make or break an app’s success.

Chinese App Market: Android Versus iOS Link

As tantalizing as it sounds for marketers to tap into the pool of well over 500 million smartphone users, China has historically been a hard market to crack. With the ban of Google Play in China and the hundreds of local app stores that have sprung up as a result, there’s no streamlined process for submitting apps on the Android market; getting featured and ranked is subject to negotiation, and IP rights regulation is lax.

Over 200 app stores compete on the Android market in China, but only the five big players3 truly own it: 360 Mobile Assistant4, YingYongBao of Tencent5, Baidu Mobile Assistant6, Wan Dou Jia (Pea Pod) and PP Assistant7. Many different stores for Android means different terms for developers. “The revenue sharing depends on the store, usually 50/50. For Tencent, it can be as high as 70/30, and the store takes the majority of the revenue,” Rock Zhang says.

“If you want to get your app featured on one or more of the multiple Chinese app stores, be prepared to negotiate,” Rock told me. Getting featured in China on the Android market is mostly about guanxi, the Chinese term for connections and networking. For an exclusive launch, you can negotiate rankings, getting featured and even revenue-sharing. The way it works is that you localize an app and submit the APK (Android application package) to several app stores. Then, you talk to the app stores’ reps and see what they offer in exchange for the right to be the first one to have it.

For iOS, Apple has made the process of app submission and approval more straightforward in China. The App Store has navigated China’s restrictive Internet policies and paved the path to local hearts and wallets after partnering with the country’s most popular payment service, UnionPay. Now, app developers looking to bring their product to the Chinese market can do so simply by adding Chinese localization. Seems easy: Translate App Store screenshot captions and in-app text, then add Simplified Chinese as a new language in iTunes Connect (the iOS developer’s dashboard). Not so fast.

Adding to the complexity of introducing your app to China is the huge influence of ecosystems belonging to China’s biggest tech players: Tencent, Alibaba and Baidu. Tencent’s WeChat is a prime example of the “app within an app” trend in China, where users can order food, request taxis and pay friends, all within their social messaging platform. Becoming a part of an ecosystem can give your app a huge boost because millions of users are a part of it (Wechat broke the 700 million mark 8 in early 2016). However, committing to an ecosystem does come with some disadvantages — namely, agreeing to be an exclusive app for one of the big three companies. This double-edged sword is yet one more layer to understand before you begin to localize for China.

Competing in China is tricky. To appeal to Chinese audiences, you need to go above and beyond word-for-word translation and adapt the app’s content and positioning for local consumers, potentially seeking partnerships with Chinese players to achieve maximum success. Here are a few rules to get you started.

Marketing To Chinese Users: Five Rules To Play By Link

Keep It Casual Link

This rule applies not only to the linguistic aspect of localization, but also to the higher-level approach to marketing and positioning for Chinese users. Top apps in the Chinese App Store speak to users on a personal level and in a helpful and simple tone.

For example, apps such as Taobao9 and Iqiyi10 cleverly describe a screenshot’s feature in four to six characters, followed by easy-to-understand specifics.

Screenshot from Iquyi app promoting its celebrity video platform11
Screenshot from Iqiyi promoting its celebrity video platform: “Iqiyi Bubbles – A more wonderful way to watch videos of famous stars” (Large preview12)

When localizing your screenshot’s caption, don’t cut corners with a simple translation tool. Instead, go with a trusted translator or service familiar with current Internet lingo and slang in China.

Chinese app localization13
(Large preview14)

Make It Social Link

Even when they are not primarily social, the most successful Chinese apps demonstrate some social or sharing ability in one or some of their screenshots in the App Store. Mainstream users in China don’t use social platforms such as Facebook and Twitter because of the government ban (they would have to access those and other banned websites through a VPN, which is too costly for many Chinese). However, it is important to add some social layer to boost engagement. WeChat15 and Weibo16, the WhatsApp and Twitter of China, are great ways to integrate social into your app.

App localization in China17
Eleme, a food delivery startup, allows friends to conveniently request their own meals in one order through WeChat’s group chat integration. (Large preview18)

Money, Money, Money Link

Localizing in China is no small feat, so prepare to adapt to the expectations of local users. It’s a developing country — making and saving money is a big goal for many Chinese smartphone users. In a country where the savings rate hovers around 50%19, more than double than that of the US, app developers and marketers understand that savings and discounts are a huge hit with Chinese users.

One striking example is the Chinese tradition of sending red envelopes (hong bao) filled with money around the Chinese New Year. This ritual has been directly digitized into virtual hong bao that users can send to each other. The trend has caught on not only among payment apps, but also in other categories of apps.

WeChat20
WeChat’s hong bao feature, red envelopes with real money that users can give away within the messaging app. (Image source21)

If yours is an e-commerce app, then explicitly showing discounts of 50%, 20%, even 5% is enough to draw the attention of thrifty Chinese mobile shoppers. Local mobile publishers have also taken the lead in using financial incentives to make their apps stickier. Dianping, the Yelp of China, draws and retains users through its amazing selection of coupons in many of its listed restaurants. For app developers, business partnerships and cross-promotions with coupons and rebates are a very effective way to attract users.

App localization in China22
Dianping users can enjoy discounts with lightning deals when they pay the bill with their phones — up to 50% off as advertised. (Large preview23)

Original Content Rules Link

As you walk on the street or take a subway in China, you’ll notice that everyone is looking down at their screens. Mobile content is constantly being devoured, and fresh content is always being sought out. Thanks to companies such as Xiaomi24 and innovative smartphone manufacturing, more and more people in China are becoming owners of Internet-enabled devices. China’s smartphone penetration rate has reached 50%25, which, for a country with a population of over 1.4 billion, translates to a lot of eyeballs and screens.

Youku26, which might be thought of as the Chinese YouTube but is actually more like the Chinese Netflix, is a leader in producing and distributing original content on the Internet. However, you don’t have to be a big media company to promote original content. Even social media apps are touting their original content from users. Although this tip depends on the app you’re trying to localize, if you do have original content to show, definitely make it clear in the App Store.

Users can watch original content on Iqiyi’s stories platform27
Users can watch original content on Iqiyi’s stories platform. (Large preview28)

Obey Cultural Norms Link

As with all localization efforts, pay attention to cultural norms, particularly in China. Some things that are considered normal and mainstream in the West, such as a dating app like Tinder, are untouchable subjects. Momo29, somewhat of an equivalent of Tinder in China, has an entirely different approach, refraining from suggestive, racy photos of attractive males and females. Instead, the App Store page features balanced genders and positions the app as a way for people to meet up and socialize.

Genders are balanced, and profile pictures are tame in Momo’s initial App Store screenshot30
Genders are balanced and profile pictures are tame in Momo’s initial App Store screenshot. (Large preview31)

But that doesn’t mean you always have to play it safe and not take a more risqué approach. In fact, one of Iqiyi’s screenshots features attractive female “anchors” and exotic sports cars. This shamelessly male-oriented approach, perhaps outlandish for app stores in the West, makes sense with Iqiyi’s large segment of young male users. While gender norms are one cultural difference, there are also different norms with age, income, occupation and more, making it very important to understand the nuances of Chinese culture for situations related to your app.

Long-lasting cultural norms have indeed influenced Chinese behaviors and mindsets around mobile, but keeping up with recent and emerging cultural trends can also be crucial to localization success. The tuhao, a term that originally referred to wealthy Chinese local landlords but now applies to uncouth Chinese nouveau riche with ostentatious taste32, has played a role in changing how the Chinese, especially younger ones, view money. Often the butt of jokes, tuhao have become a mainstream topic in Chinese society and are blamed for any showy displays of wealth — the Chinese have even given the gold iPhone 5s and 6 an apt popular nickname33, tuhao jin (tuhao gold). With all of the tuhao backlash, no one wants to be called out as a tuhao by their friends, so Alipay34, the world’s largest mobile payments platform, reassures potential users that they don’t have to worry about “showing off” when giving red envelopes (see rule 3).

Knowing cultural norms is one step, and pinning down the segment you’re targeting is another. Consulting an expert or doing your own user research will reveal the kinds of cultural overtones that your app should avoid — or highlight.

The tips above offer a starting point to plan your localization strategy in China. While native Chinese apps dominate the many app stores in China, the smashing success of a few Western challengers shows that staying the course and heeding important cultural distinctions is imperative for any successful venture into the Chinese market.

Case Study 1: Wording Matters: How Uber Takes Over China With Red Cars And “The People’s Taxi” Link

With one of the very few foreign apps in the top charts in China, Uber takes localization seriously. With a strong commitment to hyper-localizing35 in the many international markets where the ride-sharing app operates, Uber is intensely focused on winning the Chinese market, which entails tailoring its service to Chinese consumers. Rather than the usual moving black car icons on the app’s map, Uber drivers in China are represented with red cars36 — a welcome nod to both communist history and the auspicious cultural meaning of red in China. City-specific localization caters even further to local riders. In addition to the regular UberX and UberBlack services, Tianjin, near Beijing, has “The People’s Uber,” and the cosmopolitan hub of Shanghai has UberEnglish for English-speaking drivers.

In China, Uber drivers are represented with red cars instead of the usual black.37
In China, Uber drivers are represented with red cars instead of the usual black.

Case Study 2: Make Friends With Locals: How NBA Partners With Tencent To Stream Locally Curated Content In China Link

The NBA, which has a huge fanbase in China, has taken its time to launch a mobile app that truly engages its Chinese fans. Launched in January 2016 and racking 105,000 downloads in the first few hours38, the app gives 11 million Chinese fans access to game recaps and behind-the-scenes footage. Through a partnership with Tencent to stream games and feature content, the NBA China app has a wide reach with China’s growing base of smartphone and tablet users. Player and historical statistics are customized for Chinese fans, for whom some NBA players are more popular than they are in the US.

Even if you don’t have the resources and connections of companies such as Uber and the NBA, following their intense focus on Chinese consumers and culture is a good way to get started. Small things, like Uber’s red cars and “The People’s Uber,” add a delightful touch for Chinese users as they choose between the multitude of competing apps. Customized content, as the NBA’s China app shows, is a must for growing user engagement. Even with the excitement of China’s current mobile market, playing patiently like the NBA and finding the right partnership is sometimes the best way to survive and thrive in China’s intensely competitive mobile market.

Conclusion Link

Many people think localization is as simple as translating in-app content and app store pages. It’s more complex than that.

While truly understanding the Chinese market and getting localization right is a long and involved process, we hope that the few valuable tips shared here get you started on the right path.

  • Keep your marketing message casual and cool (hire a translator familiar with the local slang).
  • Skip the Facebook authentication. Integrate with WeChat and Weibo instead.
  • Offer deals and coupons for money-savvy Chinese users.
  • If your app offers fresh and original content, showcase it in the first screenshot.
  • Understand the general culture, but pin down the segment you’re targeting first and play up to different demographics, showcasing it in the first screenshot.
  • Don’t underestimate the importance of details such as color and wording.
  • Seek local partnerships to help you curate and customize content.

More than many nations, China is a country where language and tone carry nuanced differences that can be easily overlooked with hasty translation. Getting the message right is critical, but if you go beyond the language and adopt a mindset of cultural awareness, the payoff will be well worth it.

Further Resources Link

  1. China Internet Watch.39 A comprehensive website dedicated to all things Internet-related in China. Its mobile section is a great place to keep updated on the latest mobile app trends in China.
  2. AppInChina.40 A full-service marketing agency specializing in Chinese app store localization and promotion. It has a useful tool for identifying similar apps already existing on Chinese app stores.
  3. Geert Hofstede.41 An interactive tool that allows you to explore a country’s culture on the four core Hofstede dimensions.
  4. web2asia.42 Another agency for Chinese localization. Its blog articles are a great primer on Chinese e-commerce and search marketing.
  5. China Web Design Trends 2015.43 Kendra Schaefer for Smashing Magazine on the latest web design trends and digital habits in China.
  6. Color Perception Considerations in Marketing Design for Chinese Market.44 A great resource to consult for learning about what colors mean in their marketing implications in China.

(da, ml, al, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content/uploads/2016/08/Chinese-App-Store-Feature-Large-opt.jpg
  2. 2 https://www.smashingmagazine.com/wp-content/uploads/2016/08/Chinese-App-Store-Feature-Large-opt.jpg
  3. 3 http://www.iimedia.cn/40366.html
  4. 4 http://developer.360.cn/
  5. 5 http://sj.qq.com/myapp/
  6. 6 http://shouji.baidu.com/
  7. 7 http://www.25pp.com/
  8. 8 http://www.businessinsider.com/wechat-breaks-700-million-monthly-active-users-2016-4
  9. 9 https://www.taobao.com/
  10. 10 http://www.iqiyi.com/
  11. 11 https://www.smashingmagazine.com/wp-content/uploads/2016/08/Iqiyi-large-preview-opt.png
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2016/08/Iqiyi-preview-opt.png
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/07/02-google-translate-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/07/02-google-translate-opt.png
  15. 15 http://www.wechat.com/en/
  16. 16 http://weibo.com/login.php
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/08/eleme-large-preview-opt.png
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/08/eleme-large-preview-opt.png
  19. 19 http://www.cnbc.com/2015/10/25/china-savings-rate-versus-the-world-in-a-chart.html
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/08/alipay-preview-opt.png
  21. 21 http://a16z.com/2016/07/24/money-as-message/
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/08/dianping-large-preview-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/08/dianping-large-preview-opt.png
  24. 24 http://www.mi.com/en/
  25. 25 http://www.statista.com/statistics/257045/smartphone-user-penetration-in-china/
  26. 26 http://www.youku.com/
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/08/iqiyi-story-platform-large-preview-opt.png
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/08/iqiyi-story-platform-large-preview-opt.png
  29. 29 https://www.immomo.com/?v=en
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2016/08/momo-mobile-app-large-preview-opt.png
  31. 31 https://www.smashingmagazine.com/wp-content/uploads/2016/08/momo-mobile-app-large-preview-opt.png
  32. 32 http://shanghaiist.com/2015/09/23/tuhao_proposal.php
  33. 33 http://sinosphere.blogs.nytimes.com/2013/10/15/yet-another-way-to-mock-chinas-new-rich/
  34. 34 https://global.alipay.com/ospay/home.htm
  35. 35 https://www.buzzfeed.com/johanabhuiyan/uber-takes-over-the-world?utm_term=.mqobBYBXR#.rmLx9X94L
  36. 36 http://www.huffingtonpost.com/2015/05/04/uber-beijing-communist_n_7203624.html
  37. 37 https://www.smashingmagazine.com/wp-content/uploads/2016/07/10-uber-opt.png
  38. 38 http://www.ibtimes.com/nba-china-mobile-app-launches-heres-why-chinese-fans-wanted-basketball-phones-2354301
  39. 39 http://www.chinainternetwatch.com
  40. 40 http://www.appinchina.co
  41. 41 https://geert-hofstede.com/china.html
  42. 42 http://www.web2asia.com
  43. 43 https://www.smashingmagazine.com/2015/02/china-web-design-trends-2015/
  44. 44 http://sampi.co/color-perception-considerations-in-marketing-design-for-chinese-market/#ixzz4EngizZ8A
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Web Development Reading List #150: Less Code, GitHub’s Security, And The Morals Of Science

artificial intelligence 5291510 1920

Web Development Reading List #150: Less Code, GitHub’s Security, And The Morals Of Science

There is a lot to learn this week. It starts with non-technical things like going for a walk to refresh your mind and finishes with how to prevent reverse XSS attacks in forms. But it doesn’t matter whether you learn how to build self-contained web components using the new specification or to maximize the efficiency of your Angular 2 app or just how you can write less code. What matters is that you keep asking questions and that you try to get better and smarter at your craft.

General Link

  • Heydon Pickering shares tips on writing less code1 to make your developer life easier. Something we all should remember.

Tools & Workflows Link

  • Nucleus52 is certainly not the first living style guide generator but it’s still worth sharing. The Node.js module fits into existing projects, follows the Patternlab splitting by default, and has a nice layout where you easily find the things you’re looking for.
  • If you ever lost a stash in git, here are a few tips on how to recover dropped stashes3.
4
Nucleus52 is a living style guide generator that fits in well in both new and existing projects.

Security Link

  • Matthew Green asks himself if Apple’s cloud key vault is a crypt backdoor6. In his explanatory answer, he shares why Apple’s method of using Hardware Security Modules is pretty clever and maybe worth learning more about if you’re interested in storing sensitive user data behind weak user-set passwords.
  • Using social engineering by pretending to be a valid website in the URL bar is easy with the RTL feature of Chrome and Firefox and this little trick7. I’m sure this type of attack is successful since most normal users do check if a URL is correct but they can’t see anything bad in it. A good reminder that we need to find better ways to let users know that the URL they visit is safe.
  • When we look into the source code of forms at github.com, we’ll find some interesting markup in there8. Its purpose: preventing XSS attacks. In this blog post we can learn about the tricks that GitHub uses9 to maximize the security of their web application.
  • Troy Hunt wraps up how our personal data is usually leaked10 and why security is a design process, not only an implementation process. Also a good primer on how to design a password recovery feature.
Address bar spoofing11
Who’s really behind the URL? Ray Baloch uncovers an address bar spoofing vulnerability12 in Chrome and Firefox. (Image credit: Rafay Baloch13)

Web Performance Link

  • Nolan Lawson wrote about the cost of small modules14, analyzing how much code is used when you build your codebase with a lot of small modules. The article reveals interesting stats and compares modern minifiers and JavaScript bundlers, as well as execution times of such bundles in various browsers.

JavaScript Link

Work & Life Link

Going Beyond… Link

  • Bill Gates shares what he learned from his school teacher20 and how only later he realized that students should ask teachers more questions. If we ask more, we will learn from others. It’s always harder to proactively communicate knowledge to other people than being asked for it.
  • Phillip Rogaway shares a paper on “The Moral Character of Cryptographic Work21” (PDF). An interesting read on the shift of power and why cryptography is often a political tool that demands high morals and ethical fundamentals of those who build it. Anyone who ever discussed the topic of morals and ethics in science should read this.

And with that, I’ll close for this week. If you like what I write each week, please support me with a donation22 or share this resource with other people. You can learn more about the costs of the project here23. It’s available via email, RSS and online.

— Anselm

Footnotes Link

  1. 1 http://www.heydonworks.com/article/on-writing-less-damn-code
  2. 2 https://holidaypirates.github.io/nucleus/
  3. 3 https://stackoverflow.com/questions/89332/how-to-recover-a-dropped-stash-in-git/7844566
  4. 4 https://holidaypirates.github.io/nucleus/
  5. 5 https://holidaypirates.github.io/nucleus/
  6. 6 http://blog.cryptographyengineering.com/2016/08/is-apples-cloud-key-vault-crypto.html?m=1
  7. 7 http://www.rafayhackingarticles.net/2016/08/google-chrome-firefox-address-bar.html
  8. 8 https://chloe.re/2016/07/19/protect-against-html-extraction/
  9. 9 https://chloe.re/2016/08/15/lets-look-at-some-of-the-security-at-github/
  10. 10 https://www.troyhunt.com/website-enumeration-insanity-how-our-personal-data-is-leaked/
  11. 11 http://www.rafayhackingarticles.net/2016/08/google-chrome-firefox-address-bar.html
  12. 12 http://www.rafayhackingarticles.net/2016/08/google-chrome-firefox-address-bar.html
  13. 13 http://www.rafayhackingarticles.net/2016/08/google-chrome-firefox-address-bar.html
  14. 14 https://nolanlawson.com/2016/08/15/the-cost-of-small-modules/
  15. 15 http://blog.mgechev.com/2016/08/14/ahead-of-time-compilation-angular-offline-precompilation/
  16. 16 https://medium.com/@addyosmani/offline-storage-for-progressive-web-apps-70d52695513c
  17. 17 https://developers.google.com/web/fundamentals/primers/shadowdom/
  18. 18 https://shift.newco.co/how-a-single-conversation-with-my-boss-changed-my-view-on-delegation-and-failure-ae5376451c8d
  19. 19 http://zenhabits.net/walk/
  20. 20 https://www.gatesnotes.com/Education/A-Teacher-Who-Changed-My-Life
  21. 21 http://web.cs.ucdavis.edu/~rogaway/papers/moral-fn.pdf
  22. 22 https://wdrl.info/donate
  23. 23 https://wdrl.info/costs/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Building A Server-Side Application With Async Functions and Koa 2

artificial intelligence 5291510 1920

Building A Server-Side Application With Async Functions and Koa 2

One of the upcoming features of JavaScript that I especially like is the support for asynchronous functions1. In this article, I would like to show you a very practical example of building a server-side application using Koa 2, a new version of the web framework, which relies heavily on this feature.

First, I’ll recap what async functions are and how they work. Then, I’ll highlight the differences between Koa 1 and Koa 2. After that, I will describe my demo app for Koa 2, covering all aspects of development, including testing (using Mocha, Chai and Supertest) and deployment (using PM2).

Async Functions Link

The old problem of complex JavaScript applications is how to deal with callbacks and how to structure the code to avoid so-called “callback hell.” Several solutions have been developed over time, some of which are still based on callbacks and others that rely on more recent features of JavaScript — promises and generators. Let’s compare callbacks, promises and generators using the example of a function that fetches two JSON files in sequence.

// Fetch two files with callbacks function doWork(cb) { fetch('data1.json', (err1, result1) => { if (err1) { return cb(err1); } fetch('data2.json', (err2, result2) => { if (err2) { return cb(err2); } cb(null, { result1, result2, }); }) }); }

Nested anonymous inline callback functions are the primary indicator of callback hell. You could restructure the code and split the functions into modules, but you would have to rely on callbacks anyway.

// Fetch two files with promises function doWork(cb) { fetch('data1.json') .then(result1 => fetch('data2.json') .then(result2 => cb(null, { result1, result2, }))) .catch(cb); }

The promise-based version looks a bit better, but the calls are still nested and we need to reorganize the code to appear sequential.

// Fetch two files with generators function* doWork() { var result1 = yield fetch('data1.json'); var result2 = yield fetch('data2.json'); return { result1, result2 }; }

Generators allow for the shortest solution, and this looks like normal synchronous code, whereas the callback and promise snippets are clearly asynchronous and highly nested. Nevertheless, the generator solution requires that we change the function type to the generator function by adding * after the function keyword, and it requires the special way to invoke doWork. This looks somewhat unintuitive, and the async/await syntax addresses this drawback by providing better abstraction. Look at the same example using async functions:

async function doWork() { // Fetch two files with async/await var result1 = await fetch('data1.json'); var result2 = await fetch('data2.json'); return { result1, result2 }; }

This syntax can be interpreted as follows: Functions marked with the async keyword allow us to use the await keyword in them, which pauses the execution of the function to wait for the asynchronous operations to finish. The asynchronous operation can be represented by a generator, a promise or another async function. Also, you can use try/catch to handle any errors or rejections that occur during the async operations that you await. The same error-handling mechanism is possible with the generator-based control flow.

What is Koa? Link

Koa is positioned as a next generation web framework and it was designed by the people who created Express (and in particular, by TJ2). Koa is very lightweight and modular and allows writing code without using callbacks. Koa application is an array of middleware functions that run in sequence processing incoming requests and providing a response. Every middleware function has the access to the context object that wraps native node request and response objects and provides an improved API to work with them. Basic Koa application looks like this:

// This is Koa 1 var koa = require('koa'); var app = koa(); app.use(function *(){ this.body = 'Hello World'; }); app.listen(3000); 

This is not much except for this in the Koa core. Advanced functionality is provided by 3rd-party modules.

Koa 2 Versus Koa 1 Link

Koa 1 is famous for its early adoption of generators and for supporting generator-based control out of the box. This is what a typical piece of code for Koa 1 that uses the middleware cascading and improved error handling looks like:

// Adapted from https://github.com/koajs/koa // In Koa 1.0, middleware is a generator function. app.use(function *(next) { try { yield next; } catch (err) { // the request context is <code>this</code> this.body = { message: err.message } this.status = err.status || 500 } }) app.use(function *(next) { const user = yield User.getById(this.session.id); this.body = user; })

Koa 2 removes built-in support for generators and uses async functions instead. The signature of middleware functions will change to support async arrow functions. Here is what the same code looks like written for Koa 2:

// Taken from https://github.com/koajs/koa // Uses async arrow functions app.use(async (ctx, next) = > { try { await next(); // next is now a function, await instead of yield } catch (err) { ctx.body = { message: err.message }; ctx.status = err.status || 500; } }); app.use(async ctx => { // await instead of yield const user = await User.getById(ctx.session.id); // ctx instead of this ctx.body = user; });

Using normal functions, promises and generator functions is still possible, as described in the documentation for Koa 23.

Koa Versus Express Link

Koa is a simpler and leaner framework than Express, built on top of the Node.js’ HTTP module. Express provides built-in features for routing, templating and sending files and other features, whereas Koa provides the very minimum, as well as a generator-based (Koa 1) or async/await-based (Koa 2) control flow. Routing, templating and other features are provided as separate modules by the community, and normally there are several alternatives to choose from. The Koa section of GitHub has a document with additional insight4 on the differences between Koa and Express.

Status of Koa 2 Link

Koa 2 will be released once the async/await feature is available in Node.js natively. Fortunately, async/await and Koa 2.0 can be tested right now using Babel. We will get to this soon. First, let’s go over the scope of the app that I built to demonstrate Koa 2 and async functions.

Demo App Link

The goal here is to build a simple app that tracks page views for a static website — something like Google Analytics but much simpler. The app will have two endpoints:

  • one to store the information about an event (for example, a page view);
  • and one to get the total number of events;
  • additionally, the endpoints have to be secured with an API key.

Redis will be used to store the events data. The functionality will be tested by unit and API tests. The full source code of the app is available on Github5.

App Dependencies Link

Let’s start with the list of modules needed for the app, along with explanations for why they are needed. First, here are the dependencies needed at runtime:

npm install --save  # babel-polyfill provides the runtime that async functions need babel-polyfill  # The Koa framework itself koa@next  # Because Koa is minimalist, we need a parser # to parse JSON in the body of requests koa-bodyparser@next  # and the router koa-router@next  # The redis module to store the app's data redis # The Koa cors module to allow cross-origin requests kcors@next

Note that the version for Koa modules we are using is next. This means that this version will be compatible with Koa 2, and many modules already provide it. Here are the modules needed for development and testing:

npm install --save-dev  # To write assertions in our tests chai  # A popular testing framework mocha  # API-level tests supertest  # Babel CLI to build our app babel-cli  # A set of Babel plugins to support ES6 features babel-preset-es2015  # and to support stage-3 features babel-preset-stage-3  # Overrides Node.js's require and compiles modules at runtime babel-register  # To watch JavaScript files in development and restart the server # if there are changes in the files nodemon 

How to Organize the Application? Link

After trying out several ways to organize the application’s files, I came up with the following simple structure that is suitable for small apps and small teams:

  • index.js

    The main entry point of the app
  • ecosystem.json

    The PM2 ecosystem, which describes how to start the app
  • src

    The source of the app, containing JavaScript files to be compiled by Babel
  • config

    The app’s configuration files
  • build

    The build of the app, containing the compiled code from src

The src directory contains the following:

  • api.js

    The module that defines the app’s API
  • app.js

    The module that instantiates and configures the Koa app’s instance
  • config.js

    The module that provides the configuration of the app to other modules

If additional files or modules are needed as the app grows, we would put them in a subfolder of the src folder — for example, src/models for application models, src/routes for more modular API definitions, src/gateways for modules that interact with external services, and so on.

NPM Scripts As A Task Runner Link

After using Gulp and Grunt as task runners, I came to the conclusion that npm scripts are better than separate tools when working on server-side projects. One of the advantages of npm scripts is that they allow you to invoke locally installed modules as if there were globally installed. I use the following scripts, which need to be defined in package.json:

"scripts": { "start": "node index.js", "watch": "nodemon --exec npm run start", "build": "babel src -d build", "test": "npm run build; mocha --require 'babel-polyfill' --compilers js:babel-register" }

The start script simply runs index.js. The watch script runs the start script using the nodemon tool, which automatically restarts the server whenever you change something in the app. Note that nodemon is installed as a local development dependency and does not have to be installed globally.

The build script compiles the files in the src folder using Babel and outputs the results to the build folder. The test script runs the build script first and then runs tests using mocha. Mocha requires two modules: babel-polyfill, to provide runtime dependencies of the compiled code, and babel-register, to compile the test files before executing them.

Additionally, presets for Babel have to be added to package.json, so that you don’t have to provide them in the command line:

{ "babel": { "presets": [ "es2015", "stage-3" ] } }

This preset enable all ECMAScript 2015 features, as well as features that are currently in stage 36. With this installed and configured, we can start developing the app.

The Application’s Code Link

First, let’s look at index.js:

const port = process.env.PORT || 4000; const env = process.env.NODE_ENV || 'development'; const src = env === 'production' ? './build/app' : './src/app'; require('babel-polyfill'); if (env === 'development') { // for development use babel/register for faster runtime compilation require('babel-register'); } const app = require(src).default; app.listen(port);

The module reads two environmental variables: PORT and NODE_ENV. NODE_ENV should be either development or production. In development mode, babel-register will be used to compile modules at runtime. babel-register caches the results of the compilation and, thus, reduces the server start time, so that you can iterate faster during development. Because this module is not recommended for production use, the precompiled version from the build directory will be used in production mode.

index.js is the only file of the project that will not be compiled by Babel and that must use native module syntax (i.e. CommonJS). Therefore, the app’s instance is located in the default property of the imported app module, which is an ECMAScript 6 module that exports the app’s instance as a default export:

export default app;

This is important to keep in mind if you mix ECMAScript 6 and CommonJS modules.

Now to the app.js file itself. This and the other files discussed below are always compiled by Babel in both development and production environments, and the new syntax (including async functions) may be used freely in them:

import Koa from 'koa'; import api from './api'; import config from './config'; import bodyParser from 'koa-bodyparser'; import cors from 'kcors'; const app = new Koa() .use(cors()) .use(async (ctx, next) => { ctx.state.collections = config.collections; ctx.state.authorizationHeader = `Key ${config.key}`; await next(); }) .use(bodyParser()) .use(api.routes()) .use(api.allowedMethods()); export default app;

Here, we are using ECMAScript 2015’s import syntax to import the required modules. Then, we create a new instance of the Koa application and attach several middleware functions to it using the use method. The last thing we do is export the app so that it can be used by index.js.

The second middleware function in the chain is an async function and an arrow function at the same time:

app.use(async (ctx, next) => { // Set up the request context ctx..state.collections = config.collections; ctx..state.authorizationHeader = `Key ${config.key}`; await next(); // The execution will reach here only when // the next function returns and finishes all async tasks // console.log('Request is done'); })

In Koa 2, the next parameter is an async function that triggers the next middleware function in the list. Just like in Koa 1, you can control whether the current middleware function should do its job before or after the others by putting the call to next either at the beginning of the current function or at the end. Also, you can catch all errors in the downstream middleware functions by wrapping the await next(); statement in a try/catch statement wherever doing so makes sense.

Defining the API Link

The api.js file is where the core logic of our app resides. Because Koa does not provide routing out of the box, the app has to use the koa-router module:

import KoaRouter from 'koa-router'; const api = KoaRouter();

Here, koa-router provides functions to define middleware functions for specific HTTP methods and paths — for example, the route that stores events in the database:

// Declare a post method and what it does // :collection is a parameter api.post('/:collection', // First, validate auth key validateKey, // Then, validate that the provided collection exists validateCollection, // Handle adding the new item to the collection async (ctx, next) => { // Use ES6 destructuring to extract the collection param const { collection } = ctx.params; // Wait until the persistence layer saves the item const count = await ctx .state .collections[collection] .add(ctx.request.body); // Reply with 201 Created when the item is saved ctx.status = 201; });

Each method can have several handlers, which run sequentially and have exactly the same signature as the middleware functions defined in the top level of app.js. For example, validateKey and validateCollection are simply async functions that validate the incoming request and return 404 or 401 if the provided event collection does not exist or if the API key is not valid:

const validateCollection = async (ctx, next) => { const { collection } = ctx.params; if (!(collection in ctx.state.collections)) { return ctx.throw(404); } await next(); } const validateKey = async (ctx, next) => { const { authorization } = ctx.request.headers; if (authorization !== ctx.state.authorizationHeader) { return ctx.throw(401); } await next(); }

Note that arrow middleware functions cannot refer to the context of the current request using this (i.e. this is always undefined in the examples thus far). Therefore, request and response objects as well as Koa helpers are available in the context object (ctx). Koa 1 had no separate context object, and this referred to the current request context.

After defining other API methods7, we finally export the API to be connected to the Koa application in app.js:

export default api;

Persistence Layer Link

In api.js, we accessed the collections array in the context ctx, which we initialized in app.js. These collection objects are responsible for storing and retrieving data stored in Redis. The Collection class is as follows:

// Use promise-based Redis client const redis = require('promise-redis')(); const db = redis.createClient(); class Collection { // Full source: // https://github.com/OrKoN/koa2-example-app/blob/master/src/collection.js async count() { // We can `await` for promises // The await syntax allows us to work with // async calls as if they were synchronous var count = await db .zcount(this.name, '-inf', '+inf'); return Number(count); } async add(event) { await db .zadd(this.name, 1, JSON.stringify(event)); await this._incrGroups(event); } async _incrGroups(event) { // ES6 for:of syntax allows for easier iteration // groupBy is an array that holds possible attributes of the event for (let attr of this.groupBy) { // We can use await inside loops, // thus calling async operations sequentially in the loop await db.hincrby(`${this.name}_by_${attr}`, event[attr], 1); } } } export default Collection;

The async/await syntax is really helpful here because it allows us to coordinate several async operations easily — for example, in a loop. But there is one important thing to keep in mind. Let’s look at the _incrGroups method:

async _incrGroups(event) { // ES6 for:of syntax allows iterating easier for (let attr of this.groupBy) { // We can use await inside loops, // thus calling async operations sequentially in the loop await db.hincrby(`${this.name}_by_${attr}`, event[attr], 1); } }

Here, the keys are incremented sequentially, meaning that the next key will be incremented once the previous incrementation has succeeded. But this kind of job can be done in parallel! With async/await, the task might not be easy to accomplish, but promises can help:

// Start all increments in parallel // because there is no await inside the map callback here const promises = this.groupBy.map(attr => db.hincrby(`${this.name}_by_${attr}`, event[attr], 1)); // Wait for all of them to finish await Promise.all(promises);

The interchangeability of promises and async functions is very helpful.

Testing Link

The app’s tests are located in the test folder8. Let’s look at apiSpec.js, which represents the test specification for the app’s API:

import { expect } from 'chai'; import request from 'supertest'; import app from '../build/app'; import config from '../build/config';

We import expect from chai and supertest. We use the precompiled version of the app and the config to make sure that we are testing exactly the same code that will be running in production. Next, we write the tests for the API, leveraging the async/await syntax to achieve sequential execution of the test steps:

describe('API', () => { const inst = app.listen(4000); describe('POST /:collection', () => { it('should add an event', async () => { const page = 'http://google.com'; const encoded = encodeURIComponent(page); const res = await request(inst) .post(<code>/pageviews</code>) .set({ Authorization: 'Key ' + config.key }) .send({ time: 'now', referrer: 'a', agent: 'b', source: 'c', medium: 'd', campaign: 'e', page: page }) .expect(201); // here res is available // you can use res.headers, res.body etc // no callback for <code>expect</code> or <code>end</code> functions is required. expect(res.body).to.be.empty; }); }); });

Note that functions passed to it functions are marked with async. This means that await can be used to run asynchronous tasks, including the supertest requests, which return then-able objects and which, therefore, are compatible with what await expects.

Deployment With PM2 Link

Once the app is ready and tests have passed, let’s prepare everything to run the app in production. For this, let’s declare ecosystem.json, which will hold the production configuration of the app:

{ "apps" : [ { "name" : "koa2-example-app", // The entry point to the compiled version of the app "script" : "index.js", // In production, we don't want to watch for changes in files "watch" : false, // And we want to merge logs from all instances "merge_logs" : true, // We want to timestamp log messages "log_date_format": "YYYY-MM-DD HH:mm Z", "env": { // And include environment variables for the app "NODE_ENV": "production", "PORT": 4000 }, // Start two processes of the app, and balance the load between them "instances": 2, // Start app as a cluster "exec_mode" : "cluster_mode", // Watch failures and auto-restart processes "autorestart": true } ] }

If your app requires additional servers (for example, a cron job), you can add them to ecosystem.json, and they will be started together with the main server. To start the app on the production server, you can run this:

pm2 start ecosystem.json

And to persist the configuration, you would run this:

pm2 save

PM2 provides some monitoring features (try pm2 list, pm2 info, pm2 monit). For example, PM2 shows how much memory your application is using. This basic Koa application consumes 44 MB per Node.js process.

Conclusion Link

Babel allows us to build apps using ECMAScript syntax that is not natively available but that includes async/await, which makes writing asynchronous code more enjoyable. The code that uses the async/await syntax is easier to read and maintain. Koa 2 and Babel allow you to start using async functions right now.

Nevertheless, Babel brings additional overhead and requires additional configuration and an extra build step. Therefore, waiting until async/await is natively available in Node.js is recommended. Koa 2 should be officially released once this happens. Then, Koa 2 will be a good alternative to Express because it is more modular and simpler and allows for configuration the way you want it.

The deployment section of this tutorial might be too simple and unscalable. It leaves open the question of how and when to build and actually deploy the code — you can do this manually (rsync, scp) or set up a continuous integration server for this. Also, the inner architecture of the app is too simple yet is suitable for a demo. Larger and more ambitious apps might require other entities, such as gateways, mappers, repositories and so on, but all of them can leverage async functions.

I hope you’ve enjoyed this tutorial. Thanks for reading!

Links Link

(al)

Footnotes Link

  1. 1 https://tc39.github.io/ecmascript-asyncawait/
  2. 2 https://github.com/tj
  3. 3 https://github.com/koajs/koa/tree/v2.x#common-function
  4. 4 https://github.com/koajs/koa/blob/master/docs/koa-vs-express.md
  5. 5 https://github.com/OrKoN/koa2-example-app
  6. 6 https://github.com/tc39/ecma262#current-proposals
  7. 7 https://github.com/OrKoN/koa2-example-app/blob/master/src/api.js
  8. 8 https://github.com/OrKoN/koa2-example-app/tree/master/test
  9. 9 https://github.com/koajs/koa/wiki
  10. 10 https://tc39.github.io/ecmascript-asyncawait/
  11. 11 https://github.com/OrKoN/koa2-example-app
  12. 12 https://github.com/koajs/koa/wiki#middleware
  13. 13 https://github.com/koajs/koa/issues/533
  14. 14 https://github.com/nodejs/promises/issues/4

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Photoshop Etiquette For Responsive Web Design

artificial intelligence 5291510 1920

Photoshop Etiquette For Responsive Web Design

It’s been almost five years since Photoshop Etiquette151 launched, which officially makes it a relic on the web. A lot can happen on the web in a few years, and these past five have illustrated that better than most.

In 2011, everyone was just getting their feet wet with responsive web design. The traditional comp-to-HTML workflow was only beginning to be critiqued, and since then, we’ve seen a myriad of alternatives. Style Tiles2, Style Prototypes3, Visual Inventories4, Element Collages5, style guides6, and even designing in the browser have all been suitable approaches to multi-device design. With a shift from page-based design to building a design system, it’s truly an exciting time.

Further Reading on SmashingMag: Link

There’s also been an explosion of tools attempting to make a responsive workflow more efficient. Applications like Webflow and Macaw have made breakpoint visualization digestible for the code-averse. Many designers have moved on from Photoshop as their workhorse to Sketch, Affinity Designer, or similar. Others have adopted apps like Keynote for prototyping.

11
A flurry of new tools and techniques has seemingly put good ol’ fashioned etiquette on the back burner.

Is ‘Etiquette’ Still Relevant? Link

With alternatives to the heavy Photoshopping we may be familiar with, it’s fair to question if we still need etiquette. For the sake of this article, we’ll define etiquette as transferring files in an organized, clear, and discernible way. Responsive design typically comes with a lot of moving pieces, from @2x images, concatenated CSS files, and more. With seemingly more to do in order to publish a website, being efficient is unquestionably high priority, if we want to be profitable.

Often masked as efficiency, poor organization and communication are products of rushing to ship a project. With Photoshop taking on different roles in our workflows, layers and exported files are easy targets for cutting corners. The fact remains: anything worth doing is worth doing well.

If we want to save time, we need to invest a bit upfront in staying organized and clear. Inefficiency is inheriting a file from a coworker and spending valuable time attempting to figure out where to start because it’s not clearly labeled. It’s having to fix images that have already been exported. At worst, it’s not being able to find the file you need in the first place.

What’s New In Photoshop Etiquette? Link

Photoshop Etiquette was given a fresh coat of paint by Adjacent12, a design studio in Syracuse, NY. For those new to the concept, Photoshop Etiquette is a best practices guide that promotes efficiency through clarity in web design. Though engineered for Photoshop, many of these principles apply to Sketch and similar, layer-based design tools.

The guide is broken down into the following sections:

  • File organization
  • Layer structure
  • Asset exporting
  • Type execution
  • Effect application
  • Quality check

Those familiar with the site will see a lot of familiar guidelines, such as quintessential tips like ‘Name Your Layers’ and ‘Name Files Accurately’, each an attempt at ridding the earth of practices like ‘Layer copy copy 5’ and ‘client-final-v3.psd’, respectively. If you dig a little deeper, you’ll find a glut of responsive resources attached to various guidelines, and a few tips for designing for multiple devices.

1. Consolidate Your PSDs Link

If you’re making multiple comps for multiple pages, Photoshop now has artboards that can help you stick to a single document. This helps eliminate confusion about which PSD is the right PSD.

If you can swing it, try using artboards, layer comps, or smart objects instead of managing tons of PSDs.
If you can swing it, try using artboards, layer comps, or smart objects instead of managing tons of PSDs.

2. Work Collaboratively Link

With the addition of Creative Cloud Libraries and Linked Smart Objects, designers can share assets quite easily. For example, if you’re creating a pattern or component guide in Photoshop, one designer can be working on a component while another designer simultaneously works on a different one. These components can be shared within a Library, or as Linked Smart Objects that are pulled into a master PSD.

Between Linked Smart Objects and CC Libraries, there
Between Linked Smart Objects and CC Libraries, there’s plenty of options for being collaborative.

3. Don’t Design To The Device Link

This can be argued, but if responsive design is about embracing all devices, perhaps we shouldn’t use popular Apple device presets as document sizes in Photoshop. Instead, allow your design to dictate breakpoints because of layout stress, wherever it falls. The exception is if you’re designing a device or platform-specific app, where targeting such presets is helpful.

Allow your design to dictate breakpoints, not popular-for-the-moment device widths.
Allow your design to dictate breakpoints, not popular-for-the-moment device widths.

4. Be Non-Destructive Link

With the rising implementation and support for SVG, it’s important for designers to sustain vector assets in Photoshop and not flatten them. Photoshop now allows you to save out SVGs, giving us one more reason to be nondestructive with our pixels.

5. Be Aware Of Screen Resolution Link

Speaking of SVG, it has really become a great approach to serving one asset that can adapt to any size and not lose fidelity. Having a Retina asset workflow13, whether SVG or @2x/@3x images, has become part of a responsive practitioner’s workflow.

6. Compress Link

Performance is a worthy cause, not only for a developer but for a designer. I’ve often rationalized that if I want to include heavy web fonts and their Open Type features in my projects, I’ll need to make up the difference by aggressively compressing my images to stay within a performance budget. Third party tools like TinyPNG14 have made image compression a breeze.

Performance is a designer
Performance is a designer’s task. Make sure you’re squeezing any extra file size out of your images.

As our web design workflows and use of Photoshop continues to change, so will the site. While it encompasses a Photoshop-centric workflow, there’s a few tips for ones where Photoshop is used sparingly, as well. The guide only advocates that if, and when, you use Photoshop, communicate your intent as clearly as possible.

Fueled By Community Link

One of the primary focuses for Photoshop Etiquette151 is growth, manifested in more guidelines, more resources, and more perspectives. A feature has been added to the site providing easier access to submit a new guideline for review, something hundreds of designers and developers did over the years by tracking me down on Twitter or hunting down an email address.

In the wake of Google Translate’s inaccuracies, there’s also an open call for translations by community volunteers.

It’s exciting to see how Photoshop Etiquette has resonated with so many organizations and individuals. How can it help you and your team?

(vf, il)

Footnotes Link

  1. 1 http://photoshopetiquette.com/
  2. 2 http://styletil.es/
  3. 3 http://seesparkbox.com/foundry/our_new_responsive_design_deliverable_the_style_prototype
  4. 4 http://danielmall.com/articles/visual-inventory/
  5. 5 http://danielmall.com/articles/rif-element-collages/
  6. 6 http://styleguides.io/
  7. 7 https://www.smashingmagazine.com/2015/05/retina-design-in-photoshop/
  8. 8 https://www.smashingmagazine.com/2015/06/creating-advanced-animations-in-photoshop/
  9. 9 https://www.smashingmagazine.com/2016/03/the-retina-asset-workflow-youve-always-wanted-for-photoshop/
  10. 10 https://www.smashingmagazine.com/2016/01/responsive-image-breakpoints-generation/
  11. 11 http://photoshopetiquette.com/
  12. 12 http://weareadjacent.com
  13. 13 https://www.smashingmagazine.com/2015/05/retina-design-in-photoshop/
  14. 14 http://tinypng.com
  15. 15 http://photoshopetiquette.com/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

S(GH)PA: The Single-Page App Hack For GitHub Pages

artificial intelligence 5291510 1920

Sponsored PostS(GH)PA: The Single-Page App Hack For GitHub Pages

For some time now, I’ve wanted the ability to route paths for a GitHub Pages website to its index.html for handling as a single-page app (SPA). This is table-stakes because such apps require all requests to be routed to one HTML file, unless you want to copy the same file across all of your routes every time you make a change to the project. Currently, GitHub Pages doesn’t offer a route-handling solution; the Pages system is intended to be a flat, simple mechanism for serving basic project content.

In case you weren’t aware, GitHub does provide one morsel of customization for your project website: the ability to add a 404.html file and have it served as your custom error page. I took a first stab at an SPA hack simply by duplicating my index.html file and renaming the copy to 404.html. Turns out that many folks have experienced the same issue1 with GitHub Pages and liked the general idea. However, the problem that some folks on Twitter correctly raised was that the 404.html page is still served with a status code of 404, which is not good for search engine crawlers. The gauntlet had been thrown down, and I decided to answer — and answer with vigor!

One More Time, With Feeling Link

After sleeping on it, I thought to myself, “Self, we’re deep in dirty hack territory, so why don’t I make this hack even dirtier?!” To that end, I developed an even better hack that provides the same functionality and simplicity, while also preserving your website’s crawler juice — and you don’t even need to waste time duplicating your index.html file and renaming it to 404.html anymore! The following solution should work in all modern desktop and mobile browsers (Edge, Chrome, Firefox, Safari) and in Internet Explorer 10+.

Template and Demo: If you want to skip the explanation and get the goods, here’s a template repo2, and a test URL to see it in action3.

That’s So Meta Link

The first thing I did was investigate other options for getting the browser to redirect to the index.html page. That part was pretty straightforward. You basically have three options: a server config, a JavaScript location manipulation, or a refresh meta tag. The first one is obviously a no-go for GitHub pages. And JavaScript is basically the same as a refresh, but arguably worse for crawler indexing. That leaves us with the meta tag. A meta tag with a refresh value of 0appears to be treated as a 301 redirect4 by search engines, which works out well for this use case.

You’ll need to start by adding a 404.html file to a gh-pages repository that contains an empty HTML document inside it. That document must total more than 512 bytes (explained below). Next, put the following markup in your 404.html page’s head element:

<script> sessionStorage.redirect = location.href; </script> <meta http-equiv="refresh" content="0;URL='/REPO_NAME_HERE'">

This code sets the attempted entrance URL to a variable on the standard sessionStorage object and immediately redirects to your project’s index.html page using a meta refresh tag. If you’re doing a Github Organization site, don’t put a repo name in the content attribute replacer text, just do this: content="0;URL='/'"

Customizing Route Handling Link

If you want more elaborate route handling, just include some additional JavaScript logic in the script tag shown above. You can tweak several things: the composition of the href that you pass to the index.html page; which pages should remain on the 404 page (via dynamic removal of the meta tag); and any other logic you want to put in place to dictate what content is shown based on the inbound route.

512 Magical Bytes Link

This is, hands down, one of the strangest quirks I have ever encountered in web development. You must ensure that the total size of your 404.html page is greater than 512 bytes, because if it isn’t, Internet Explorer will disregard it and show a generic browser 404 page instead. When I finally figured this out, I had to crack open a beer to cope with the amount of time it took.

Let’s Make History Link

To capture and restore the URL that the user initially navigated to, you’ll need to add the following script tag to the head of your index.html page before any other JavaScript acts on the page’s current state:

<script> (function(){ var redirect = sessionStorage.redirect; delete sessionStorage.redirect; if (redirect && redirect != location.href) { history.replaceState(null, null, redirect); } })(); </script>

This bit of JavaScript retrieves the URL that we cached in sessionStorage over on the 404.html page and replaces the current history entry with it. How you choose to handle things from here is up to you, but I’d use popstate and hashchange if I were you.

Well, folks, that’s it. Now go celebrate by writing some single-page apps on GitHub Pages!

This article is part of a web development series from Microsoft tech evangelists and engineers on practical JavaScript learning, open-source projects and interoperability best practices, including Microsoft Edge5 browser.

We encourage you to test across browsers and devices (including Microsoft Edge — the default browser for Windows 10) with free tools on dev.microsoftedge.com6, including the F12 developer tools7: seven distinct, fully documented tools to help you debug, test and speed up your web pages. Also, visit the Edge blog8 to stay informed by Microsoft developers and experts.

(al)

Footnotes Link

  1. 1 https://twitter.com/csuwildcat/status/730558238458937344
  2. 2 https://github.com/csuwildcat/sghpa
  3. 3 https://csuwildcat.github.io/sghpa/foo/bar
  4. 4 http://sebastians-pamphlets.com/google-and-yahoo-treat-undelayed-meta-refresh-as-301-redirect/
  5. 5 https://blogs.windows.com/msedgedev/2015/05/06/a-break-from-the-past-part-2-saying-goodbye-to-activex-vbscript-attachevent/?wt.mc_id=DX_873182
  6. 6 https://dev.windows.com/en-us/?wt.mc_id=DX_873182
  7. 7 https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/f12-devtools-guide/?wt.mc_id=DX_873182
  8. 8 https://blogs.windows.com/msedgedev/?wt.mc_id=DX_873182

↑ Back to topTweet itShare on Facebook

Creativity Under The Microscope: Running A UI Design Critique

artificial intelligence 5291510 1920

Creativity Under The Microscope: Running A UI Design Critique

Criticism is easy. It seems like everybody has an opinion, but, as the author Harlan Ellison points out, “You are not entitled to your opinion. You are entitled to your informed opinion.” To become informed, though, requires exploration. Design critiques are an important part of any product exploration.

A design critique — where the creator discusses and explains the creation with the rest of the team and/or client — is not about badgering the designer or pushing them to justify every decision they made. That’s just criticism. A good design critique is meant to explore the design, find where it is working and where it could be improved. If done well, design critiques allow everyone on the team to feel as if they have been heard and allow clients to give valuable feedback.

If you are the person running the critique, getting to constructive criticism is often a challenge, especially with groups that do not have experience with the design critique format. In an agile environment, you will often have coders, project managers, product managers and people from other disciplines sitting in to give feedback, and you need to know how to quickly get them up to speed on the expectations if you want to get anywhere fast.

Principles For Running A Great UI Critique Link

From my own experience, I’ve found that design critiques for user interfaces (UIs) need to be performed throughout the entire product design and development process, at least weekly, and possibly even daily at certain times. They keep the product design on track, and they become even more critical in an interactive agile or lean UX product environment, where designs go through multiple iterations before deployment. Running a UI design critique is a challenge, requiring you not only to explain decisions, but also to listen carefully to other ideas.

1
The critique allows your team to create together. (Image: Jamie Cummings2) (View large version3)

Establishing clear principles — not “rules” — at the beginning of every critique is imperative. Unlike rules, which are dogmatic and feel restrictive, principles help everyone understand the expectations but still allow for the freeform discussion that is needed.

Chief among these expectations is for everybody to agree on why you are actually critiquing what you are looking at. Jason Ulaszek recommends:

Start by asking about the purpose or intention behind the design you’re critiquing. Why are we asking for this piece of information? What expectations have been set that allow us to ask for it? What will we do with it? If we can answer those questions, then we move on to discussing various options of interpreting the need for the element and respective advantages and disadvantages with each option.

Critique4
Be prepared to show and tell. (Image: Jason CranfordTeague5) (View large version6)

To help you keep to this guideline, I recommend following the standard principles you might apply to any design critique, whether it involves UI design or not:

  • Show respect.

    It might sound cliched, but if everyone in the critique is not respectful of the opinions and skills of the others at the table, then the critique will quickly degrade into hostility.
  • Designate roles.

    Before starting, clarify who will be taking on which role(s) during the critique. It’s best to mix these up from critique to critique so that no one feels left out, and it’s optimal if the three lead roles are different people (but that is not always practical).

    • Presenter

      This is the person responsible for presenting the design and the thinking behind it. This person answers all questions or directs them to other people in the critique who can answer them.
    • Moderator

      If possible, it is best if this role is performed by someone not directly responsible for the design, often the project or product manager. The moderator ensures that everyone stays on topic and that everyone is heard.
    • Note-taker

      This person focuses on recording what is discussed and is especially vital for making sure that the takeaways (another principle, listed below) are clearly defined at the end of the critique. The note-taker should not be left out of the discussion, although their role might lean towards getting other members of the team to clarify what they have said.
  • State the goals for the project and for the critique up front.

    Quickly remind everyone of the goals of the project and what this specific critique will cover. Keep the critique focused on the task at hand, rather than allowing the scope to creep to other considerations that would derail the primary purpose of the discussion.
  • Review the audience(s).

    To reinforce that the people in the critique are not the target audience for the product, remind everyone about who is.
  • Avoid coming up with “the answers.”

    Participants will feel a strong desire to solve problems and come up with the “answer” in a critique. However, the best solutions rarely arise in the actual meeting. The point of a critique is to probe for issues and discuss multiple potential solutions for the designer to take away and consider.
  • Agree on takeaways.

    After everything has been said in the critique, the note-taker needs to review the takeaway tasks for everyone who participated to ensure that everyone is on the same page for the next critique.

Unfortunately, all too often, UI design critiques focus heavily on the visual and not enough on the interactive, much less temporal, nature of the design. For a UI design critique, add the following elements:

  • Identify the presentation media.

    Along with identifying the audience, review the platform and technologies being used to create the product. Is this an iPhone app? A website? Are you using AngularJS? C#? Make sure these are all considered so that you avoid proposing solutions that wouldn’t work.
  • Outline the process flow.

    You need to know the road map. For UI design, that would be the process flow for the user’s experience. This might come in the form of storyboards, journey maps or other ways of describing the process, but everyone should be familiar with it before considering the UI.
  • Demo the product, but show more than tell.

    I cannot stress this one enough: A great user experience has a lot more showing than telling. The end user will need to know exactly how the product works with minimal explanation. Your demo should also require as little explanation as possible. As the saying goes, a good UI is like a joke: If you have to explain it, it’s not very good.

Asking The Right Questions Link

Plenty of questions7 and statements8 work against strong cooperation in a design critique. Here are a few questions that I have found open dialogue for exploring designs in a collaborative, rather than combative, way, which you can suggest to your team.

Ask More Questions.9
The key is to ask the right questions. (Image: Jonathan Simcoe10) (View large version11)

“How Did You Come Up With That Solution?” Link

A great place to start any critique or conversation is to ask the designer how — not why — they did something. Asking why immediately puts them on the defensive, while asking how invites exploration of the concept’s origin without the need for justification.

Description of the image.12
Finding answers is easy. Asking the right questions is hard. (Image: Jason CranfordTeague13) (View large version14)

“Why” questions push us towards trying to prove something is “true,” rather than explaining it as one possibility. According to Aaron Morton15:

“Why” elicits a story, explanations of why something is true. If you ask why nothing is working out the way you want it to, you are likely to create a story, which may or may not be true. This is dangerous territory in making you feel bad.

Instead of asking “why,” consider asking “how” questions to elicit a story about the process of creation, rather than a defence of its existence. From there, you can then ask what possibilities the designer considered before, and only then explore alternatives they may not have considered. But listen carefully to what the designer has already tried before offering suggestions. They may have overlooked something, but don’t go into the conversation assuming so.

“Where Did You Get the Idea To Do It That Way?” Link

Thomas Edison famously said, “Genius is one percent inspiration and ninety-nine percent perspiration.” But he largely stole his one percent from Nikola Tesla. Then again, Picasso said, “Good artists borrow, great artists steal” (but he probably stole that line).

A central idea of Pixar Animation president Ed Catmull16’s book Creativity, Inc is that having a great team is more important than having a great idea:

Getting the right people and the right chemistry is more important than getting the right idea.

We rarely conceive ideas in a vacuum, and thinking about where we got our inspiration from can push our own innovation. Even better, bringing our inspirations together in a team setting can spawn new ideas.

A word of caution: Be careful not to sound accusatory or condescending — i.e. implying they stole the idea. Though, you do want the designer to push their own understanding of the motivations for their ideas and where they came from, without squishing the innovation.

“When Does That Need to Happen?” Link

Just like in comedy, timing is everything in temporal design17, and events need to happen at the right time and in the right order. When we are designing, though, that order is not always obvious until we have to sit down and explain it.

A great UI is like a great story, and that means you have to carefully pace it. How much information is just enough to get started with a form? Are you displaying data in the right context for the user to understand? Is this the right moment to reveal the conclusion?

Jason Kunesh, CEO of Public Good18, a startup that helps nonprofits connect with people through the news, tells me:

For our customers, a great interaction at the right moment is the difference between a happy fan of the product or service and a lost opportunity to connect. Turning a casual interaction into a lasting relationship depends on a series of tiny, positive interactions and messages arriving when people are ready for them.

Part of the critique process should be to iron out the wrinkles in the timing of the interface by asking at every opportunity whether this is the right moment to perform an action, ask a question or present data.

“Can We Use Motion to Add Visual Cues?” Link

This question will surprise a lot of designers who are used to the static nature that has dominated UI design for years. However, movement, animation and transitions are becoming the norm in experience design. Motion will soon be as important to consider in a design as color.

Animated UI.19
Motion is as important as color in modern UI design. (Image: Jakub Antalík20) (View large version21)

According to UI animation expert Rachel Neighbors22:

With the rise of flat design and the UX stumbles that have come with it, we’ve seen just how dangerous it can be to strip visual cues from a site’s components. Animation can be used to the opposite effect.

Movement or change could be as simple as a change in opacity or color, or a monkey’s arm stretching across the page, or a sun rising as the user completes a task. Asking about adding moment-to-moment movement in a UI design will often push the designer to change their perspective in good ways. Push the designer to think beyond the discrete moment and to discuss the design in time, not just in space.

“How Could We Make It Simpler?” Link

Simplicity is hard. It seems like adding is always easier than taking away, and many UIs suffer from what I like to call the “snowflake in a blizzard” syndrome: Sure, every snowflake is unique, but you’ll never notice that in a blizzard. In UI design, we all too often see interfaces chockablock full of links, buttons, controls and images. Clients will often think they need to include everything the audience might ever need, to the point that you can’t find anything you actually need.

Simple.23
Reduce noise and clutter. (Image: Bench24) (View large version25)

I put the simplicity question to Steve Krug, author of Don’t Make Me Think26:

I think it’s a very useful question. I would have thought it’s a lesson everyone’s absorbed by now, but I know they haven’t. I always like to say that anything on the page or screen that’s not part of the solution — for the user’s real goals — is noise and a candidate for being thrown overboard.

At every step in a design, we need to ask ourselves, How can we create something that requires less thought yet keeps the same power? In a critique, this is best expressed by asking how to make something simpler. It’s important to maintain clarity in the design, but to do so with fewer clicks, less text and not as many form fields. Get down to the bare minimum needed to get the job done, and your users will thank you.

“What Happens Next?” Link

A great design critique shares a lot in common with a great interview: They are both about exploration. One of the greatest interviewers, Studs Terkel, said27:

[Interviewing] isn’t an inquisition; it’s an exploration, usually an exploration into the past. So I think the gentlest question is the best one, and the gentlest is, “And what happened then?”

Applying this to a UI design, we always need to ask the designer to think about what happens next. This question invites them to think beyond what they considered to be the end. Users must always have somewhere to go next.

One of the greatest challenges to envisioning any UI is to consider all of the possible paths, not just the “happy path” we want the user to take. What happens after they click a button? What happens if there is an error? What happens after they submit a form? Ask what happens next until you’ve considered every possible scenario, otherwise you run the risk of leaving the user hanging, which is always a bad experience.

Don’t Just Ask Questions to Answer Them Link

When asking these questions — or any others for that matter — don’t ask simply so that you can answer yourself. It is annoying when someone asks you a question not to hear your answer or to understand your thinking but simply to hear their own voice.

Blank Notebook.28
Be ready to take notes and listen. (Image: Luis Llerena29) (View large version30)

If you are one of those people, cut it out immediately. Ask all of your questions with your mind wide open to the answers given. Then, craft your responses based on those answers, not the answers you wanted to hear.

What A Good UI Critique Looks Like Link

Critiques will vary greatly depending on the skills, goals and responsibilities of the participants. However, a good critique always focuses on specific aspects of the product and thoroughly explores the presented solution.

A UI critique focuses not just on what the product looks like at the moment, but on how it works over time and whether this best suits the user’s needs. Rather than considering the user’s needs, participants will often wonder why something wasn’t done the way they expected. Jason Ulaszek of UX for Good31 agrees, telling me about his own critiques:

Staying objective in our discussion and considering the mental model of the individual tasked with using the design [i.e. the user] is critical in how we discuss the solution.

Always keep in mind that — like cell-based animation, where a second’s worth of the final film could take weeks or months to produce — while we might spend hours agonizing over a minute detail in the interface, it will probably be just a blip on the user’s radar.

CCTV Cams.32
The whole team needs to be looking in the same direction. (Image: Matthew Wiebe33) (View large version34)

Steve Krug had this to say when I asked him about this:

We’re thinking, “great literature” (or at least “product brochure”), while the user’s reality is much closer to “billboard going by at 60 miles an hour.” It’s incredibly hard for UI designers to realize just how quickly people are zooming through — or past — the interface they’ve worked so hard to develop, and how little of it they actually take in.

A good UI critique slows down to consider every element, but recognizes that this is not how the user will be seeing the design. If the participants in your critique do not have formal training to speak directly to color, typography or experience design, they can still consider these important factors in all UI designs:

  • Consistency

    Are the design and its implementation consistent throughout the product? This includes color, typography, controls, imagery and any design element (static or interactive) that is used more than once in the interface.
  • Context

    Have you consistently respected the context of the user as they are using the product? Constantly asking this question is key because you are likely not in that context, but merely simulating it, while designing or testing.
  • Voice

    Do the brand and design have a clear, consistent and recognizable voice?
  • Transitions

    Are you using transitions from state to state for any significant changes in the UI? Modern designs are about far more than the visual. Consider how all interface elements move and change during the user’s interaction.
  • Simplicity

    Is the design as simple as it can be to get the job done?

Avoiding Hostile Critiques Link

Critiques can be — and often are — done in a pugnacious way, where members of the team, for whatever reason, are inclined to criticize the work without listening to the thought process that went into its creation. They bring their own biases to the design, rather than consider the user, and they often just try to show how clever they are.

You can always tell when a critique becomes overly aggressive: The designer tends to become prickly about their decisions, rather than explain how they arrived at them and discuss alternatives. The key to avoiding aggressive critiques is to set out clear principles and ask open-ended, constructive questions. Remember that the idea is to strengthen the design collaboratively, not to win a design battle.

I find aggressive critiques to be unhelpful and usually harmful. Antagonistic critiques force the designer into a defensive posture, entrenching them in what they have done, rather than empowering them to expand it. Design is — to a very large extent — intuitive and not always easily qualifiable, much less quantifiable.

However, that does not mean the critique is purely about the designer’s opinion; it is about the designer’s well-informed opinion gained through years of study. Web producer Phillip Djwa35 of Agentic feels that the key is to…

… speak from my experience, and not try to generalize. For example, I would ask, “I wonder whether the opening banner is communicating enough of the brand?” instead of, “Wow, people will never understand what brand value we have.”

Final Word: A Critique Is Not Usability Testing Link

It’s easy to trick yourself into thinking that you speak for the audience, either through the use of personas or your own biases. No matter how many personas you create or critiques you run through, you are not your audience. Steve Krug tells me:

This is one reason why I think every designer should spend time watching people try to use what they’ve built (aka usability tests).

Toolchest.36
A design critique is just one tool in your UX toolchest. (Image: Todd Quackenbush37) (View large version38)

Just like a laser level39 versus a bubble level, usability testing is more precise and accurate than internal critiques, but also generally more time-consuming and expensive. Regular design critiques are invaluable for keeping a project on target but can never replace getting out in the field and testing with real-life users. Otherwise, all you are doing is talking to yourself.

(ah, al, il)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/wp-content//uploads/2016/08/create-opt.jpeg
  2. 2 https://unsplash.com/@bamagal
  3. 3 https://www.smashingmagazine.com/wp-content//uploads/2016/08/create-opt.jpeg
  4. 4 https://www.smashingmagazine.com/wp-content//uploads/2016/08/critique-opt.jpg
  5. 5 http://cranfordTeague.com/
  6. 6 https://www.smashingmagazine.com/wp-content//uploads/2016/08/critique-opt.jpg
  7. 7 https://medium.com/jasonspeaking-report/6-seemingly-innocent-questions-guaranteed-to-kill-creativity-c4d35aa8f2cd#.kbk4wne2l
  8. 8 https://medium.com/jasonspeaking-report/6-statements-that-kill-ui-creativity-f0a8384a63aa#.ahc7de9j9
  9. 9 https://www.smashingmagazine.com/wp-content//uploads/2016/08/questions-opt.jpeg
  10. 10 https://unsplash.com/@jdsimcoe
  11. 11 https://www.smashingmagazine.com/wp-content//uploads/2016/08/questions-opt.jpeg
  12. 12 https://www.smashingmagazine.com/wp-content//uploads/2016/08/solution-opt.jpg
  13. 13 http://cranfordteague.com/
  14. 14 https://www.smashingmagazine.com/wp-content//uploads/2016/08/solution-opt.jpg
  15. 15 http://lateralaction.com/articles/creative-questions
  16. 16 http://waltdisneystudios.com/corp/unit/6/bio/53
  17. 17 https://medium.com/jasonspeaking-report/temporal-design-thinking-8b37e2879d08#.u8qxa5do8
  18. 18 https://publicgood.com/
  19. 19 https://www.smashingmagazine.com/wp-content//uploads/2016/08/goals-animation.gif
  20. 20 https://dribbble.com/antalik
  21. 21 https://www.smashingmagazine.com/wp-content//uploads/2016/08/goals-animation.gif
  22. 22 http://rachelnabors.com/
  23. 23 https://www.smashingmagazine.com/wp-content//uploads/2016/08/simple-opt.jpg
  24. 24 https://unsplash.com/@benchaccounting
  25. 25 https://www.smashingmagazine.com/wp-content//uploads/2016/08/simple-opt.jpg
  26. 26 https://www.sensible.com/
  27. 27 http://www.nytimes.com/2008/11/01/books/01terkel.html
  28. 28 https://www.smashingmagazine.com/wp-content//uploads/2016/08/notes-opt.jpeg
  29. 29 https://unsplash.com/@albertosaure
  30. 30 https://www.smashingmagazine.com/wp-content//uploads/2016/08/notes-opt.jpeg
  31. 31 http://www.uxforgood.com
  32. 32 https://www.smashingmagazine.com/wp-content//uploads/2016/08/looks-opt.jpeg
  33. 33 https://unsplash.com/@matthewwiebe/
  34. 34 https://www.smashingmagazine.com/wp-content//uploads/2016/08/looks-opt.jpeg
  35. 35 http://www.agentic.ca/studio/phillip-djwa
  36. 36 https://www.smashingmagazine.com/wp-content//uploads/2016/08/tools-opt.jpg
  37. 37 https://unsplash.com/@toddquackenbush
  38. 38 https://www.smashingmagazine.com/wp-content//uploads/2016/08/tools-opt.jpg
  39. 39 http://www.dewalt.com/en-us/products/hand-tools/measuring-and-layout-tools/self-leveling-line-lasers/12v-max-compatible-red-cross-line-laser/dw088lr
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Web Development Reading List #149: CSS Dynamic Colors, Refactoring CSS, And CSP Hashing

artificial intelligence 5291510 1920

Web Development Reading List #149: CSS Dynamic Colors, Refactoring CSS, And CSP Hashing

Even though we think everything happens in real-time nowadays, we need patience. While technology has been capable of real-time for long now, the “bottleneck” are human beings. Whether it’s a pull request that’s waiting for review since days or weeks or an email response, we need to keep in mind that delays might happen for a good reason.

Different people have different priorities, they might be focusing on something else at the moment, or they just take a break. Training patience is an important aspect of mental health, and, in the end, a well-thought-out, not instantly written feedback is better, too. Take your time and let others do the same.

To my readers in or near Germany: Some of you might be aware that I organize a small event, and this week I have one ticket to give away for the NightlyBuild conference 20161 in Cologne, Germany on September, 2nd. If you want to attend, just send me an email2, and I’ll raffle the ticket on Tuesday.

News Link

Privacy Link

  • While researching a bit on user tracking, I found out about header enrichment, a technique used by mobile network providers to set unique identifiers. But more interestingly, while it’s advised by the IETF to not expose any of these headers to public servers, many ISPs do it anyway and leak the private IP addresses of devices, the IMEI/IMSI or even the phone number, to any server. This research paper4 by the ICSI analyzed the worldwide spread and impact on users’ privacy.
  • Many of you might be aware that we can’t style :visited states and similar browser-history-based features in CSS very well. With CSS’ new mix-blend-mode-feature there seems to be a leak again that lets rogue sites inspect your browsing history. Michał Zalweski explains how it works5.
  • Netflix engineers now share insights into how they protect the viewing privacy6 of their users by adding TLS to their video streams, which at that scale is a pretty challenging and interesting problem.

JavaScript Link

CSS/Sass Link

13
Clipping and masking allows for interesting ways to show or hide pieces of your graphics. Abbey Fitzgerald explains how to do it with CSS and SVG14.

Work & Life Link

  • Today I read an interesting statement about constant learning15 (see the blockquote below) with which I fundamentally disagree. So instead of following this advice, I want to encourage you to take a break from constant learning every few days. There are reasons why you should rest on a weekend and recover from learning new things during the week: By taking a break, you’ll eagerly await learning something new afterwards.
  • “In today’s highly competitive business environment, we all need to be in constant learning mode. No one can afford to take a vacation from developing new skills, especially as economic and political uncertainty threaten businesses and job stability and make future career prospects unclear.”

  • Rose Marcario, CEO of Patagonia, has published an essay on why it’s important that employers support families16. It’s not just about saying this but about taking meaningful, real action to make employees feel comfortable, have a good life, and enjoy working for their employer.

Going Beyond… Link

  • The NASA started a new blog called “Science WOW!17” which shares educational articles on science each week. If you’re interested in learning how hurricanes form or about space exploration stuff, this might be for you.

And with that, I’ll close for this week. If you like what I write each week, please support me with a donation18 or share this resource with other people. You can learn more about the costs of the project here19. It’s available via email, RSS and online.

— Anselm

Footnotes Link

  1. 1 https://nightlybuild.io/
  2. 2 mailto:mail@wdrl.info
  3. 3 https://webkit.org/blog/6830/a-refined-content-security-policy/
  4. 4 https://www.icsi.berkeley.edu/pubs/networking/headerenrichment15.pdf
  5. 5 https://lcamtuf.blogspot.de/2016/08/css-mix-blend-mode-is-bad-for-keeping.html
  6. 6 http://techblog.netflix.com/2016/08/protecting-netflix-viewing-privacy-at.html
  7. 7 https://css-tricks.com/image-upload-manipulation-react/
  8. 8 http://qfox.nl/weblog/371
  9. 9 http://qfox.nl/weblog/361
  10. 10 https://cloudfour.com/thinks/building-themes-with-css4-color-features/
  11. 11 https://getflywheel.com/layout/css-svg-clipping-and-masking-techniques/
  12. 12 https://speakerdeck.com/csswizardry/refactoring-css-without-losing-your-mind
  13. 13 https://getflywheel.com/layout/css-svg-clipping-and-masking-techniques/
  14. 14 https://getflywheel.com/layout/css-svg-clipping-and-masking-techniques/
  15. 15 http://further.net/tricky-goals/
  16. 16 https://www.linkedin.com/pulse/why-should-employers-care-families-rose-marcario
  17. 17 https://blogs.nasa.gov/educationsciencewow/
  18. 18 https://wdrl.info/donate
  19. 19 https://wdrl.info/costs/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

A Beginner’s Guide To Progressive Web Apps

artificial intelligence 5291510 1920

A Beginner’s Guide To Progressive Web Apps

Progressive web apps could be the next big thing for the mobile web. Originally proposed by Google in 2015, they have already attracted a lot of attention because of the relative ease of development and the almost instant wins for the application’s user experience.

A progressive web application takes advantage of the latest technologies to combine the best of web and mobile apps. Think of it as a website built using web technologies but that acts and feels like an app. Recent advancements in the browser and in the availability of service workers and in the Cache and Push APIs have enabled web developers to allow users to install web apps to their home screen, receive push notifications and even work offline.

Progressive web apps take advantage of the much larger web ecosystem, plugins and community and the relative ease of deploying and maintaining a website when compared to a native application in the respective app stores. For those of you who develop on both mobile and web, you’ll appreciate that a website can be built in less time, that an API does not need to be maintained with backwards-compatibility (all users will run the same version of your website’s code, unlike the version fragmentation of native apps) and that the app will generally be easier to deploy and maintain.

Why Progressive Web Apps? Link

A study has shown that, on average, an app loses 20%1 of its users for every step between the user’s first contact with the app and the user starting to use the app. A user must first find the app in an app store, download it, install it and then, finally, open it. When a user finds your progressive web app, they will be able to immediately start using it, eliminating the unnecessary downloading and installation stages. And when the user returns to the app, they will be prompted to install the app and upgrade to a full-screen experience.

However, a native app is definitely not all bad. Mobile applications with push notifications achieve up to three times more retention2 than their counterparts without push, and a user is three times more likely to reopen a mobile application than a website. In addition, a well-designed mobile application consumes less data and is much faster because some resources reside on the device.

A progressive web application takes advantage of a mobile app’s characteristics, resulting in improved user retention and performance, without the complications involved in maintaining a mobile application.

Use Cases Link

When should you build a progressive web app? Native is usually recommended for applications that you expect users to return to frequently, and a progressive web app is not any different. Flipkart3 uses a progressive web app for its popular e-commerce platform, Flipkart Lite, and Air Berlin4 uses a progressive web app for its online check-in process, allowing users to access their tickets without an Internet connection.

When assessing whether your next application should be a progressive web app, a website or a native mobile application, first identify your users and the most important user actions. Being “progressive,” a progressive web app works in all browsers, and the experience is enhanced whenever the user’s browser is updated with new and improved features and APIs.

Thus, there is no compromise in the user experience with a progressive web app compared to a traditional website; however, you may have to decide what functionality to support offline, and you will have to facilitate navigation (remember that in standalone mode, the user does not have access to the back button). If your website already has an application-like interface, applying the concepts of progressive web apps will only make it better.

If certain features are required for critical user actions but are not yet available due to a lack of cross-browser support5, then a native mobile application might be the better option, guaranteeing the same experience for all users.

Characteristics Of A Progressive Web App Link

Before we jump into the code, it is important to understand that progressive web apps have the following characteristics6:

  • Progressive

    By definition, a progressive web app must work on any device and enhance progressively, taking advantage of any features available on the user’s device and browser.
  • Discoverable

    Because a progressive web app is a website, it should be discoverable in search engines. This is a major advantage over native applications, which still lag behind websites in searchability.
  • Linkable

    As another characteristic inherited from websites, a well-designed website should use the URI to indicate the current state of the application. This will enable the web app to retain or reload its state when the user bookmarks or shares the app’s URL.
  • Responsive

    A progressive web app’s UI must fit the device’s form factor and screen size.
  • App-like

    A progressive web app should look like a native app and be built on the application shell model, with minimal page refreshes.
  • Connectivity-independent

    It should work in areas of low connectivity or offline (our favorite characteristic).
  • Re-engageable

    Mobile app users are more likely to reuse their apps, and progressive web apps are intended to achieve the same goals through features such as push notifications.
  • Installable

    A progressive web app can be installed on the device’s home screen, making it readily available.
  • Fresh

    When new content is published and the user is connected to the Internet, that content should be made available in the app.
  • Safe

    Because a progressive web app has a more intimate user experience and because all network requests can be intercepted through service workers, it is imperative that the app be hosted over HTTPS to prevent man-in-the-middle attacks.

Let’s Code! Link

Our first progressive web app, Sky High, will simulate an airport’s arrivals schedule. The first time the user accesses our web app, we want to show them a list of upcoming flights, retrieved from an API. If the user does not have an Internet connection and they reload the web app, we want to show them the flight schedule as it was when they last downloaded it with a connection.

7
Sky High, our fictitious progressive web app (Large preview8)

The Basics Link

The first characteristic of a progressive web app is that it must work on all devices and must enhance on devices and browsers that allow it. Therefore, we’ve built our website using traditional HTML5 and with JavaScript that simulates the retrieval of data from a mock API. Throughout the application, we are using small bits of Knockout9 to handle our Model-View-ViewModel (MVVM) bindings — a lightweight JavaScript framework that allows us to bind our JavaScript models to our HTML views. We chose to use Knockout because it is relatively simple to understand and does not clutter the code; however you may replace this with any other framework, such as React or AngularJS.

Our website follows Google’s material design10 guidelines, a set of principles that guide design and interaction. Material design not only serves as a unified standard across applications and devices, but also gives design meaning. We’ve used material design for Sky High’s arrivals view to give our progressive web app that native-app look and feel.

Finally, we tested our app to make sure it is jank-free11 and that scrolling is silky-smooth. Jank-free rendering has been shown to improve user engagement. Aim for a rendering of 60 frames per second.

For this demo, we will retrieve a static JSON file, instead of a real API. This is merely to keep things simple. In the real world, you would query an API or use WebSockets.

index.html Link

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Sky-High Airport Arrivals</title> <link async rel="stylesheet" href="./css/style.css"> <link href="https://fonts.googleapis.com/css?family=Roboto:300,600,300italic,600italic" rel="stylesheet" type="text/css"> </head> <body> <header> <div> <h3>Arrivals</h3> </div> </header> <div> <div> <ul data-bind="foreach: arrivals"> <li> <span data-bind="html: title"></span> <span data-bind="html: status"></span> <span data-bind="html: time"></span> </li> </ul> </div> </div> <script src="./js/build/vendor.min.js"></script> <script src="./js/build/script.min.js"></script> </body> </html>

The index.html file is relatively standard. We’ve created an HTML list and bound our View Model property arrivals to it using Knockout12, through the attribute data-bind="foreach: arrivals". The View Model arrivals is declared in the page.js file below and exposed in the Page module. On our HTML page, for each item in the arrivals array, we’ve bound the title, status and time properties to the HTML view.

page.js Link

(var Page = (function() { // declare the view model used within the page function ViewModel() { var self = this; self.arrivals = ko.observableArray([]); } // expose the view model through the Page module return { vm: new ViewModel(), hideOfflineWarning: function() { // enable the live data document.querySelector(".arrivals-list").classList.remove('loading') // remove the offline message document.getElementById("offline").remove(); // load the live data }, showOfflineWarning: function() { // disable the live data document.querySelector(".arrivals-list").classList.add('loading') // load html template informing the user they are offline var request = new XMLHttpRequest(); request.open('GET', './offline.html', true); request.onload = function() { if (request.status === 200) { // success // create offline element with HTML loaded from offline.html template var offlineMessageElement = document.createElement("div"); offlineMessageElement.setAttribute("id", "offline"); offlineMessageElement.innerHTML = request.responseText; document.getElementById("main").appendChild(offlineMessageElement); } else { // error retrieving file console.warn('Error retrieving offline.html'); } }; request.onerror = function() { // network errors console.error('Connection error'); }; request.send(); } } })();

This page.js file exposes the Page module, which contains our ViewModel vm and two functions, hideOfflineWarning and showOfflineWarning. The View Model ViewModel is a simple JavaScript literal that will be used throughout the application. The property arrivals on the ViewModel is Knockout’s observableArray, which automatically binds our HTML to a JavaScript array, allowing us to push and pop items onto our array in JavaScript and automatically update the page’s HTML.

The functions hideOfflineWarning and showOfflineWarning enable the rest of our application to call these functions to update the page’s UI that displays whether we are connected online. The showOfflineWarning adds a class of loading to our arrivals-list HTML element to fade the list, and then it retrieves the HTML file offline.html through XHR. Assuming that the file has been retrieved successfully (response.status === 200), we append this to our HTML. Of course, if we aren’t using service workers13 and the user is not connected to the Internet, then it would not be possible to retrieve offline.html, and so the user would see the browser’s offline page.

The business logic from where we retrieve the data from our API and bind it to our View Models and Views is found in arrivals.js14 and is standard MVVM functionality using Knockout. In the arrivals.js file, we simply initialize the services and View Models that we will be using throughout the application, and we expose a function — Arrivals.loadData() — that retrieves the data and binds it to the view model.

Web App Manifest Link

Let’s make our web app more app-like. A web app manifest file is a simple JSON file that follows the W3C’s specification15. With it, it is possible to run the web app in full-screen mode as a standalone application, to assign an icon that will get displayed when the application is installed on the device, and to assign a theme and background color to the app. In addition, Chrome on Android will proactively suggest that the user install the web app, via a web app install banner16. To display the installation prompt, your web app needs to:

  • have a valid web app manifest file,
  • be served over HTTPS,
  • have a valid service worker registered,
  • have been visited twice, with at least five minutes between each visit.
Web app install banner17
Web app install banner (View large version18)

manifest.json Link

{ "short_name": "Arrivals", "name": "Arrivals at Sky High", "description": "Progressive web application demonstration", "icons": [ { "src": "launcher-icon.png", "sizes": "48x48", "type": "image/png" }, { "src": "launcher-icon-96.png", "sizes": "96x96", "type": "image/png" }, { "src": "launcher-icon-144.png", "sizes": "144x144", "type": "image/png" }, { "src": "launcher-icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "launcher-icon-256.png", "sizes": "256x256", "type": "image/png" } ], "start_url": "./?utm_source=web_app_manifest", "display": "standalone", "orientation": "portrait", "theme_color": "#29BDBB", "background_color": "#29BDBB" }

Let’s break down this manifest file:

  • short_name is a human-readable name for the application. In Chrome for Android, this is also the name accompanying the icon on the home screen.
  • name is also a human-readable name for the application and defines how the application will be listed.
  • description provides a general description of the web application.
  • icons defines an array of images of varying sizes that will serve as the application’s icon set. In Chrome for Android, the icon will be used on the splash screen, on the home screen and in the task switcher.
  • start_url is the starting URL of the application.
  • display defines the default display mode for the web application: fullscreen, standalone, minimal-ui or browser.
  • orientation defines the default orientation for the web application: portrait or landscape.
  • theme_color is the default theme color for the application. On Android, this is also used to color the status bar.
  • background_color defines the background color of the web application. In Chrome, it also defines the background color of the splash screen.
  • related_applications is not implemented in our example but is used to specify native application alternatives in the various app stores.

Add the manifest.json reference to the index.html file’s head tag:

<link rel="manifest" href="./manifest.json">

Once a user has added the web app to their home screen, they will be able to re-engage with your application immediately from their device, without having to directly open the browser. You can see how this is much more than a web bookmark.


Add to home screen in Chrome for Android

Service Workers

One of the more exciting aspects of progressive web apps is that they can work offline. Using service workers, it is possible to show data that was retrieved in previous sessions of the app (using IndexedDB19) or, alternatively, to show the application shell and inform the user that they are not connected to the Internet (the approach we’ve taken in this demo). Once the user reconnects, we can then retrieve the latest data from the server.

All of this is possible through service workers, which are event-driven scripts (written in JavaScript) that have access to domain-wide events, including network fetches. With them, we can cache all static resources, which could drastically reduce network requests and improve performance considerably, too.

Application Shell Link

The application shell is the minimum HTML, CSS and JavaScript required to power a user interface. A native mobile application includes the application shell as part of its distributable, whereas websites ordinarily request this over the network. Progressive web applications bridge this gap by placing the application shell’s resources and assets in the browser’s cache. In our Sky High application, we can see that our application shell consists of the top header bar, the fonts and any CSS required to render these elegantly.

To get started with service workers, we first need to create our service worker’s JavaScript file, sw.js, placed in the root directory.

sw.js Link

// Use a cacheName for cache versioning var cacheName = 'v1:static'; // During the installation phase, you'll usually want to cache static assets. self.addEventListener('install', function(e) { // Once the service worker is installed, go ahead and fetch the resources to make this work offline. e.waitUntil( caches.open(cacheName).then(function(cache) { return cache.addAll([ './', './css/style.css', './js/build/script.min.js', './js/build/vendor.min.js', './css/fonts/roboto.woff', './offline.html' ]).then(function() { self.skipWaiting(); }); }) ); }); // when the browser fetches a URL… self.addEventListener('fetch', function(event) { // … either respond with the cached object or go ahead and fetch the actual URL event.respondWith( caches.match(event.request).then(function(response) { if (response) { // retrieve from cache return response; } // fetch as normal return fetch(event.request); }) ); });

Let’s look more closely at our service worker. First, we are setting a cacheName variable. This is used to determine whether any changes have been made to our cached assets. For this example, we will be using a static name, meaning that our assets will not change or require updating.

self.addEventListener('install', function(e) { // declare which assets to cache }

The install event fires during the installation phase of the service worker and will fire only once if the service worker is already installed. Therefore, refreshing the page will not trigger the installation phase again. During the installation phase, we are able to declare which assets will be cached. In our example above, we are caching one CSS file, two JavaScript files, our fonts file, our offline HTML template and, of course, the application root. self.skipWaiting() forces the waiting service worker to become active.

So far, we have declared our service worker, but before we see it kick into effect, we need to reference it in our JavaScript. In our application, we register it in main.js

// Register the service worker if available. if ('serviceWorker' in navigator) { navigator.serviceWorker.register('./sw.js').then(function(reg) { console.log('Successfully registered service worker', reg); }).catch(function(err) { console.warn('Error whilst registering service worker', err); }); } window.addEventListener('online', function(e) { // Resync data with server. console.log("You are online"); Page.hideOfflineWarning(); Arrivals.loadData(); }, false); window.addEventListener('offline', function(e) { // Queue up events for server. console.log("You are offline"); Page.showOfflineWarning(); }, false); // Check if the user is connected. if (navigator.onLine) { Arrivals.loadData(); } else { // Show offline message Page.showOfflineWarning(); } // Set Knockout view model bindings. ko.applyBindings(Page.vm); 

We’ve also included two event listeners to check whether the session’s state has changed from online to offline or vice versa. The event handlers then call the different functions to retrieve the data through Arrivals.loadData() and to enable or disable the offline message through Page.showOfflineWarning and Page.hideOfflineWarning, respectively. Our application also checks whether the user is currently online, using navigator.onLine20, and either retrieves the data or shows the offline warning accordingly. And in the last line of main.js, we apply the Knockout bindings to our View Model Page.vm.

If we load our application for the first time (with Chrome Developer Tools), we will see nothing new. However, upon reloading, we will see that a number of network resource have been retrieved from the service worker. This is our application shell.

Application shell21
Application shell network resources, in Chrome Developer Tools (View large version22)

Offline Test Link

A user running the application without an Internet connection (assuming that they have already been on the page) will simply result in the application shell and the offline warning being displayed — an improvement over Chrome’s prowling t-rex. Once the user has established a network connection, we disable the warning and retrieve the latest data.

Failing gracefully23
Render a custom HTML page instead of Chrome’s default page (View large version24)

The Guardian takes a particularly interesting approach when offline users access its website, providing a crossword puzzle:

The Guardian's offline crossword puzzle25
The Guardian’s offline crossword puzzle (View large version26)

Push Notifications Link

Push notifications allow users to opt in to timely updates from applications they trust, helping them to re-engage with the apps. Push notifications on the web27 allow you to engage with your audience even when the browser is closed.

Push notifications28
Push notifications on Emojoy29 (View large version30)

The Push API is supported in Chrome, Opera and Samsung’s browser and is under development in Firefox and Microsoft Edge. Unfortunately, there is no indication that the feature will be implemented in Safari.

Performance Link

One of the easiest wins with service workers is that we can improve performance with little to no effort. Comparing our website to itself before service workers were implemented, before we were retrieving over 200 KB upon page load; that is now reduced to 13 KB. On a regular 3G network, the page would have taken 3.5 seconds to load; now it takes 500 milliseconds.

These performance improvements are drastic because the application itself is very small and has limited functionality. Nevertheless, through the correct use of caching, it is possible to significantly improve performance and perceived performance, especially for users in places with low-connectivity.

Lighthouse Link

Google’s Chrome team has put together a tool for testing progressive web apps. Lighthouse31 runs in Node.js or as a Chrome plugin32 and can be found on GitHub, too.

To run a Lighthouse test, your website needs to be available online, meaning that you cannot test on localhost.

To start, download the npm package:

npm install -g GoogleChrome/lighthouse

Once that’s installed, run Chrome (version 52 onwards):

npm explore -g lighthouse -- npm run chrome lighthouse https://incredibleweb.github.io/pwa-tutorial/

The output of the Lighthouse run will be visible in the command line and will grade your website according to the progressive web app features and properties you have implemented — for example, whether you are using a manifest.json file or whether your page is available offline.

Conclusion Link

This article is merely an appetizer for progressive web apps. We could do a lot more to create that app-like experience users are looking for, whether by supporting push notifications with the Push API33, making the app re-engageable, or using IndexedDB and background syncing34 to improve the offline experience.

Cross-Browser Support

These are still early days for progressive web apps, and cross-browser support is still limited, especially in Safari and Edge. However, Microsoft openly supports progressive web apps and should be implementing more features by the end of the year.

  • Service workers and Cache API

    Supported in Chrome, Firefox, Opera and Samsung’s browser. In development in Microsoft Edge, expected to be available by the end of 2016. Under consideration for Safari.
  • Add to home screen

    Supported in Chrome, Firefox, Opera, Android Browser and Samsung’s browser. Microsoft seems to indicate that progressive web apps will be available as store listings. No plans for Safari as of yet.
  • Push API

    Mostly supported in Chrome, Firefox, Opera and Samsung’s browser. In development in Microsoft Edge. No plans for Safari as of yet.

If more developers take advantage of the features offered by progressive web apps — which are relatively easy to implement and provide immediate rewards — then users will prefer consuming these web apps in supported browsers, hopefully convincing the other browser vendors to adapt.

Source Code Link

The entire source code for this tutorial is available in a Github repository35, and the demo is available on GitHub Pages36.

(da, al, il)

Footnotes Link

  1. 1 http://blog.gaborcselle.com/2012/10/every-step-costs-you-20-of-users.html
  2. 2 http://info.localytics.com/blog/push-messaging-drives-88-more-app-launches-for-users-who-opt-in
  3. 3 http://www.flipkart.com/
  4. 4 https://flights.airberlin.com/en-DE/progressive-web-app
  5. 5 #crossBrowser
  6. 6 https://developers.google.com/web/fundamentals/getting-started/your-first-progressive-web-app/
  7. 7 https://www.smashingmagazine.com/wp-content//uploads/2016/08/sky-high-screenshot-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content//uploads/2016/08/sky-high-screenshot-opt.png
  9. 9 http://knockoutjs.com/
  10. 10 https://material.google.com/
  11. 11 https://addyosmani.com/blog/making-a-site-jank-free/
  12. 12 http://knockoutjs.com/documentation/introduction.html
  13. 13 #serviceWorker
  14. 14 https://github.com/IncredibleWeb/pwa-tutorial/blob/master/demo/js/arrivals.js
  15. 15 https://w3c.github.io/manifest/
  16. 16 https://developers.google.com/web/updates/2015/03/increasing-engagement-with-app-install-banners-in-chrome-for-android
  17. 17 https://www.smashingmagazine.com/wp-content//uploads/2016/08/web-app-install-banner-opt.png
  18. 18 https://www.smashingmagazine.com/wp-content//uploads/2016/08/web-app-install-banner-opt.png
  19. 19 https://developer.mozilla.org/en/docs/Web/API/IndexedDB_API
  20. 20 https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine
  21. 21 https://www.smashingmagazine.com/wp-content//uploads/2016/08/app-shell-opt.png
  22. 22 https://www.smashingmagazine.com/wp-content//uploads/2016/08/app-shell-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content//uploads/2016/08/sky-high-offline-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content//uploads/2016/08/sky-high-offline-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content//uploads/2016/08/the-guardian-opt.jpg
  26. 26 https://www.smashingmagazine.com/wp-content//uploads/2016/08/the-guardian-opt.jpg
  27. 27 https://developers.google.com/web/updates/2015/03/push-notifications-on-the-open-web
  28. 28 https://www.smashingmagazine.com/wp-content//uploads/2016/08/pwa-push-opt.png
  29. 29 https://jakearchibald-gcm.appspot.com/
  30. 30 https://www.smashingmagazine.com/wp-content//uploads/2016/08/pwa-push-opt.png
  31. 31 https://github.com/GoogleChrome/lighthouse
  32. 32 https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk
  33. 33 https://developer.mozilla.org/en/docs/Web/API/Push_API
  34. 34 https://developers.google.com/web/updates/2015/12/background-sync
  35. 35 https://github.com/IncredibleWeb/pwa-tutorial
  36. 36 https://incredibleweb.github.io/pwa-tutorial/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Experience Design Essentials: Animated Microinteractions In Mobile Apps

artificial intelligence 5291510 1920

Sponsored ArticleExperience Design Essentials: Animated Microinteractions In Mobile Apps

Dariel Fitzkee, the famous magician, once said, “Magic is both in the details and in the performance.” Interaction design is just like that. Designers love to get the big picture right, but if the details aren’t handled properly, the solution will fail. The magic is all in the details. That’s why well-designed microinteractions make experiences feel crafted.

To get a better understanding of how your design benefits from microinteractions, it will help to sketch out your app ideas. Adobe introduced a new design and wireframing app called Experience Design (or Adobe XD) which lets you design wireframes and make them interactive. You can download and test Adobe XD1for free.

Further Reading on SmashingMag Link

Show System Status Link

Jakob Nielsen’s first heuristic for UI design states, “The system should always keep users informed about what is going on, through appropriate feedback in a reasonable time.” This means that the user interface should keep the user abreast of what is happening by providing feedback. The app shouldn’t keep the user guessing — it should tell the user what’s happening, and microinteractions can help you make that known via appropriate visual feedback.

Data uploading and downloading processes are great opportunities for creative animated microinteractions.

4
Data downloading animation (Image: Nick Buturishvili5)

Another well-known animation for this group is “pull down to refresh,” which initiates a process of content updates on mobile devices. A cheerful refresh animation can make users chuckle.

microtwo26
Pull down to refresh (Image: Toma Reznichenko7)

Takeaway: Animation provides real-time notification of an app’s process status, enabling the user to quickly understand what is going on.

Make Buttons And Controls Tangible Link

User interface elements such as buttons and controls should appear tangible, even though they are behind a layer of glass. Visual and motion cues can bridge this gap by acknowledging input immediately and animating in ways that look and feel like direct manipulation. UI buttons can mimic interaction with common physical objects. Simply put, you can add clarity through visual responses to the user’s input.

microtwo38
(Image: Google9)

Takeaway: Visual feedback works because it appeals to the user’s natural desire for acknowledgement. It just feels good to click through an app and always feel like you know what’s happening.

Build Meaningful Transitions Link

You can use animation to smoothly transport users between navigational contexts, to explain changes in the arrangement of elements on a screen or to reinforce an element’s hierarchy.

Icons can morph from one shape to another, serving dual functions at different times.

microtwo410
(Image: Google11)

Motion design can effectively guide the user’s attention in ways that both inform and delight. This is especially good for mobile devices and smartwatches because it’s impossible to fit a lot of information on those screens.

Apple’s iOS UI is a good example of meaningful transitions. In the example below, the user selects a folder or app and is zoomed into its detailed view (or directly to the app’s main screen).

microtwo512
(Image: Rian Van Der Merwe13)

Another good example is animation that creates visual connections between two states through color and persistent elements. This makes transitions smooth and effortless.

microtwo614
(Image: Ehsan Rahimi15)

Takeaway: Microinteractions can establish a visual connection between pages and add clarity to the UI.

Help The User Get Started Link

Microinteractions are very helpful during onboarding. Flawless UX and animations in the onboarding flow can have a tremendous impact on how first-time users engage with the app. They guide and educate users after the launch of an app by highlighting the most important features and controls.

microtwo716
Smooth onboarding (Image: Ramotion17)

Takeaway: Microinteractions reveal information and help the user to efficiently reach their goal.

Highlight Changes In The UI Link

Microinteractions can direct the user’s attention. In many cases, animation is used to attract their attention to an important detail (such as a notification). However, be sure that the animation serves a functional purpose and is appropriate to your users.

microtwo818
Notification (Image: Arjun Kani19)

Takeaway: Microinteractions can be good visual cues for the user.

Add Delightful Details Link

The most basic use of a microinteraction animation is in transitions. However, an app can truly delight users when animation is used in ways beyond the standard scope of actions. The button below seamlessly changes states and serves dual functions: to inform the user and to create a moment of wonder.

microtwo920
Social media sharing (Image: Kei Sato21)

Takeaway: Focus on user emotions, which play a huge role in UI interactions.

What To Consider When Designing Microinteractions Link

When you create a visual design containing the elements discussed above, keep a few things in mind:

  • Make microinteractions almost invisible and completely functional.

    Make sure the animations fit a functional purpose and do not feel awkward or annoying. For frequent and minor actions, the response can be modest, while for infrequent and major actions, the response should be more substantial.
  • Keep longevity in mind.

    Microinteractions must survive long-term use. What seems fun the first time might become annoying after the hundredth use.
  • Follow the KISS principle22.

    Over-designing a microinteraction can be lethal. Microinteractions shouldn’t overload the screen and cause a long process of loading. Rather, they should save time by instantly communicating valuable information.
  • Don’t start from zero.

    You will almost always know something about your target audience and their context. Use that knowledge to make your microinteractions more precise and effective.
  • Create visual harmony with the other UI elements.

    Microinteractions should match the general style of the application, supporting a harmonious perception of the product.

Conclusion Link

Microinteractions show that attention to small details can deliver big and powerful results. As Charles Eames once said, “The details are not the details. They make the design.” Every element of the design matters. Details make your app stand out from the competition because they can be either practical and forgettable or impressive, useful and unforgettable.

Always design with care, and don’t forget that a great design has to happen full-stack, from the functional parts down to the microinteractions.

This article is part of the UX design series sponsored by Adobe. The newly introduced Experience Design app23 is made for a fast and fluid UX design process, as it lets you sketch out ideas, create interactive prototypes, test and share them all in one place.

You can check out more inspiring projects created with Adobe XD on Behance24, and also visit the Adobe XD blog25 to stay updated and informed. Adobe XD is being updated with new features frequently, and since it’s in public Beta, you can download and test it for free26.

(ms, vf, il, al)

Footnotes Link

  1. 1 http://adobe.ly/2aNMUAX
  2. 2 https://www.smashingmagazine.com/2016/07/how-to-create-icons-adobe-xd/
  3. 3 https://www.smashingmagazine.com/2016/07/quick-ux-prototyping-with-adobe-xd-shortcuts-pdf-cheatsheet/#comments
  4. 4 https://www.smashingmagazine.com/wp-content/uploads/2016/07/microtwo1-large.gif
  5. 5 http://www.materialup.com/posts/download-animation
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/07/microtwo2-large.gif
  7. 7 https://dribbble.com/shots/2101933-GIF-for-Pull-Down-Space-Ship
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/07/microtwo3-large.gif
  9. 9 http://www.google.com/design/spec/animation/responsive-interaction.html#responsive-interaction-user-input
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2016/07/microtwo4-large.gif
  11. 11 https://www.google.com/design/spec/material-design/introduction.html
  12. 12 https://www.smashingmagazine.com/wp-content/uploads/2016/07/microtwo5-large.gif
  13. 13 http://www.elezea.com/2013/09/ios7-parkour/
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/07/microtwo6-large.gif
  15. 15 https://dribbble.com/shots/1640866-Alarm-Material-UI
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/07/microtwo7-large.gif
  17. 17 https://dribbble.com/shots/1849030-Onboarding-for-Muzo-App
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/07/microtwo8-large.gif
  19. 19 https://dribbble.com/shots/1646262-Twitter-Bell-Animated
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/07/microtwo9-large.gif
  21. 21 https://dribbble.com/shots/1961558-Twitter-share-button
  22. 22 https://en.wikipedia.org/wiki/KISS_principle
  23. 23 http://adobe.ly/2aNMUAX
  24. 24 http://adobe.ly/1U9LS0E
  25. 25 http://adobe.ly/1sGB17z
  26. 26 https://creative.adobe.com/products/download/experience-design

↑ Back to topTweet itShare on Facebook

Developers “Own” The Code, So Shouldn’t Designers “Own” The Experience?

artificial intelligence 5291510 1920

Opinion ColumnDevelopers “Own” The Code, So Shouldn’t Designers “Own” The Experience?

We’ve all been there. You spent months gathering business requirements, working out complex user journeys, crafting precision interface elements and testing them on a representative sample of users, only to see a final product that bears little resemblance to the desired experience.

Maybe you should have been more forceful and insisted on an agile approach, despite your belief that the organization wasn’t ready? Perhaps you should have done a better job with your pattern portfolios, ensuring that the developers used your modular code library rather than creating five different variations of a carousel. Or, maybe you even should’ve sat next to the development team every day, making sure what you designed actually came to pass.

Instead you’re left with a jumble of UI elements, with all the subtlety stripped out. Couldn’t they see that you worked for days getting the transitions just right, only for them to drop in a default animation library? And where on earth did that extra check-out step come from. I bet marketing threw that in at the last minute. You knew integration was going to be hard and compromises would need to be made, but we’re supposed to be making the users lives easier here, not the tech team.

1
When many people are involved in a project, it is very important to make sure that they have a common understanding of the problem and its solution. (Image credit: The Next Web2)

Of course, there are loads of good reasons why the site is this way. Different teams with varying levels of skill working on different parts of the project, a bunch of last-minute changes shortening the development cycle, and a whole host of technical challenges. Still, why couldn’t the development team come and ask for your advice on their UI changes? You don’t mess with their code, so why do they have to change your designs around? Especially when the business impact could be huge! You’re only round the corner and would have been happy to help if they had just asked.

While the above story may be fictional, it’s a sentiment I hear from all corners of the design world, whether in-house or agency side. A carefully crafted experienced ruined by a heavy-handed development team.

This experience reminds me of a news story I saw on a US local news channel several years ago. A county fair was running an endurance competition where the last person remaining with their hand on a pickup truck won the prize. I often think that design is like a massive game of “touch the truck”, with the development team always walking away with the keys at the end of the contest. Like the last word in an argument, the final person to come in contact with the site holds all the power and can dictate how it works or what it looks like. Especially if they claim that the particular target experience isn’t “technically possible”, which is often shorthand for “really difficult”, “I can’t be bothered doing it that way” or “I think there’s a better way of doing it so am going to pull the dev card”.

Now I know I’m being unfairly harsh about developers here and I don’t mean to be. There are some amazingly talented technologists out there who really care about usability and want to do the best for the user. However, it often feels as though there’s an asymmetric level of respect between disciplines due to a belief that design is easy and therefore something everybody can have an opinion on, while development is hard and only for the specially initiated. So while designers are encouraged (sometimes expected) to involve everybody in the design process, they often aren’t afforded the same luxury.

To be honest, I don’t blame them. After all, I know just enough development to be dangerous, so you’d be an idiot if you wanted my opinion on database structure and code performance (other than I largely think performance is a good thing). Then again I do know enough to tell when the developers are fudging things and it’s always fun to come back to them with a working prototype of something they said was impossible or take months to implement — but I digress.

The problem is, I think a lot of developers are in the same position about design — they just don’t realize it. So when they make a change to an interface element based on something they had heard at a conference a few years back, they may be lacking important context. Maybe this was something you’ve already tested and discounted because it performed poorly. Perhaps you chose this element over another for a specific reason, like accessibility? Or perhaps the developers opinions were just wrong, based on how they experience the web as superusers rather than an average Jo.

Now let’s get something straight here. I’m not saying that developers shouldn’t show an interest in design or input into the design process. I’m a firm believer in cross-functional pairing and think that some of the best usability solutions emanate from the tech team. There are also a lot of talented people out there who span a multitude of disciplines. However, at some point the experience needs to be owned, and I don’t think it should be owned by the last person to open the HTML file and “touch the truck”.

So, if good designers respect the skill and experience great developers bring to the table, how about a little parity? If designers are happy for developers to “own the code”, why not show a similar amount of respect and let designers “own the experience”?

Communication is key, so be available.3
Everybody has an opinion. However, it’s not a good enough reason to just dive in and start making changes. Image credit: Open Source Way4

Doing this is fairly simple. If you ever find yourself in a situation where you’re not sure why something was designed in a particular way, and think it could be done better, don’t just dive in and start making changes. Similarly, if you hit a technical roadblock and think it would make your lives easier to design something a different way, go talk to your designer. They may be absolutely fine with your suggested changes, or they may want to go away and think about some other ways of solving the same problem.

After all, collaboration goes both ways. So if you don’t want designers to start “optimizing” your code on the live server, outside your version control processes, please stop doing the same to their design.

(vf, il)

Footnotes Link

  1. 1 https://www.flickr.com/photos/thenextweb/5664545340/
  2. 2 https://www.flickr.com/photos/thenextweb/5664545340/
  3. 3 https://www.flickr.com/photos/opensourceway/4371000846
  4. 4 https://www.flickr.com/photos/opensourceway/4371000846
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

A Glimpse Into The Future With React Native For Web

artificial intelligence 5291510 1920

A Glimpse Into The Future With React Native For Web

One of the hardest decisions to make when starting a new app is which platforms to target. A mobile app gives you more control and better performance but isn’t as universal as the web. If you’re making a mobile app, can you afford to support both iOS and Android? What about trying to build a mobile app and a responsive web app? Ultimately, the best experience for your customers is for your app to work everywhere, but the development and maintenance costs of that can be prohibitive.

We have already seen how1 React Native can help you make iOS and Android apps with a shared code base, without sacrifices in quality. But what about the web? This is exactly the problem the React Native for Web312 project is trying to solve. Instead of forcing you to maintain two separate code bases for your mobile and web apps, or making a hybrid app, with all its compromises3, React Native for Web is intended to let you write a single app that runs in a browser using standard web technologies, or on iOS and Android as a real native mobile app. While I don’t think the project is ready for production use yet, its potential success could mark a massive change in how large multi-platform applications are built. Let’s jump in!

How It Works Link

You might be thinking, “Wait! doesn’t React already work on the web?” You wouldn’t be wrong. Unfortunately, traditional React and React Native build on a different set of primitives. React uses <div>, <p> and <input>, whereas React Native uses <View>, <Text> and <TextInput>. There are good historical reasons for this, since the building blocks of a web page and of a mobile app are quite different. Nonetheless, it would be great if we could use a single set of shared components.

React Native for Web’s solution is to provide browser-compatible implementations of React Native’s components — meaning, for example, that the <View> of React Native has a DOM-based version that knows how to render to a <div>. While not every React Native component is supported, enough of them are that you could (hopefully) share the majority of your code base.

In addition to the components themselves, styles for React and React Native are written differently. With React, most people use plain CSS or a preprocessor such as Sass4. But in React Native, all styles are written in JavaScript, because there is no DOM and no selectors. With React Native for Web, styles are written just like they would be for React Native, rather than with CSS. This has the benefit of allowing you to write a single set of styles, which will work on both native mobile and the web.

We’ll take a deeper look later at how these ideas work in practice and at how much code is actually reusable. First, let’s get a sample app going.

Starting A New React Native Project Link

To get started, we will need to set up our project. At first, this will just be a regular React Native app, and then we’ll add React Native for Web. If you are following along, you’ll need to complete React Native’s “Getting Started325” guide before heading into the next section.

Once you’ve got React Native installed, you can run the following command from your terminal:

react-native init ReactNativeWeb

This will make a new React Native project named ReactNativeWeb. After it has finished installing, you can cd ReactNativeWeb, and then react-native run-ios or react-native run-android. If everything has gone correctly, you should see a friendly welcome message on your iOS or Android simulator or device.

6
React Native iOS welcome screen (View large version7)
React Native Android welcome screen8
React Native Android welcome screen (View large version9)

Notice that React Native has created two JavaScript files in our project’s directory: index.android.js and index.ios.js. You can edit any of the styles or logic in these files and see those changes update in the running app. As you can probably guess, the .android.js file is for Android, and the .ios.js file is for iOS. Fortunately, separate files are only needed when you want multiple versions of a given file per platform. Most of the time, you’ll have a single file per component.

Managing Dependencies Link

Before we can get our app running in a web browser, we’ll need to get a bit of package installation out of the way. First, run the following to install both the react-native-web package and the official React web packages.

npm i react react-dom react-native-web --save

(You might see some errors about peer dependencies from this command. You should be safe to ignore them, because they didn’t cause me any problems. If newer versions of any of these packages are out when you run the commands, though, you might need to adjust the installed versions.)

At this point, your package.json file should look something like this:

{ "name": "ReactNativeWeb", "version": "0.0.1", "private": true, "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start" }, "dependencies": { "react": "15.1.0", "react-dom": "15.1.0", "react-native": "0.28.0", "react-native-web": "0.0.25" } } 

While we have what seems to be everything required for our React Native app to run in a web browser, we must take a brief detour to consider the realities of web development. React Native’s packager compiles your ECMAScript 6 code to something that a phone’s JavaScript engine can understand, but it won’t help us in the browser. If we tried to run our app in a web browser right now, it would quickly fail due to syntax errors.

To solve this problem, we will use Babel10 and webpack11. Babel will compile our ECMAScript 6 code into browser-compatible ECMAScript 5, and webpack will bundle the compiled JavaScript, as well as just generally make development faster. (There are other options for this. If you prefer another compiler or bundler, feel free to use it instead.)

Here are the installation commands to run:

npm i webpack babel-loader babel-preset-react babel-preset-es2015 --save
npm i webpack-dev-server --save-dev

Here, babel-loader and webpack-dev-server will be used to bundle and serve our JavaScript, while babel-preset-react and babel-preset-es2015 tell Babel which plugins we need to compile our code.

Here is what your package.json file should look like now:

{ "name": "ReactNativeWeb", "version": "0.0.1", "private": true, "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start" }, "dependencies": { "babel-loader": "6.2.4", "babel-preset-es2015": "6.9.0", "babel-preset-react": "6.5.0", "react": "15.1.0", "react-dom": "15.1.0", "react-native": "0.28.0", "react-native-web": "0.0.25", "webpack": "1.13.1" }, "devDependencies": { "webpack-dev-server": "1.14.1" } } 

Configuring Link

Those are all of the packages we will need. But more setup is required before our app will work in a browser.

webpack.config.js Link

First, we’ll make a webpack config file. This file tells webpack how to build, bundle and serve our compiled code. In addition, we are going to use the alias property to automatically replace imports on react-native with react-native-web. This file should be placed in your project’s root.

const webpack = require('webpack'); module.exports = { entry: { main: './index.web.js', }, module: { loaders: [ { test: /.js?$/, exclude: /node_modules/, loader: 'babel', query: { presets: ['es2015', 'react'], }, }, ], }, resolve: { alias: { 'react-native': 'react-native-web', }, }, }; 

index.html Link

Now, we need to create an HTML file for our app to run in. This will be pretty simple because it will just be a skeleton to attach our React app to.

<!DOCTYPE html> <html> <head> <title>React Native Web</title> <meta charSet="utf-8" /> <meta content="initial-scale=1,width=device-width" name="viewport" /> </head> <body> <div></div> <script type="text/javascript" src="/bundle.js"></script> </body> </html> 

index.web.js Link

Finally, we must make an index JavaScript file for the web. The contents of this file can be the same as index.ios.js or index.android.js, but with one additional line to attach to the DOM. The div with the ID react-app from our HTML file must be selected and then used in the call to AppRegister.runApplication.

import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Text, View } from 'react-native'; class ReactNativeWeb extends Component { render() { return ( <View style={styles.container}> <Text style={styles.welcome}> Welcome to React Native! </Text> <Text style={styles.instructions}> To get started, edit index.web.js </Text> <Text style={styles.instructions}> Press Cmd+R to reload </Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, welcome: { fontSize: 20, textAlign: 'center', margin: 10, }, instructions: { textAlign: 'center', color: '#333333', marginBottom: 5, }, }); AppRegistry.registerComponent('ReactNativeWeb', () => ReactNativeWeb); AppRegistry.runApplication('ReactNativeWeb', { rootTag: document.getElementById('react-app') }); 

Now, just run ./node_modules/.bin/webpack-dev-server --inline to start webpack, and open your browser to http://localhost:8080/12. Fingers crossed, you will see a familiar welcome message but in the browser!

React Native web welcome screen13
React Native web welcome screen (View large version14)

With all of that setup complete, we are ready to start tinkering!

Experimenting With The Code Link

Create a FriendsList.js Component Link

Let’s start by making a friends list. This will be a good simple stress test of React Native for Web, because we need to use a few different components for it: <Image>, <Text>, <View> and <ListView>.

import React, { Component } from 'react'; import { Image, ListView, StyleSheet, Text, View, } from 'react-native'; const styles = StyleSheet.create({ list: { marginTop: 20, }, friend: { flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start', }, avatar: { margin: 10, width: 50, height: 50, borderRadius: 25, }, name: { fontSize: 18, color: '#000', } }); export default class FriendsList extends Component { constructor(props) { super(props); const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); this.state = { ds: ds.cloneWithRows(props.friends), }; } render() { return ( <ListView dataSource={this.state.ds} style={styles.list} renderRow={(friend) => <View style={styles.friend}> <Image style={styles.avatar} source={{ uri: friend.avatarUrl }} /> <Text style={styles.name}>{friend.firstName} {friend.lastName}</Text> </View> } /> ); } } 

We’ll need to edit our index files, too, so that a friends array gets passed in as a prop.

import FriendsList from './FriendsList'; import React, { Component } from 'react'; import { AppRegistry, Text, View } from 'react-native'; const friends = [ { id: 1, firstName: 'Jane', lastName: 'Miller', avatarUrl: 'https://placehold.it/100x100', }, { id: 2, firstName: 'Kate', lastName: 'Smith', avatarUrl: 'https://placehold.it/100x100', }, { id: 3, firstName: 'Kevin', lastName: 'Yang', avatarUrl: 'https://placehold.it/100x100', }, ]; class ReactNativeWeb extends Component { render() { return <FriendsList friends={friends} />; } } AppRegistry.registerComponent('ReactNativeWeb', () => ReactNativeWeb); 

Upon running it in iOS or Android, you should see something like this:

React Native iOS friends list15
React Native iOS friends list (View large version16)

Looks good so far. Let’s see the web version:

17
React Native web friends list. (View large version18)

Uh oh! Turns out there isn’t any web support yet for ListView’s DataSource, effectively making ListView completely unusable.

Friend.js Link

We can work around this lack of support for now. Let’s make a Friend component for the individual rows, but have a FriendsList component per platform. This will separate out the shared code that works everywhere but allow us to customize each platform where we need to.

import React, { Component } from 'react'; import { Image, StyleSheet, Text, View, } from 'react-native'; const styles = StyleSheet.create({ friend: { flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start', }, avatar: { margin: 10, width: 50, height: 50, borderRadius: 25, }, name: { fontSize: 18, color: '#000', } }); export default class Friend extends Component { render() { return ( <View style={styles.friend}> <Image style={styles.avatar} source={{ uri: this.props.avatarUrl }} /> <Text style={styles.name}>{this.props.firstName} {this.props.lastName}</Text> </View> ); } } 

FriendsList.ios.js Link

import Friend from './Friend'; import React, { Component } from 'react'; import { Image, ListView, StyleSheet, Text, View, } from 'react-native'; const styles = StyleSheet.create({ list: { marginTop: 20, }, }); export default class FriendsList extends Component { constructor(props) { super(props); const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 }); this.state = { ds: ds.cloneWithRows(props.friends), }; } render() { return ( <ListView dataSource={this.state.ds} style={styles.list} renderRow={(friend) => <Friend key={friend.id} avatarUrl={friend.avatarUrl} firstName={friend.firstName} lastName={friend.lastName} /> } /> ); } } 

On iOS, our ListView usage code is unchanged. (I’m leaving out the Android code example here and for the rest of the article, for brevity. The Android and iOS code can be the same for the rest of the code samples.)

FriendsList.web.js Link

import Friend from './Friend'; import React, { Component } from 'react'; import { Image, Text, View, } from 'react-native'; export default class FriendsList extends Component { render() { return ( <View> {this.props.friends.map(friend => <Friend key={friend.id} avatarUrl={friend.avatarUrl} firstName={friend.firstName} lastName={friend.lastName} /> )} </View> ); } } 

Now, for the web, we use the map function to render each Friend, similar to traditional React.

React Native friends list on the web, now working19
React Native friends list on the web, now working (View large version20)

Much better. At this point, hearing that ListView requires workarounds might be enough to make you think that React Native for Web isn’t ready for production use. I am inclined to agree, particularly since lists constitute a large percentage of many applications. How much it matters will vary depending on the project, though. On the bright side, all of our other React Native code so far has been completely reusable. In any case, I am still interested in exploring it further, because there is still much potential in the ideas on display here. Let’s continue with our sample app.

Instead of hardcoding a handful of list items, we can use JSON Generator21 to create a long list for us to work with. If you haven’t used it before, JSON Generator is a great tool for creating dummy and development data. Here is the structure I have defined, which adds a few fields on top of what we already have.

[ '{{repeat(200)}}', { id: '{{guid()}}', firstName: '{{firstName()}}', lastName: '{{surname()}}', avatarUrl: 'https://placehold.it/100x100', isOnline: '{{bool()}}', company: '{{company()}}', email: '{{email()}}' } ] 

And here is a snippet of some of the generated data:

[ { "id": "c5368bbe-adfb-424f-ade3-9d783befa2b6", "firstName": "Hahn", "lastName": "Rojas", "avatarUrl": "https://placehold.it/100x100", "isOnline": true, "company": "Orbixtar", "email": "hahnrojas@orbixtar.com" }, { "id": "15ef2834-3ba5-4621-abf1-d771d39c2dd6", "firstName": "Helen", "lastName": "Stout", "avatarUrl": "https://placehold.it/100x100", "isOnline": true, "company": "Ebidco", "email": "helenstout@ebidco.com" }, { "id": "1ef05de1-fd8e-41ae-85ac-620b6d716b62", "firstName": "Floyd", "lastName": "Mcpherson", "avatarUrl": "https://placehold.it/100x100", "isOnline": false, "company": "Ecraze", "email": "floydmcpherson@ecraze.com" }, … ] 

To use it, just take your generated JSON and replace our friends array declaration from before. Of course, you can move that data into its own file if you’d like, so that your code files aren’t cluttered with data. In a real application, we would get that data from an API server.

Friend.js Link

Next, we can add these new fields to the Friend component.

… render() { return ( <View style={styles.friend}> <Image style={[styles.avatar, { borderColor: this.props.isOnline ? '#9d9' : '#d99' }]} source={{ uri: this.props.avatarUrl }} /> <View> <Text style={styles.name}>{this.props.firstName} {this.props.lastName}</Text> <Text style={styles.company}>{this.props.company}</Text> <Text style={styles.email}>{this.props.email}</Text> </View> </View> ); } … 

FriendsList.js Link

Next, add them as props in each platform’s FriendsList.

… <Friend key={friend.id} avatarUrl={friend.avatarUrl} firstName={friend.firstName} lastName={friend.lastName} isOnline={friend.isOnline} company={friend.company} email={friend.email} /> … 
React Native long friends list for iOS22
React Native’s long friends list for iOS (View large version23)
React Native long friend list web24
React Native’s long friends list for the web (View large version25)

So far so good. It is encouraging to see that the core components seem to work well.

Friend.js Link

Next, we can add an animation with a transformation to see how well those work. Let’s make it so that when you tap a row, it animates left and right before returning to its initial position. We will need to add imports for Animated and TouchableOpacity, and wire up the animation and press handler.

import { Animated, TouchableOpacity, … } from 'react-native'; … export default class Friend extends Component { constructor(props) { super(props); this.state = { translateValue: new Animated.Value(0), }; } animate() { Animated.sequence([ Animated.timing(this.state.translateValue, { toValue: 50, duration: 200, }), Animated.timing(this.state.translateValue, { toValue: -50, duration: 200, }), Animated.timing(this.state.translateValue, { toValue: 0, duration: 200, }) ]).start(); } render() { return ( <TouchableOpacity onPress={() => this.animate()} style={[styles.friend, { transform: [{ translateX: this.state.translateValue }]}]}> <Image style={[styles.avatar, { borderColor: this.props.isOnline ? '#9d9' : '#d99' }]} source={{ uri: this.props.avatarUrl }} /> <View> <Text style={styles.name}>{this.props.firstName} {this.props.lastName}</Text> <Text style={styles.company}>{this.props.company}</Text> <Text style={styles.email}>{this.props.email}</Text> </View> </TouchableOpacity> ); } } 

Looks good on mobile.

React Native iOS animation26
React Native iOS animation (View large version27)

What about the web?

28
React Native web animation (View large version29)

No luck. Our TouchableOpacity throws an error when pressed. Apparently, this will be fixed30 in the next release and is only present for our particular combination of versions. Attempting to run the animation without using TouchableOpacity causes the same error, too.

I am going to stop here, but if you want to continue on your own, here is a list of topics you could research next:

  • How well do the remaining React Native components and APIs work? We’ve seen that some definitely don’t work, but we don’t yet have a comprehensive list of support.
  • You could explore more extensive styling work, including media queries.
  • React Native for Web supports server rendering. This could be particularly cool because, if it works, it would mean that you could have a single code base driving native mobile applications and a responsive web app that is SEO-optimized.

Conclusion Link

As you can tell, React Native for Web is definitely not ready for production. There are too many unsupported components, even in our small demo app, for me to feel confident about using it in a real project. The most encouraging thing to me, though, is that the pieces that do work seem to completely work, and the parts that don’t, fail entirely. I find that much preferable to the entire thing just kind of working. At the moment, it seems like the project just needs more time to build support. If everything was only 50% functional, I would view that as a sign that the approach is fundamentally broken.

Despite the problems, I still think this is a very exciting project and worth keeping an eye on.

Resources Link

(da, ml, al)

Footnotes Link

  1. 1 https://www.smashingmagazine.com/2016/04/consider-react-native-mobile-app/
  2. 2 https://github.com/necolas/react-native-web
  3. 3 http://www.apptentive.com/blog/5-points-to-consider-before-making-a-hybrid-mobile-app/
  4. 4 http://sass-lang.com/
  5. 5 https://facebook.github.io/react-native/docs/getting-started.html
  6. 6 https://www.smashingmagazine.com/wp-content/uploads/2016/07/01-react-native-welcome-ios-opt.png
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/07/01-react-native-welcome-ios-opt.png
  8. 8 https://www.smashingmagazine.com/wp-content/uploads/2016/07/02-react-native-welcome-android-opt.png
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/07/02-react-native-welcome-android-opt.png
  10. 10 https://babeljs.io/
  11. 11 https://webpack.github.io/
  12. 12 http://localhost:8080/
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2016/07/03-react-native-welcome-web-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2016/07/03-react-native-welcome-web-opt.png
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/07/04-react-native-friends-ios-opt.png
  16. 16 https://www.smashingmagazine.com/wp-content/uploads/2016/07/04-react-native-friends-ios-opt.png
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/07/05-react-native-friends-web-opt.png
  18. 18 https://www.smashingmagazine.com/wp-content/uploads/2016/07/05-react-native-friends-web-opt.png
  19. 19 https://www.smashingmagazine.com/wp-content/uploads/2016/07/06-react-native-friends-web-2-opt.png
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/07/06-react-native-friends-web-2-opt.png
  21. 21 http://www.json-generator.com/
  22. 22 https://www.smashingmagazine.com/wp-content/uploads/2016/07/07-react-native-friends-2-ios-opt.png
  23. 23 https://www.smashingmagazine.com/wp-content/uploads/2016/07/07-react-native-friends-2-ios-opt.png
  24. 24 https://www.smashingmagazine.com/wp-content/uploads/2016/07/08-react-native-friends-2-web-opt.png
  25. 25 https://www.smashingmagazine.com/wp-content/uploads/2016/07/08-react-native-friends-2-web-opt.png
  26. 26 https://www.smashingmagazine.com/wp-content/uploads/2016/07/09-react-native-ios-animation-opt.gif
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2016/07/09-react-native-ios-animation-opt.gif
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2016/07/10-react-native-web-animation-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2016/07/10-react-native-web-animation-opt.png
  30. 30 https://github.com/necolas/react-native-web/issues/150
  31. 31 https://github.com/necolas/react-native-web
  32. 32 https://facebook.github.io/react-native/docs/getting-started.html
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

Web Development Reading List #148: CSS Color Syntax Change, Browser News, And Hidden Expectations

artificial intelligence 5291510 1920

Web Development Reading List #148: CSS Color Syntax Change, Browser News, And Hidden Expectations

I shut down my browser on Wednesday, accidentally having a setting switched on that clears history and all sessions. First, I was sad to have lost many tabs with articles I stored “for later”. At the same time, it felt refreshing, liberating to have a clean browser window with zero tabs open. So my new goal is to start work in the morning with a completely clean browser window at least once a week.

In other news: I spent several hours fixing broken links this week, and as a result I can’t say how happy I am that archive.is1 and archive.org2 exist to prevent content from disappearing forever. Still, some of the resources I found broken have left forever. So remind yourself about redirecting content.

News Link

  • There’s a big change coming up for how we write colors in CSS. Tab Atkins recently changed the color functions syntax3 in the CSS specification. So in future, we will write rgb(0 255 0 / 50%) instead of rgba(0, 255, 0, 50%). This might sound awkward after years of doing it differently, but the reason for it are the new color functions available in CSS Colors Level 4, including color(). You can read more about this in Tab’s blog post, but for now be assured that the old syntax is likely to be supported forever in our browsers thanks to legacy support.
  • Opera 39 and Chromium 52 hit the streets this week and with them a couple of new features4: The Fetch API now supports a custom referrer policy, Performance Observer5 is supported, just like alpha channel for RGB colors in hex notation (#ffffff50), and CSP 3’s strict-dynamic directive is now available as well.
  • The new Docker for Mac and Windows is finally production-ready6 after several months in beta. Great news for all users who eagerly awaited it but always had issues with the previous version (i.e. disk and permission management problems).
  • Big news from Mozilla this week: With Firefox 487, the multi-process engine e10s is now enabled for many users, making Firefox much more robust, faster and more reliable. Also, protection against harmful downloads has been improved8 and unsigned/unverified add-ons won’t load anymore. Web Extensions support9 including CSP enforcements for web extensions is also new, just like the about:debugging developer page. For developers, the DevTools come with an improved font inspector, calc() is now supported for line-height and can be nested, and, last but not least, support for the CSP directive upgrade-insecure-requests has been added, too.
  • Microsoft pushed Edge 14 this week10 and with it a lot of great new things11. Notably, the new version got a lot of accessibility improvements and now competes as one of the best browsers in the HTML5 Accessibility test1412. New features also include extensions and pinned tabs and performance got better to improve battery life, too. Fellow developers will be happy to hear about web notifications, the Fetch API, Beacon Interface, JavaScript’s asyncawait, and support for <time> and WOFF2.
13
The new version of Edge, Edge 14, got a lot of improvements and now scores 100% in the HTML5 Accessibility test1412.

General Link

  • Dave Rupert reflected on hidden expectations15 and why the hardest parts of the web are the ones the client doesn’t see. Accessibility, security, and performance serve very well as main examples for such hidden expectations.

Concept & Design Link

  • In our industry, it’s important to have a connected workflow between design and development16 to make sure we’re aligned and to make real collaboration possible. Subjects like “avoiding assumptions, team up with our peers or sharing knowledge” will help us work together in a better way, says Simon Colijn.

Tools & Workflows Link

  • Users don’t care what tools we use; they care when we ship something useful. A great presentation by Liz Abinante on the simplicity of tooling17 and reasonable choices18.
  • We take GitHub for granted. We pay for it and we use it as the primary end point for our git-repositories. Now Fabio Akita shares why it’s the more expensive option and how you can use the open-source alternative gitlab19 on a pre-configured VPS that is cheaper and more flexible. At least worth reading.

Security Link

  • Proofpoint published a very interesting in-depth analysis of a big malvertising network20 that they found in the wild and that hid itself from plain sight by using steganography and file whitelisting. There’s evidence that they targeted a daily traffic of 1-5 million high-quality client hits.
  • Mathy Vanhoef and Tom Van Goethem presented a new HEIST-attack on HTTPS pages to steal SSNs, email addresses, and more. You can view the slides21 (PDF) or read the write-up22 (PDF) to understand the attack and what you can do to prevent it.
  • Mike West, one of the main persons pushing security web standards at the moment, proposes to introduce an origin-wide policy manifest23 to reduce the risk that security policies aren’t applied to specific resources. The proposal suggests to use a file in the /.well-known/origin-policy/[name-goes-here] directory on the origin server, adapting an already used folder name and path.
  • The well-known security researcher Jonathan Zdziarski found an issue in Whatsapp’s iOS app that seems wide-spread in iOS apps in general: Deleted chats aren’t deleted24, which means that forensic experts could reconstruct them. Any app that uses SQLite on iOS has the same issue since deleted entries are only set “free” to be overwritten instead of actually deleted. In fact, Apple’s Messages app faces the same issues, and cloud sync makes this even worse as it spreads the deleted information to other devices. Jonathan finally shows how to implement an SQLite database in an iOS app to prevent this issue.
25
A wide-spread issue in iOS apps that use SQLite: Deleted entries aren’t deleted26 but only set free to be overwritten. (Image credit: Jonathan Zdziarski27)

Privacy Link

  • The Battery Status API in general sounds like a great addition to our web platform. Initially built by Mozilla to complete the API-set on the web, we can use it on websites to reduce the amount of interactivity and animation or serve videos in low resolutions when the battery is nearly empty, for example. Lukasz Olejnik, however, found out that this API is actually already used28 as a user tracking identifier by ad networks and others. And last but not least, it can also be used to charge more for a service when a user’s battery is low — as reportedly done by Uber29.

Web Performance Link

  • Mattias Geniar had a look at Google’s new QUIC protocol30 that uses UDP instead of TCP and manages to be more reliable and faster — an ideal candidate as a successor to the TCP protocol. While it’s still at an early stage, the IETF is considering to make it a standard, Google uses it for some of their services already, and several server and browser vendors have plans to implement it, too.
  • For very big websites, we often tend to use a CMS, as this seems to be the best option at first glance. But what about choosing a static site generator for better performance and less security risks? Stefan Baumgartner shares his experience with using static site generators at scale31 and how they even built something like a content management system around it.

JavaScript Link

CSS/Sass Link

  • For long articles, a scroll indicator can be very useful to indicate the reading progress. Most people use some sort of JavaScript code to do this (which is calculation-expensive); some people, however, find clever tricks to do it with CSS. The CSS-only scroll indicator35 by Mike Riethmuller is an awesome show-off of using gradients, viewport units and a pseudo-element.

CSS only scroll indicator36 by Mike Riethmuller (MadeByMike37) on CodePen38.

CSS-only scroll indicator by Mike Riethmuller.

Work & Life Link

Going Beyond… Link

  • Simon St. Laurent on decentralizing the web41. Some useful thoughts about our current lock-in on technology, service providers, and centralized solutions, and how we might be able to break that up again to unlock the real power of the web.
  • Katharine Viner writes about how social media swallowed the news42 and how the consequences of this go far beyond journalism. Does the truth even matter any more? An interesting essay on how well-done social marketing has an enormous influence on the decisions people make — no matter if it’s about buying a product or making a political decision.
  • Since the financial crisis, the private equity industry has become hugely influential. The New York Times curated a lovely, interactive story about how private equity plays out in your daily life43.

And with that, I’ll close for this week. If you like what I write each week, please support me with a donation44 or share this resource with other people. You can learn more about the costs of the project here45. It’s available via email, RSS and online.

— Anselm

Footnotes Link

  1. 1 https://archive.is/
  2. 2 https://archive.org/
  3. 3 http://www.xanthir.com/b4iW0
  4. 4 https://dev.opera.com/blog/opera-39/
  5. 5 https://developers.google.com/web/updates/2016/06/performance-observer
  6. 6 https://blog.docker.com/2016/07/docker-for-mac-and-windows-production-ready/
  7. 7 https://blog.mozilla.org/blog/2016/08/02/exciting-improvements-in-firefox-for-desktop-and-android/
  8. 8 https://blog.mozilla.org/security/2016/08/01/enhancing-download-protection-in-firefox/
  9. 9 https://blog.mozilla.org/addons/2016/04/29/webextensions-in-firefox-48/
  10. 10 https://developer.microsoft.com/en-us/microsoft-edge/platform/changelog/desktop/14393/?compareWith=10586
  11. 11 https://blogs.windows.com/msedgedev/2016/08/04/introducing-edgehtml-14/
  12. 12 http://www.html5accessibility.com/
  13. 13 http://www.html5accessibility.com/
  14. 14 http://www.html5accessibility.com/
  15. 15 http://daverupert.com/2016/08/hidden-expectations/
  16. 16 http://simon.fyi/articles/aligning-design-and-development
  17. 17 https://twitter.com/AndyHieb/status/761272450554269696
  18. 18 https://speakerdeck.com/feministy/in-defense-of-static-sites
  19. 19 http://www.akitaonrails.com/2016/08/03/moving-to-gitlab-yes-it-s-worth-it
  20. 20 https://www.proofpoint.com/us/threat-insight/post/massive-adgholas-malvertising-campaigns-use-steganography-and-file-whitelisting-to-hide-in-plain-sight
  21. 21 https://tom.vg/talks/BlackHatUSA2016_HEIST-presentation.pdf
  22. 22 https://tom.vg/papers/heist_blackhat2016.pdf
  23. 23 https://discourse.wicg.io/t/proposal-set-origin-wide-policies-via-a-manifest/1617/4
  24. 24 http://www.zdziarski.com/blog/?p=6143
  25. 25 http://www.zdziarski.com/blog/?p=6143
  26. 26 http://www.zdziarski.com/blog/?p=6143
  27. 27 http://www.zdziarski.com/blog/?p=6143
  28. 28 https://go.lynxbroker.de/eat_heartbeat.js
  29. 29 http://www.telegraph.co.uk/business/2016/05/22/uber-app-can-detect-when-a-users-phone-is-about-to-die/
  30. 30 https://ma.ttias.be/googles-quic-protocol-moving-web-tcp-udp/
  31. 31 https://www.smashingmagazine.com/2016/08/using-a-static-site-generator-at-scale-lessons-learned/
  32. 32 http://blog.goguardian.com/nerds/an-odyssey-to-find-a-sustainable-icon-system-with-svgs-in-react
  33. 33 https://tech.metriccollective.com/of-course-ill-let-you-execute-arbitrary-javascript-code-in-my-users-browsers-3032eca3480e
  34. 34 https://benfrain.com/understanding-native-javascript-array-methods/
  35. 35 https://codepen.io/MadeByMike/pen/ZOrEmr?editors=0100
  36. 36 ‘https://codepen.io/MadeByMike/pen/ZOrEmr/’
  37. 37 ‘http://codepen.io/MadeByMike’
  38. 38 ‘http://codepen.io’
  39. 39 https://newrepublic.com/article/135468/exhaustion-became-status-symbol
  40. 40 http://www.tombartel.de//2016/07/05/recalibrate-your-productivity-sensors/
  41. 41 https://www.oreilly.com/ideas/decentralize-now
  42. 42 https://www.theguardian.com/media/2016/jul/12/how-technology-disrupted-the-truth
  43. 43 http://www.nytimes.com/interactive/2016/08/02/business/dealbook/this-is-your-life-private-equity.html?_r=0
  44. 44 https://wdrl.info/donate
  45. 45 https://wdrl.info/costs/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook

7 Reasons to Develop Your Next Web App with Meteor

artificial intelligence 5291510 1920

When I first learned about the Meteor JavaScript framework, I saw someone write, “Meteor is to Node.js as Rails is to Ruby,” and I think that’s a good comparison. A few years ago, Rails was the hot new thingon the web, sprinkling some useful “magic” through the development process to make programming on the web more approachable and pleasant. Out of the countless new frameworks that have spawned as of late though, none have made me feel the way Rails did as much as Meteor — a framework that you should seriously consider using for your coming projects. Here’s a few reasons why.

1. Your applications are real-time by default.

Lately, companies like Twitter and Facebook have been moving toward a real-time web. It’s inevitable that, sooner than you probably expect, users will expect web applications to work near-instantaneously. I imagine there’s already users who wince whenever a separate page load is required for simple tasks like changing settings and logging out.

The problem is, creating real-time web applications is tricky. Or at least, it was. Meteor has real-time built into its core though. When the database is updated, the data in your templates is updated. When a user clicks a button or submits a form, the action occurs immediately. In the vast majority of cases, this doesn’t even require any extra effort. You build a web application as you normally would and, out of the box, it just happens to be real-time.

A while back, the folks at Meteor released a screencast to demonstrate these real-time features, and it’s very much worth a watch, but there’s a range of production applications that do an even better job of showing off the Meteor difference:

These are just a small sample, too.

2. You can develop with just one language.

One of the frustrating parts of being a web developer is the need to wear a variety of hats. You need to think about the front-end, the back-end, and the database, and then there’s another million details that squeeze out the last inch of your mental capacity. Meteor simplifies this process by shrinking the scope of what you need to consider, allowing you to build and manage the front-end, the back-end, and the database with nothing but JavaScript.

This, for instance, is how we create a “collection” — the equivalent of an SQL table – in Meteor:

BlogPosts = new Meteor.collection('posts');

So, we can create a collection with a familiar syntax, but also manipulate a collection with a familiar syntax. Here’s how we insert data:

BlogPosts.insert({
  title: 'Hello World',
  content: 'This is the content.',
  published: true
});

There’s another benefit to writing an entire application with one language. One line of code can run on both the client and the sever and do different things in either environment. Here’s why this matters:

When the statement to create a collection runs on the server it, predictably enough, creates a collection. But when that same statement runs on the client (which it will do by default), it creates a purely local collection within the user’s browser. The user then interfacts with the local collection directly, which is why the data on their screen can change instantaneously, while the local and server-side collections are seamlessly synced in the background.

This doesn’t require any special treatment. You write one line of code and are provided with a boat-load of functionality in addition to being able to use a familiar syntax throughout the development cycle.

3. You can save a lot of time with smart packages.

Let’s say you want to create a user accounts system within a Meteor project. How might you approach it? If your first thought was, “Well, I’d create a collection for the user’s data,” then you’re already thinking too hard.

In Meteor, this is how we create an accounts system:

meteor add accounts-password

We run this command in a terminal, and Meteor adds one of its built-in “smart packages” to the project. This particular package creates an accounts system that expects an email (or username) and password. But what if we wanted to let users sign up with their Twitter account? Then we could write:

meteor add accounts-twitter

Or, with their Google account:

meteor add accounts-google

Or, Facebook:

meteor add accounts-facebook

We could even run all of these commands so our users could choose how they want to sign up.

Meteor also provides an accounts-ui package that creates the front-end of this accounts system, and that only requires one other command:

meteor add accounts-ui

With our account system in place, we can do everything we would reasonably need to do when working on a web application, like checking if the current user is logged in via one of our templates:

{{#if currentUser}}
  <p>You're logged in.</p>
{{else}}
  <p>You're not logged in.</p>
{{/if}}

Or navigating through and manipulating the Meteor.users collection, which is the collection that Meteor creates to store the data of our users.

Smart packages are not just for accounts though. There’s a range of them already available, with more presumably on the way, and they all allow you to do something cool, including:

  • Writing your applications in CoffeeScript.
  • Automatically compiling LESS files into CSS.
  • Integrating extras like D3.js and Bootstrap.

But if smart packages don’t have what you need, then the increasingly large library of third-party packages will probably have you covered.

4. The community is extremely supportive.

Nothing attracts me more to a new framework or technology than an active and vibrant community. I figure that, if the community’s active, then:

  • There’ll be a lot of detailed documentation.
  • I’ll waste less time getting up to speed with the basics.
  • The technology won’t hit the deadpool in the near future.

Luckily, Meteor’s community is already one of its greatest assets. There’s a ton of helpful resources that have spawned from people’s love of the framework, including:

  • Crater, a Reddit-like site for keeping track of what’s happening in the world of Meteor.
  • Evented Mind, a video training site for intermediate developers wanting deeper insight into how Meteor works.
  • Kadira, a performance tracking application that is both easy to use and has a reasonable free plan for getting started.

The official YouTube channel for Meteor has a range of talks from Meteor meetups and there’s plenty of blogs to follow for tips and tutorials:

But if you’re still not satisfied with what’s available, Stephan Hochhaus maintains a huge list of Meteor resources that has a little something for everyone.

5. It’s optimized for developer happiness.

Just about every framework markets itself as a better and more enjoyable way to work. What I appreciate though is Meteor’s attention to detail in holding true to its promise of optimizing for developer happiness.

Take this code, for instance:

<head>
  <title>Your Cool Meteor App</title>
</head>
<body>
  {{> myCoolTemplate}}
</body>

<template name="myCoolTemplate">
  <p>Hello world.</p>
</template>

This is a basic interface for a Meteor application with a template included between the body tags. (For templating, Meteor uses Spacebars — a Handlebars-inspired syntax.)

But notice that:

  • We haven’t included the html tags.
  • We haven’t included any CSS files.
  • We haven’t included any JavaScript files.

…and that’s because we don’t need to do these things since Meteor takes care of them for us. Is this the most significant feature in the world? Nope. But it’s indicative of Meteor’s interest in making every developer’s life that little bit easier at every turn.

Other pleasant details include:

  • A built-in LiveReload feature so you won’t have to manually refresh your browser.
  • The freedom to structure your projects however you want. There are standards you can follow but no strict rules or conventions.
  • The sheer modularity of Meteor that allows you to mix-and-match different components in case one part of Meteor isn’t to your liking.

So while Meteor has its fair share of “magic” and conventions designed to make your life easier, you can still make choices based on your personal preferences. It’s the best of both worlds.

6. It’s friendly to beginner developers.

What surprised me about Meteor was how quickly I was able to start building things that were actually kind of cool. I’d heard people refer to the framework as “easy” but, usually, other people’s definition of that word differs from my own. In this case though, they were right:

Meteor is one of the easiest frameworks for beginners to learn.

It’s still programming, and you’ll want to be familiar with the syntax of JavaScript — variables, loops, conditionals, JSON, etc. — but you don’t need to be a JavaScript ninja to make a start. You don’t even need prior experience with making web applications (it’s a great choice for front-end developers looking to bolster their skillset). You might not grasp all of the concepts right away but that won’t stop you from enjoying the practical side of things.

As for why Meteor is such a great fit for beginning developers, it’s mostly for the same reasons that I recommend Meteor in general:

  1. You only need to know a single language.
  2. There’s a ton of community-made resources.
  3. It’s optimised for developer happiness.

So even if you stumble across a slight hump when learning Meteor, just push a little further and I think you’ll find that those humps are few and far between.

7. It’s ahead of the tech curve.

Like I said earlier, the web is becoming a real-time environment, but the shift won’t happen purely based on the actions of the big companies with the big budgets. The shift will happen as tools become available that allow small teams and individual developers to make real-time applications quickly and easily. Meteor is amongst the first wave of this tools and its “all in one” approach is surely going to make it a big player in the coming years.

The folks at Meteor have stated their long-term mission, and to put it plainly, their mission is huge:

…to build a new platform for cloud applications that will become as ubiquitous as previous platforms such as Unix, HTTP, and the relational database.

Can they pull this off? No one can say with absolute certainty, of course, but they have the funding, the community, and the ever-important balance of being great for developers and great for end-users. So at the very least, they’re on the right track (and it’s a track where I’m glad to be tagging along for the ride).

Conclusion

As of writing these words, Meteor is still young at version 0.8.2, but the releases are coming big and quick, and a range of impressive Meteor-built apps are live and being used on the web. Your particular situation will determine whether or not a particular framework is the right fit for you and your creations, but every developer owes it to themselves to at least play with Meteor for a day or two. I haven’t had this much fun with programming on the web in a long while and there’s a good chance you’ll feel the same way.

Was this helpful? – 

Meet the author
David Turnbull is the author of the Meteor Tips blog, a regular source of tips, tricks, and tutorials for the Meteor JavaScript framework. He’s currently hard at work on a screencast series for beginning developers to get started with Meteor.
 

https://www.meteor.com/install
https://docs.meteor.com

Web Development Reading List #147: Security Guidelines, Accessible UI Components, And Content-First Design

artificial intelligence 5291510 1920

Web Development Reading List #147: Security Guidelines, Accessible UI Components, And Content-First Design

When working in a team, it’s important to stick to rules. A common challenge is to build all your projects with a similar or the same toolset and coding guidelines. Only yesterday I discussed how we could port over a project that outgrew its initial codebase over the years to a fresh, React.js-based source code.

The decision for this wasn’t easy, since we had invested quite a lot of work and money into this project already, and a move to React would require quite some time, too. But since the switch makes sense from a technical perspective and the team is already using React for three other projects, we concluded that this would be a good step to do. It will enable more developers of the team to contribute to the project, to review code and to reduce the shift of technologies in the company. Occasionally, it’s time to re-evaluate your projects and move on.

News Link

  • Bootstrap 4 Alpha 31 has been released this week. It comes with an overhauled grid, updated form controls, a system font stack, and more.
  • Microsoft announced that their JavaScript engine ChakraCore2 now supports Mac OS and Linux. This means, you can now test and run your Node.js applications not only in Google’s V8 engine. Christian Heilmann wrote up why this is an important step3.
4
Good news for Mac and Linux users: ChakraCore is finally supported5. (Image credit: Christian Heilmann6)

Concept & Design Link

Tools & Workflows Link

  • If you work on small projects, an (S)FTP-client can still be very useful. But on the other hand, it means you need to manually copy files from your git workflow to the server. To solve this issue, the indie developer Jan Östlund built GitFTP-Deploy8, a handy (S)FTP tool for a small fee that does automatic deployments based on your git workflow.
  • The privacy/tracking issue is bigger than we think. Have you ever monitored which apps connect to which service? You suddenly realize that an ad blocker/privacy add-on in your browser is only a drop in the bucket. Apps often connect to Google services, Google Analytics, sometimes to various ad networks, and very often to New Relic’s user tracking service. Fortunately, there’s a solution to nearly every problem: Add tracker hostnames to your /etc/hosts file. There’s even a public sample hosts file that you can use9 that includes most ad networks and trackers. Use it at your own risk though and be aware that some apps might not work anymore. But maybe your privacy is worth it?

Security Link

  • FallibleInc’s “A practical security guide for web developers10” tries to help developers build more secure, less vulnerable solutions. While they claim that it’s by no means a comprehensive guide, it covers stuff based on the most common issues they’ve discovered in the past.
  • We know that HTTPS is not super-secure. That’s why lately a lot of bugs were fixed in the software implementations and a lot of techniques like HSTS and HPKP were added. But sometimes all of this won’t help. Recently, an attack was discovered that can be carried out by operators11 of just about any type of network, including public Wi-Fi networks, which arguably are the places where people need HTTPS the most. There are also hints that this type of attack is already in use by at least the NSA and therefore likely by a lot of other people, too. Please never trust TLS only for your own security but use a VPN for public networks.
HTTPS protection12
Even when the Wi-Fi can’t be trusted, people rely on HTTPS to secure their connection. A fallacy, as a recently-discovered attack13 shows. (Image credit: Ars Technica14)

Privacy Link

  • I don’t want to be the scapegoat here, but Pokémon Go is very popular, and I read some interesting things about the privacy of the game. For example, not only Alphabet (aka Google) is one of the main investors, but there’s also a financial relationship between the game-maker Niantic and the CIA angel investment company In-Q-Tel15. While there’s no evidence on what this could mean for the privacy of users, it definitely means that those companies are highly interested in the data that is provided by the gamers — understandable, as it’d be very hard to get geo information and pictures of private ground in a normal way. I’ve heard that several companies such as BMW already advised their employees that it’s forbidden to play the game at their factory sites and the German army published a similar order to their soldiers. ExpressVPN also published a short summary list with nine privacy issues to consider when playing Pokémon Go16.

Web Performance Link

  • Erik Duindam writes about how a good architecture can save you a lot of money when building a product. He shares how he built a Pokémon Go app with 500k users in just five days17 and reduced the costs of it to a $100/month server infrastructure, compared to many MVP products that burn money by choosing bad technical designs.
  • Jake Archibald shares an interesting little fact about the benefits of using rel=noopener: it’s faster18.

Accessibility Link

JavaScript Link

CSS/Sass Link

Work & Life Link

Multitasking27
What happens when you give up multitasking for a week? Lydia Dishman found out28.

Going Beyond… Link

And with that, I’ll close for this week. If you like what I write each week, please support me with a donation32 or share this resource with other people. You can learn more about the costs of the project here33. It’s available via email, RSS and online.

— Anselm

Footnotes Link

  1. 1 https://blog.getbootstrap.com/2016/07/27/bootstrap-4-alpha-3/
  2. 2 https://github.com/Microsoft/ChakraCore
  3. 3 https://www.christianheilmann.com/2016/07/27/why-chakracore-matters/
  4. 4 https://github.com/Microsoft/ChakraCore
  5. 5 https://github.com/Microsoft/ChakraCore
  6. 6 https://www.christianheilmann.com/2016/07/27/why-chakracore-matters/
  7. 7 http://jgthms.com/web-design-in-4-minutes/
  8. 8 https://eastwest.se/apps/gitftpdeploy
  9. 9 http://winhelp2002.mvps.org/hosts.txt
  10. 10 https://github.com/FallibleInc/security-guide-for-developers
  11. 11 http://arstechnica.com/security/2016/07/new-attack-that-cripples-https-crypto-works-on-macs-windows-and-linux/
  12. 12 http://arstechnica.com/security/2016/07/new-attack-that-cripples-https-crypto-works-on-macs-windows-and-linux/
  13. 13 http://arstechnica.com/security/2016/07/new-attack-that-cripples-https-crypto-works-on-macs-windows-and-linux/
  14. 14 http://arstechnica.com/security/2016/07/new-attack-that-cripples-https-crypto-works-on-macs-windows-and-linux/
  15. 15 https://medium.com/friction-burns/pokémon-spy-17087ae3653d
  16. 16 https://www.expressvpn.com/blog/pokemon-go-privacy-concerns/
  17. 17 https://medium.com/unboxd/how-i-built-an-app-with-500-000-users-in-5-days-on-a-100-server-77deeb238e83#.91iwcl397
  18. 18 https://jakearchibald.com/2016/performance-benefits-of-rel-noopener/
  19. 19 https://medium.com/@addyosmani/accessible-ui-components-for-the-web-39e727101a67
  20. 20 http://accessibility.voxmedia.com/
  21. 21 http://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html
  22. 22 http://krasimirtsonev.com/blog/article/react-js-in-design-patterns
  23. 23 https://css-tricks.com/full-width-containers-limited-width-parents
  24. 24 https://css-tricks.com/full-width-containers-limited-width-parents/#article-header-id-6
  25. 25 http://www.paperplanes.de/2015/9/28/always-improve-never-appreciate.html
  26. 26 https://www.fastcompany.com/3062183/your-most-productive-self/what-happened-when-i-gave-up-multitasking-for-a-week
  27. 27 https://www.fastcompany.com/3062183/your-most-productive-self/what-happened-when-i-gave-up-multitasking-for-a-week
  28. 28 https://www.fastcompany.com/3062183/your-most-productive-self/what-happened-when-i-gave-up-multitasking-for-a-week
  29. 29 http://www.flassbeck-economics.com/how-climate-change-is-rapidly-taking-the-planet-apart/
  30. 30 https://www.washingtonpost.com/news/energy-environment/wp/2016/07/19/greenland-lost-a-trillion-tons-of-ice-in-just-four-years/
  31. 31 https://eager.io/blog/the-languages-which-almost-were-css/
  32. 32 https://wdrl.info/donate
  33. 33 https://wdrl.info/costs/
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to topTweet itShare on Facebook