My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Tuesday, April 15, 2014

The Dark Side Of Transpilers

It's cool when everyone tells us that we can use modern and future ECMAScript features today, right? Well, here the other half of the untold story, the one web developers might not be aware or just wrongly ignore.

What Is A Transpiler

A pre-processor software that converts a non supported syntax into a presumably supported one, polyfilling as example a slightly different programming language, as it is for CoffeeScript, or bringing new features not deployed and not standard and/or fully approved yet to older browsers, as it is for Traceur " oriented" case.
It's important to understand I am not blaming any specific transpiler in here and these two mentioned one are just famous examples.

Native Source Map Support Or GTFO

As simple as that, if our target browser, and once again I don't mean the one emulated via Chrome dev tools, based on V8, but the real browser with all its quirks based on that exact version of the JS engine that has nothing to do with what's inside our Chrome or Canary, does not support natively source map, we'll never be able to debug anything in a reasonable way. It will be a tedious and blind guessing process about what's going on in there.
This includes any external library that might pollute the original environment with undesired globals, and/or trying to provide meaningful info, without having a real adb live debug, an iOS live debug or a BlackBerry live debug console possibility.
All these non native, platform and browser dependent version, source map bridges aren't that good ... we can feel free to invest time using these though ... however ...

Remember Old IE Simulators? They Are Back!

As silly as it sound, using a single vendor emulator to pretend we are testing all versions of Webkit, Blackberry, Firefox, Windows Phone or webOS out there is the equivalent of pretending that IESimulator ever worked ... while we all know that to test proper IE we need either the real OS with the real IE installed, being strictly related to OS DLLs too, or at least a Virtual Machine snapshot of that OS with that version. Everything else is a lie, period.
Sadly, when we see all those browsers including iOS and iPhone in our devtool emulator, we must be fool to believe that will be the behavior the same browser will have for real.
Just try to imagine that iOS 7 freezes when you scroll while V8 and Chrome keeps firing events like a charm ... while building our next business model on top of this scrolling behavior ...

Possibly Unaware Transpilers

What if the new syntax is transpiled to a not fully compatible JavaScript? Are we going to fix the transpiler then the logic behind then the browser behavior or ... what? How double difficult is to fix a non considered target browser through a transpiler instead of directly feature detect via JS because we know where and what is the problem?
It's like thinking that an assembly issue came out of gcc compiler and we have to fix either the C syntax or the compiler itself ... can we even think about this scenario when we chose a transpiler?

Performance Upside Down

I know this hurts but it's the sad state of reality. New hardware and new software on top with great new features will perform natively as fast as possible these features ... old crappy hardware with already problematic performance issues, as it is for all Android 2 still out there, all IE < 9 browsers out there, all PC still on WinXP and ... you name it ... the moment we have to wrap everything in order to simulate some native Promise, Generator, spread operator, or arrow function to bind them all, when we all know that bound functions are very slow compared to normal one but arrow as a function shortcut it's going to bind everything no matter what, whatever it is it's going to be slower in already slower hardware and not so optimized software.

CSP Pointless Reports

Last but not least, Content Security Policy report will provide completely pointless reports because of some JavaScript generated by some non JavaScript syntax ... if security matters, this is yet another no-go, if not the main one!

About Optimizations

It came out instantly on twitter but this is another myth ... it does not matter if Emscripten compiles 10X faster thanks to asm.js, if our target browser does not support those optimizations and it actually fails with some modern Math method we are doomed. Transpilers need to know the hosting JS env and cannot optimize upfront, that's the reality once again.
This means that even using C as not supported syntax that will be optimized that much, not necessarily we need to write C to go faster .. actually, if the transpiler optimizes for some engine only, others might have worst performance ... but ...

Yeah, Some Browser Will Benefits

As mentioned initially, it's about target browsers. If we are targeting a browser that should support WebGL and asm.js and perform decently showing Unreal Tournament on the screen, there's no need to care about older browsers ... got it?

I Am Not Pushing Back Progress ... But ...

If new developers in 2014 still need to know these obvious things for most of us on the web, maybe they need to chill out with all this use the future now hype because while everything is awesome and interesting and powerful, somebody still have to support people that don't upgrade phones and PCs every year (or 6 months), and a web that would still like to be available by as many people as possible.

Graceful Enhancement

Or polyfills and meaningful libraries that work everywhere, this is my daily mantra when it comes to develop anything that might be useful ... I have no idea how we are supposed to serve different versions of the same modern standard out there. All I know is that slowly, web development is getting better but we cannot abandon web users because we don't care about slow, inefficient, problematic, and not compatible hardware ... we managed to keep alive IE6 for more than 10 years, now between this, which is wrong, and using a prematurely implemented version of ES7 there is an abyss, which represents the road that web development, IMO, should never take.

I believe the web should be similar to a book, no matter how fancy is the cover and images inside, everyone could read it.
That's how I'd like to keep it whenever is possible and reasonable (effort and target browsers speaking, of course).

Friday, April 11, 2014

All IE Objects Are Kinda Broken

Update III
Microsoft landed a patch to supported browsers, including IE9 up to IE11 Desktop.
It's not clear what's going on with Windows Phone IE, but I'd expect at least version 11 to be patched since AFAIK Surface devices have been already fixed as promised before.
I personally strongly doubt IE9 Mobile in WP7 will be patched too but finger crossed for at least WP8 hoping with the 8.1 update this problem will dissolve as well as on Desktop!
Update II there is a better solution
I had a chance to talk with @jdalton and even before that, @bterlson confirmed me they are already working on a fix for the next version of IE and considering patching previous versions: I've also added a third alternative solution to the problem itself, suggested by the same John David Dalton ... I've talked about this option later on so you can check what is this about.
I've posted out of surprise and gut because I really appreciate all progress IE is doing since version 9 so let's hope this is some sort of balsamic vinegar stain that it'll be washed away soon in as many IE versions as possible.
Now, down to the bug ...
Thanks to @bga_ that forwarded to me the following tweet, things are even worst than expected (but keep reading for possible solutions):

Bug Deatils

All IEs that support Object.create seem to be affected. If there are only numeric properties in the created object and no new keyword has been used to inizialize the same, hasOwnProperty check as well as isPropertyEnumerable will miserably fail.
// a generic "class"
function OhComeOn() {}

var a = Object.create(OhComeOn.prototype);
a[1] = 1;
a.hasOwnProperty(1);       // false
a.propertyIsEnumerable(1); // false
for (var k in a) {
  console.log(k); // will be the string "1"

var b = new OhComeOn;
b[1] = 1;
b.hasOwnProperty(1);       // true
b.propertyIsEnumerable(1); // true
for (var k in b) {
  console.log(k); // will be the string "1"

It does not matter if I use a number or a string as property name or value, it's exactly the same. The only way to make IE believe there is some numeric property to consider too is the following one:
var a = Object.create(OhComeOn.prototype);
a[1] = 1;

// could be anything that is not numeric
a._ = 1;

a.hasOwnProperty(1);       // true
a.propertyIsEnumerable(1); // true
for (var k in a) {
  console.log(k); // will be the string "1", then "_"

Fixed If A Descriptor Is Used Instead

This is where the fun begins, as soon as a descriptor is used, everything is awesome.
var a = Object.create(

a.hasOwnProperty(1);       // true
a.propertyIsEnumerable(1); // true
Even if not specified as propertyIsEnumerable, the hasOwnProperty check will be trustable once descriptors are used instead of direct access.
var a = Object.create(

Object.defineProperty(a, 1, {});

a.hasOwnProperty(1);       // true
a.propertyIsEnumerable(1); // false

Fixing Only These Cases

Accordingly with above behavior, we can say that if there is such bug, and no descriptor is used, most likely we are safe simply polyfilling the behavior:
// note: NOT suitable (yet!) for dictionaries!
var create = Object.create;
if (!function(o){
  o[1] = 1;
  return o.hasOwnProperty(1);
}(create({}))) {
  create = (function(create){
    function Class() {
      // never forget to free the
      // reference counter
      // to the external proto!
      Class.prototype = null;
    return function (p, d) {
      return d ?
        create(p, d) :
        new Class(Class.prototype = p)
With above function, previous examples should work as expected:
var a = create(

a[1] = 1;

a.hasOwnProperty(1);       // true
a.propertyIsEnumerable(1); // true
Unfortunately, this is not the only problem we gonna have with such bug ...

Corrupted And Doomed Dictionaries

What we cannot do is to use above snippet to create dictionaries, since this does not work as we expect:
function Dictionary() {}
// this is not the equivalent of null objects
Dictionary.prototype = null;

// here the proof
var d = new Dictionary;
d.toString; // function {} [native code]

d instanceof Object // true indeed

Setting null as prototype value never worked like that so we need to find a solution ... but how ...
  1. adding and deleting a non numeric property won't work (with latest updated we'll see it works with numeric properties though as hack to fix the problem)
  2. using Object.defineProperty per each property would be boring, verbose, and slow
  3. descriptors, if empty, do not solve the problem
There must be a non numeric property in order to have reliable dictionaries, otherwise these won't be reliable as dictionaries using the most common check we all know since ever: hasOwnProperty.

First Possible Work Around: The in Operator

Take that JSLint, the most secure way to have dictionaries that behaves as dictionaries is to use the in operator that does not suffer from this bug.
var n = Object.create(null);

n[1] = 1;

if (1 in n) {
For dictionaries only, in seems to be the preferred choice also because these properties will show up in for/in loops, but this will break like a charm:
var n = Object.create(null);

n[1] = 1;

if (var k in n) {
  // the infamous check
  // that will FAIL in IE
  if (, k)) {
    alert(k); // will never happen!
The problem here is that most developers are still not ready to abandon JSLint ES3 era hints and embrace dictionaries in a way that is hybrid with these platform, so here I am with the only possible extra solution.

Second Work Around: The Falsy Property

There is no way we deal on daily basis with empty strings as property, unless we are implementing some other sort of hack. I am talking about a solution based on a property that will NOT enumerate, but will FIX properties check.
For unobtrusivity sake, this property should be also configurable and writable.
var n = Object.create(null, {'':{
  configurable: true,
  writable: true

n[1] = 1;

{}, 1);       // true
{}, 1); // true

for (var k in n) {
  console.log(k); // will be **only** '1'
  // since '' is not enumerable

Above solution seems to better fit in current JS world where properties are usually filtered as if (key) {obj[key] = value} plus all own properties will be most likely checked over for/in loops.
More On The Choice Of An Empty String
If you are wondering what's special about the empty string here the answer: when you use JSON.parse(str, revivalCallback) the empty string or the empty key means that the JSON object is fully ready and that would be the last iteration. Since empty property has such strong meaning for JSON, I believe nobody really use empty strings anywhere and for no reason in any library. I also believe nobody ever wrote an empty property name in JSON but in any case this is not a problem because the fix I've proposed will never show up in JSON.parse since it's both not enumerable plus JSON has nothing to do with Object.create so it's the safest property I could think about.

Update II - Actually Not Needed!

Thanks again to Dmitry Korobkin and his further researches: We have a proper solution that won't require any empty string hack.
TL;DR if we set a configurable number and we delete it the object will behave as expected later on ... so ...

Wrapping Up A Solution

In order to have above behavior and a solution for all normal objects in place, here the modified version of initial script:
var create = Object.create;
if (!function(o){
  o[1] = 1;
  return o.hasOwnProperty(1);
}(create({}))) {
  create = (function(create, configurable, define){
    return function (p, d) {
      var r = d ? create(p, d) : create(p);
      // if already own property, nothing to do
      return, 0) ?
        r : (
        // adding and deleting the numeric property
        delete define(r, 0, configurable)[0],
        // so that now the object is "fixed"
Above snippet is the less obtrusive when it comes to Object.getOwnPropertyNames since the empty property will never show up, no matter if it's a dictionary or not.
While this is in my opinion the best fix for the problem, there might some performance implication since the internal class of each object won't be shared anymore and this can cause de-optimizations per each created object.
Putting together a solution that fixes the problem and is not obtrusive is AFAIK not possible so here yet another snippet based on both new chain and the empty property.
var create = Object.create;
if (!function(o){
  o[1] = 1;
  return o.hasOwnProperty(1);
}(create({}))) {
  create = (function(create, empty){
    function Class() {
      Class.prototype = null;
    return function (p, d) {
      // if p is null
      // or there is a descriptor
      return p === null || d ?
        // crete via descriptor or empty
        create(p, d || empty) :
        // chain via good old prototype
        new Class(Class.prototype = p)
  }(create, {'':{
    enumerable:   false,
    writable:     true,
    configurable: true
The main particular caveat, a part from the empty property that will show up in Object.getOwnPropertyNames when it comes to Dictionaries, although hopefully we don't need that so much over Dictionaries like instances, is that passing an empty object as descriptor might confuse the initialization so ... just, don't.
var obj = create(
  {} // <==== DON'T DO THIS!
If we want to be extra sure that with Dictionaries the Object.getOwnPropertyNames won't expose our initial hack, we can tweak that too via:
    var gOPN = original.value;
    function notTheEmptyOne(k) {
      return !!k;
    original.value = function (o) {
      return gOPN(o).filter(notTheEmptyOne);
    return original;
Above hack might be improved accordingly, but that's just a hint I believe not so necessary anyway.

The John-David's Alternative: Don't Object.create(null)

Since using a Dictionary is somehow a doomed choice due some V8 and old WebKit __proto__ implementation, it might make sense to use something like Set/Map from ES6 or a simple HashMap like object instead:
function HashMap() {
  // (C) Andrea Giammarchi - Mit Style
  Object.defineProperty(this, '_', {value:
    // clear all the values
    // returns the HashMap
    clear: {value: function () {
      var keys = this.keys(),
          i = keys.length;
      while (i--) delete this._['@' + keys[i]];
      return this;
    // delete a key, returns true/false
    // accordingly if successful
    del: {value: function (key) {
      return delete this._['@' + key];
    // get the value or undefined
    get: {value: function (key) {
      return this._['@' + key];
    // returns true if present, false otherwise
    has: {value: function (key) {
      return ('@' + key) in this._;
    // all stored keys
    keys: {value: function () {
      var r = [], k;
      for (k in this._) r.push(k.slice(1));
      return r;
    // set a value and returns it
    set: {value: function (key, value) {
      return this._['@' + key] = value;
With above like utility we can have a universally safe ES5 Dictionary that will never perform like an Object.create(null) but will surely work as expected.

Who Fixed The Initial Problem Already?

Not so many libraries I know have a fix for such issue, at least jsCore and my latest prototypal one has been updated using the empty string solution for dictionaries.
The purpose of prototypal is indeed to bring inheritance in every browser, included those not even compatible with Object.create so, if the test is green, you are safe from problems and ready to go.


Well, I have no other words to describe this absurd bug with plain JavaScript objects ... all I know is that old IE always had problems with plain objects too, i.e.
// IE < 9 [[DontEnum]] bug
for (var key in {toString:1}) {
  alert('old IE has never been here');

Today we also have this Object.create(proto) bug which is a very problematic one and specially for dictionaries, where knowing that some number has been set as own property to a null object might not even be such an edge case, surely less edge ... although it took years to realize there is such problem!

Please Fix it ASAP IE/Chakra Team, thank You!

Tuesday, April 08, 2014

Down To Legacy

Regardless the fact Windows XP is Death, there are places on planet Earth where the meaning of maintainable, updated, and secure Software is unknown, like in United Kingdom's government offices, as example ... however, the amount of legacy code we have to deal with daily on the web is horrendously high and it's not just IE8 or lower:

Even worst, there are server side based browsers like Opera Mini still floating around 4% of global Mobile market share ... do the Math: Android KitKat is 5.3%, Opera Mini is 4%

A Common Denominator

You might wonder what have Webkit on Android 2.X or 3.X, Opera Mini, and Internet Explorer 8 or lower in common, and the answer is pretty simple: none of them properly supports ECMAScript 5 standard!
This means that most of the code you find around the internet these days looks or behave broken on these browsers.
A culture that I don't approve much these days is also: "but who uses these browsers?" ... which is highly subjective accordingly with the country you live.
Of course if you have your little online shop for your little community in your little town this is not a concern for you, but if you want to be reached by the rest of the world too and without creating problems, instead of showing what you have to offer, you might want to keep reading and pay attention to details on how you can simply make everything usable for these browsers too.

Modern Patterns Down To IE6

Since my latest project, the only one fully compatible with all browsers and servers side JavaScript engines that went at least close to ES5 specifications, included Opera Mini, received only 3 stars, I've realized developers didn't like the ES6 like approach, full of already reasolved, tested, and robust patterns, I've proposed ... so I've used the prototypal namespace to bring to every browser prototypal inheritance in a way similar to what modern JavaScript does.

Meet prototypal

The namespace has two utilities so far, fully tested across all browsers and server side JavaScript engines, able to do few things, but in a cross platform working way:
var create = prototypal.create;

// yes, the null object
// available even in IE6
// and Opera Mini
var obj = create(null);

// inheritance
var a = {
      prop: 123,
      method: function () {
        return this.prop;
    b = create(a, {
      prop: 456
b.method(); // 456
If you think es5-shim solved that for you via Object.create you are wrong since es5-sham is marked as not reliable so here prototypal.create will offer tested portability and reliability across all platforms I could try, down to IE6, Opera Mini, Android 2.X and I bet it should work even on Android 1.X too!
The create interface is very similar to the one used in lo-dash except right now lo-dash copies all properties instead of upgrading the instance where possible so, at least for this case, prototypal should be way faster than lo-dash, assuming properties won't be reused anytime anywhere more than once, which I believe is the most common daily pattern.

Classical OOP Too

I've spent quite a while behind the original Class implementation for modern engine and it did not take much effort to support a less pattern filled version for legacy engines ... so I've put it there too without compromising much the final size, the performance, or the quality:
var Class = prototypal.Class;

var Rectangle = Class({
  constructor: function (width, height) {
    this.width = width;
    this.height = height;
  toString: function () {
    return '[object Rectangle]';
  area: function () {
    return this.width * this.height;

var Square = Class(Rectangle, {
  constructor: function (size) {, size, size);
  toString: function () {
    return '[object Square]';

No Strings Attached

Getters and setters, for compatibility sake we can forget about it. These are very nice patterns, but not the most necessary and to preserve compatibility and performance, we ain't gonna need them ... right?
Is null available too? Well, Class works exactly as create except it extends functions prototypes, if function is the first argument, otherwise it creates inheritance with objects, or null, too:
var Null = Class(null, {
  // some optional method
  // that we might want to inherit

var n = new Null;
n instanceof Object; // false
Once again, all of this has been tested basically everywhere and you will rarely find similar compatibility out there.

Not Only ES5: Mobile Internet Explorer

I really have enough bullshit around not supporting IE10 Mobile ... this is not the right place to tell you I have fixed even IE9 Mobile panning simulating touch events but IE10 ... for gosh sake, is a way more decent browser than any Android 2.X!
Why on earth some spoiled developer decided that some library or canvas based game should not work on IE because of his/her lack of understanding of pointer events or inheritance, due silly usage of __proto__ even when not strictly necessary, as I've just demonstrated I can have inheritance in IE6 too in an ES5 similar way, I have no idea!
Remember the 2048 game? It was basically one file to add in order to support IE10 too ... and guess what happened when it finally supported IE mobile?

26 retweets and 16 likes ... I've honestly no memories of last time a tweet of mine has been appreciated that much ... seriously!

Polyfill for Touch Events IE Mobile

I don't honestly know when exactly the modern internet became such a douchebag place where supporting everyone is not anymore the mandatory number 1 priority and people keep telling now and then "who uses it?", all I know is that if you really don't support IE Mobile because of your simplified touch events, you can put this polyfill upfront and deal with it!
Seriously, is that simple! You add the script and magic happens, IE 10 supports Touch events and you know why? Because the proposed PointerEvents Interface is actually superior so it's pretty easy to simulate touches in there, while it's impossible to bring same interface on old Touch API.
Bear in mind, the fact we use Touch API on the mobile web ... is because we are not updated on the current leading specification about touches ... it's not that MS did something wrong, for once at least ...

The Web To The Web!

It's a tendency I keep noticing since a couple of years ... I don't know if it's because people are tired about failing and slow standard bodies, but we should never give up about the meaning of the internet: progress yes, but when it's deadly easy to support an older browser, ask yourself and your business why on earth you are not doing it ... it's your money you are eventually loosing, those users? 4% of 4 billions surfing? Who cares, right?
Thanks for keeping the web reasonably accessible when you can ... I am not saying WebGL should not be used, I am saying except for WebGL that cannot be replaced, think twice before you chose any library or framework that supposes to make your life easier.
IE8 is still a thing, so are Opera Mini, old Androids, Nokia Express on Asha platform, and Symbian ... it would be our fault if these people cannot gracefully upgrade their devices and rather feel left outside the rest of the modern world that cannot wait, even if there was actually nothing to wait for.

Tuesday, April 01, 2014

Diversity Is Diversity

He Stepped Down as Mozilla CEO and I have mixed feelings about this choice.
I am not sure if anyone won here ... but I'll leave here my thoughts, still behind my ideal that personal believes shouldn't be judged at work.
I also wish in 2014 the "witch hunting time" was already extinguished.

I 100% support LGBT equal rights and I think that if the web should be for all, so should marriage.
In this post I am not defending anyone but the ideal behind a company that already changed this world for good. If you gonna stop in the middle of this post thinking I am a puppet or a fool, feel free to, but please don't comment me back unless you reached the end of my thoughts. Thank You!
I don't understand why people keep mixing up apples and oranges on the internet these days, and I know this is the worst time ever for a post about it, 'cause everyone will think is an April fool ... but it's actually not at all, and yes, this is about Mozilla.

Mozilla & The World Wide Web

Mozilla promotes since ever the web as a standard and before it was cool.
Mozilla believes, and I am sure his new CEO too, that the Web should reach every person in the world!
You won't find many other companies making deals for $25 smart phones support, specially considering all the effort that takes to this company's developers to make such low price HardWare phones competitive against others, and inside a browser, as crazy as it sounds!
Good news is, the recently announced Mozilla CEO has the same vision for the company he is representing ... but ...

What I personally think is that the Web should be for everyone, and so should be marriage, period!

However, does the Mozilla CEO personally think exactly the same? I don't actually care much ... and you know why?

Mozilla Promotes Diversity

Can we please drop some hypocrisy from the topic and focus on what exactly does diversity mean?
di·ver·si·ty the state of being diverse; variety.
Diversity is not just about being gay or about physical handicap and different abilities, diversity is also about accepting other people cultures, believes, religions and thoughts, as well as other people ideas, even if considered jurassic, wrong, bad, bigot, worst ever, lame, evil, pointless ... on and on ...

And Diversity Is Promoted Indeed

Apparently every freshly new hired Mozillian, as well as some veteran, is free to share thoughts about such choice, express themselves and speak out loudly and publicly!
There have been few days of my career when I was feeling really frustrated about my current job situation, and guess what? ... I wish I could do the same online, share how disappointed I was and why!
Just think about it, how many of us can easily judge another company CEO but are unable to speak freely about our own one?
I have the feeling this is like the single case everyone blames because finally there is someone to blame and drop all frustrations ... yeah, let him resign ... and then what? Will he change his mind about his own personal believes? I don't think so! Moreover, will Mozilla change a single bit about its diversity promoting culture? I don't think so neither, I actually think Mozilla once again demonstrated to be one step in front of many other companies where talking about the CEO in order to put the company under a dark light might be even forbidden by contract!
So what are we exactly talking about these days?

All I Know About Mozilla CEO

Is that he has been there for a while, it has been working 24/7, maybe too much, and regardless the amount of discussions we personally had in the past, as well in the present, this person always demonstrated a reasonable understanding of other people (ahem, mine as well) attitude without ever crossing a respectful line in term of human respect, and despite his role I personally don't even know if I'll ever be able to think about or be able to handle ... but regardless ...

Mozilla Is About Mozillians

The thing that I admire since ever about this company is the passion, equivalent or higher than mine, that every person from this company put on daily tasks. It's not by accident that I forgot to mention a single name in this post, because Mozilla represent what is the World Wide Web today, and pointing all fingers to just one of them, does not give any justice to all amazing people that somehow helped making the web as it is happen, and making step forwards every day sharing all they know and not just for profit.
In few words, when I see this bullshit I get sad:

because blaming the effort of hundreds of people that believes in the internet and made your own website possible these days breaks every free thought you could share on the web since it's born!

No Need To Generalize

If you really want to protest against this person, talk about his personal choices privately but don't promote a campaign that involves hard workers and passionate about their job as this same person is and has been for long time ... and of course, if you ever even learned how we reached the HTML5 era we know these days, we'd probably even think about blaming Mozilla, isn't it?
Be free online, and keep all your energies to keep being free to surf the net ... it's awesome, and most of this awesomeness, comes from Mozilla and also its new CEO that worked there as Mozillian since ages and for the good sort of the current and future Web!

Always fight your battles whenever you want, but in the right place, and at the right moment!

Thanks for reading.