{"categorySlug":"blog","subcategorySlug":"technology","articles":{"blog\/technology\/social-media-as-a-public-service":{"key":"blog\/technology\/social-media-as-a-public-service","type":"article","published":true,"meta":{"createdAt":"2024-07-29T14:04:08+00:00","publishedAt":"2024-07-29T14:04:08+00:00","group":null,"category":"blog","subcategory":"technology","slug":"social-media-as-a-public-service"},"content":{"en":{"slug":"social-media-as-a-public-service","title":"Social Media as a Public Service","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/social-media-public-service_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACf0lEQVRIic2WXUhTYRjHf+dszuM222p9aJQfNOyLoNKCkInhneYHGdlFZQVZgRTdB2XdhFRgF0VfdhFBdKF1lYX4gWGGM+smnTqbmFnq1M3cOnM7p4vddVNHWe5\/\/T7P+4P3\/zz\/VzCxTyWOJC43wJ+KOyC9lsObtxgoLEpGShKZ8yu43TLvuwJMe5XlAXI4TFQcsRIMqlisIhkZiYgitLX+5HbdFC3N80sGEpZiakkScOQZqTy5iuISC02vfFSf+8bkZOT\/AWVlJbJmrR6vN8zQYIhwOFqenSNx78EGjEaR0gMeBgdDsQcSBBgd34rFogPA74vQ2ODnRu0kHk8Ic7LIs+dp2O0G8vOG+T4eji0QgMksotcJrEvR48gzceasjYzMBC5eGOfpkxlMJpHm1kymvGFKCkdQNRpCZ2DjFS0FCyEVWVbxeiP0fghS\/2gGvV7gem0qY2MLOLuDvOsMUHM1hQGXTF+fHFugg+UW3nbZOVxhxWgScXYHaW+bR1Wh5loKjQ1+XP0y6ekJlJSt4HH9jCYgzU9msejYX2Bm126J01U2epwBystGCIdVOjrtuPplTp0YZc9eiZZ2Ozt3uHAPLfxzf82b2ueL8PKFj8uXflCQ7yY7x0j1+dUoCty946W4dAVJSSI9zl\/MzobJzTVp6r+o6KiqsgHQ91nm4f1pjh6zAtDRPo8kCWzbnoiiwIBLZpPdEDsgg0HgVt16am+mcrxyJQCfPgZJS49eOjERHXObLRoAfr+COVmnCUhTdIRCKm+a5ujtCeJ0BgB43TRHxaERABRFxfMlxNfRqGeMRoFAQFvOLSk6\/qai4mSGh0KaRj+mQItR3P2H4g7oN7V770kPCqofAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/social-media-public-service_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAs a software developer I can\u0027t help but look at all the issues plaguing social media and think that\n\u003Cem\u003Esurely\u003C\/em\u003E they can be fixed with code somehow \u2013 we just need a cool distributed protocol or something, right?\nBut the thing is, no amount of techy magic is going to help here, because the problems are not technical \u2013\nthey\u0027re policy issues.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/social-media-public-service_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACf0lEQVRIic2WXUhTYRjHf+dszuM222p9aJQfNOyLoNKCkInhneYHGdlFZQVZgRTdB2XdhFRgF0VfdhFBdKF1lYX4gWGGM+smnTqbmFnq1M3cOnM7p4vddVNHWe5\/\/T7P+4P3\/zz\/VzCxTyWOJC43wJ+KOyC9lsObtxgoLEpGShKZ8yu43TLvuwJMe5XlAXI4TFQcsRIMqlisIhkZiYgitLX+5HbdFC3N80sGEpZiakkScOQZqTy5iuISC02vfFSf+8bkZOT\/AWVlJbJmrR6vN8zQYIhwOFqenSNx78EGjEaR0gMeBgdDsQcSBBgd34rFogPA74vQ2ODnRu0kHk8Ic7LIs+dp2O0G8vOG+T4eji0QgMksotcJrEvR48gzceasjYzMBC5eGOfpkxlMJpHm1kymvGFKCkdQNRpCZ2DjFS0FCyEVWVbxeiP0fghS\/2gGvV7gem0qY2MLOLuDvOsMUHM1hQGXTF+fHFugg+UW3nbZOVxhxWgScXYHaW+bR1Wh5loKjQ1+XP0y6ekJlJSt4HH9jCYgzU9msejYX2Bm126J01U2epwBystGCIdVOjrtuPplTp0YZc9eiZZ2Ozt3uHAPLfxzf82b2ueL8PKFj8uXflCQ7yY7x0j1+dUoCty946W4dAVJSSI9zl\/MzobJzTVp6r+o6KiqsgHQ91nm4f1pjh6zAtDRPo8kCWzbnoiiwIBLZpPdEDsgg0HgVt16am+mcrxyJQCfPgZJS49eOjERHXObLRoAfr+COVmnCUhTdIRCKm+a5ujtCeJ0BgB43TRHxaERABRFxfMlxNfRqGeMRoFAQFvOLSk6\/qai4mSGh0KaRj+mQItR3P2H4g7oN7V770kPCqofAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/social-media-public-service_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAs a software developer I can\u0027t help but look at all the issues plaguing social media and think that\n\u003Cem\u003Esurely\u003C\/em\u003E they can be fixed with code somehow \u2013 we just need a cool distributed protocol or something, right?\nBut the thing is, no amount of techy magic is going to help here, because the problems are not technical \u2013\nthey\u0027re policy issues.\u003C\/p\u003E\n\u003Cp\u003ETry to think of a big issue with social media that \u003Cem\u003Ecan\u0027t\u003C\/em\u003E be tracked back to its flawed business model.\nOf course we\u0027re gonna get addicted to doom scrolling, if algorithms optimise our feed for maximum engagement.\nOf course it will be plagued with misinformation and polarising, hateful content, if that\u0027s what drives engagement.\nOf course the big tech won\u0027t do more than absolutely necessary to deal with all the toxic stuff and AI-generated trash\non their servers, if removing that content directly reduces their advertisement revenue.\nOf course big tech is gonna sell and abuse as much of our private data as the regulations allow them \u2013\nas long as it brings them their billions.\u003C\/p\u003E\n\u003Cp\u003EBut imagine if simply we took away the whole incentive to \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Enshittification\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E enshittify\u003C\/a\u003E\nthe Internet? What if we took ads out of the equation? What if we took \u003Cem\u003Ethe profit incentive\u003C\/em\u003E out of the equation\nand started treating social media as a public service?\u003C\/p\u003E\n\u003Cp\u003EWe already treat a bunch of other media as public services after all: we have public TV broadcasters, public radio stations,\nrarer, but still, publicly owned press\u2026 We\u0027re fine paying taxes in order to receive professional services\naccessible to everyone and under democratic control. We see how much power the conventional media has to shape public opinion,\nso we don\u0027t want it all in the hands of big corporations. I\u0027d argue that for social media this is \u003Cem\u003Eeven more\u003C\/em\u003E important.\u003C\/p\u003E\n\u003Cp\u003ERunning a social media page is no small enterprise \u2013 but the EU has more than enough resources to pull it off.\nAnd judging from how strongly have they been going after big tech for their monopolistic and anti-privacy practices,\nthere would likely be a political will do accomplish it too.\u003C\/p\u003E\n\u003Cp\u003EImagine that\u2026 every EU resident gets their own virtual space: some storage space, a subdomain, an email address,\na simple website builder with blogging and commenting capabilities. It could use \u003Ca href=\u0022https:\/\/www.w3.org\/TR\/activitypub\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E ActivityPub\u003C\/a\u003E\nor its own new protocol to federalise those blogs. Instead of creating a Gmail account owned by Google,\nand a Facebook account owned by Meta, and a Twitter account owned by Musk, etc. etc.,\nyou could just create an account \u003Cem\u003Eowned by you\u003C\/em\u003E \u2013 with the infrastructure maintained and the content moderated\nby the state, just like it now does with other kinds of infrastructure, from roads to radio waves.\u003C\/p\u003E\n\u003Cp\u003EWe could go back to the early days of the Internet before big tech swooped in and monopolised the mainstream.\nBack to the times where people owned the stuff they posted \u2013 except make it easily accessible even to non-techies.\u003C\/p\u003E\n\u003Cp\u003EIt shouldn\u0027t even be hard to get a critical mass of users on the platform \u2013 just make it as good as Facebook or Twitter\n(what a depressingly low bar!) but make it completely free and without any ads or \u201cthe algorithm\u201d \u2013 who wouldn\u0027t switch?\nOffering an alternative to big tech\u0027s vision of the Internet wouldn\u0027t really kill big tech \u2013 but it would definitely\nforce it to do better and compete with user- and privacy-friendly alternatives.\u003C\/p\u003E\n\u003Cp\u003EIf you don\u0027t want your page stored by the government, you can host it yourself \u2013 but still reap the benefits\nof the open-source website creator and federating with the network. If you don\u0027t want to use the website builder,\nwrite your own page and implement the open protocol on it (or not). If you prefer to use your space for something\ndifferent, just do that instead. You can have all the freedom of corporation-free Internet,\nwithout needed the technical know-how to set it all up.\u003C\/p\u003E\n\u003Cp\u003EObviously, accomplishing that wouldn\u0027t be easy. It costs to run a social media portal \u2013 just like it costs\nto maintain roads or run radio stations. Social media requires moderation \u2013 just like road safety requires\ntraffic rules and vehicle registration. Moderation rules and decisions would be just as controversial as today \u2013\nbut at least controlled democratically and not by a faceless corporate entity.\u003C\/p\u003E\n\u003Cp\u003EIt might not be easy. But if we do it right, it could be soooo worth it!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["internet","social media","policy","eu","open-source"],"hasMore":true,"image":"https:\/\/avris.it\/image\/social-media-public-service_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/social-media-public-service_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/social-media-public-service_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAs a software developer I can\u0027t help but look at all the issues plaguing social media and think that\n\u003Cem\u003Esurely\u003C\/em\u003E they can be fixed with code somehow \u2013 we just need a cool distributed protocol or something, right?\nBut the thing is, no amount of techy magic is going to help here, because the problems are not technical \u2013\nthey\u0027re policy issues.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/social-media-public-service_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/social-media-public-service_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAs a software developer I can\u0027t help but look at all the issues plaguing social media and think that\n\u003Cem\u003Esurely\u003C\/em\u003E they can be fixed with code somehow \u2013 we just need a cool distributed protocol or something, right?\nBut the thing is, no amount of techy magic is going to help here, because the problems are not technical \u2013\nthey\u0027re policy issues.\u003C\/p\u003E\n\u003Cp\u003ETry to think of a big issue with social media that \u003Cem\u003Ecan\u0027t\u003C\/em\u003E be tracked back to its flawed business model.\nOf course we\u0027re gonna get addicted to doom scrolling, if algorithms optimise our feed for maximum engagement.\nOf course it will be plagued with misinformation and polarising, hateful content, if that\u0027s what drives engagement.\nOf course the big tech won\u0027t do more than absolutely necessary to deal with all the toxic stuff and AI-generated trash\non their servers, if removing that content directly reduces their advertisement revenue.\nOf course big tech is gonna sell and abuse as much of our private data as the regulations allow them \u2013\nas long as it brings them their billions.\u003C\/p\u003E\n\u003Cp\u003EBut imagine if simply we took away the whole incentive to \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Enshittification\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E enshittify\u003C\/a\u003E\nthe Internet? What if we took ads out of the equation? What if we took \u003Cem\u003Ethe profit incentive\u003C\/em\u003E out of the equation\nand started treating social media as a public service?\u003C\/p\u003E\n\u003Cp\u003EWe already treat a bunch of other media as public services after all: we have public TV broadcasters, public radio stations,\nrarer, but still, publicly owned press\u2026 We\u0027re fine paying taxes in order to receive professional services\naccessible to everyone and under democratic control. We see how much power the conventional media has to shape public opinion,\nso we don\u0027t want it all in the hands of big corporations. I\u0027d argue that for social media this is \u003Cem\u003Eeven more\u003C\/em\u003E important.\u003C\/p\u003E\n\u003Cp\u003ERunning a social media page is no small enterprise \u2013 but the EU has more than enough resources to pull it off.\nAnd judging from how strongly have they been going after big tech for their monopolistic and anti-privacy practices,\nthere would likely be a political will do accomplish it too.\u003C\/p\u003E\n\u003Cp\u003EImagine that\u2026 every EU resident gets their own virtual space: some storage space, a subdomain, an email address,\na simple website builder with blogging and commenting capabilities. It could use \u003Ca href=\u0022https:\/\/www.w3.org\/TR\/activitypub\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E ActivityPub\u003C\/a\u003E\nor its own new protocol to federalise those blogs. Instead of creating a Gmail account owned by Google,\nand a Facebook account owned by Meta, and a Twitter account owned by Musk, etc. etc.,\nyou could just create an account \u003Cem\u003Eowned by you\u003C\/em\u003E \u2013 with the infrastructure maintained and the content moderated\nby the state, just like it now does with other kinds of infrastructure, from roads to radio waves.\u003C\/p\u003E\n\u003Cp\u003EWe could go back to the early days of the Internet before big tech swooped in and monopolised the mainstream.\nBack to the times where people owned the stuff they posted \u2013 except make it easily accessible even to non-techies.\u003C\/p\u003E\n\u003Cp\u003EIt shouldn\u0027t even be hard to get a critical mass of users on the platform \u2013 just make it as good as Facebook or Twitter\n(what a depressingly low bar!) but make it completely free and without any ads or \u201cthe algorithm\u201d \u2013 who wouldn\u0027t switch?\nOffering an alternative to big tech\u0027s vision of the Internet wouldn\u0027t really kill big tech \u2013 but it would definitely\nforce it to do better and compete with user- and privacy-friendly alternatives.\u003C\/p\u003E\n\u003Cp\u003EIf you don\u0027t want your page stored by the government, you can host it yourself \u2013 but still reap the benefits\nof the open-source website creator and federating with the network. If you don\u0027t want to use the website builder,\nwrite your own page and implement the open protocol on it (or not). If you prefer to use your space for something\ndifferent, just do that instead. You can have all the freedom of corporation-free Internet,\nwithout needed the technical know-how to set it all up.\u003C\/p\u003E\n\u003Cp\u003EObviously, accomplishing that wouldn\u0027t be easy. It costs to run a social media portal \u2013 just like it costs\nto maintain roads or run radio stations. Social media requires moderation \u2013 just like road safety requires\ntraffic rules and vehicle registration. Moderation rules and decisions would be just as controversial as today \u2013\nbut at least controlled democratically and not by a faceless corporate entity.\u003C\/p\u003E\n\u003Cp\u003EIt might not be easy. But if we do it right, it could be soooo worth it!\u003C\/p\u003E","words":726,"readTime":3,"lang":"en"}}},"blog\/technology\/ovh-bulldozed-my-server":{"key":"blog\/technology\/ovh-bulldozed-my-server","type":"article","published":true,"meta":{"createdAt":"2024-06-29T06:54:49+00:00","publishedAt":"2024-06-29T06:54:49+00:00","group":"customer-rants","category":"blog","subcategory":"technology","slug":"ovh-bulldozed-my-server"},"content":{"en":{"slug":"ovh-bulldozed-my-server","title":"OVH bulldozed my server","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer_small.png\u0022 alt=\u0022AI-generated illustration: a wrecking ball with OVHcloud logo smashing a server with my blog\u0027s logo\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022343.59375\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAZCAYAAABZ5IzrAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAKoUlEQVRIiSXU249c90HA8e+5z5kz99vO3uz17vqWxI5dxzgJKYlrSAVUrdKqalNFiJbSvgCiL6FCSPgRVCRAFZWAB9RKSFRKVSBNCnXaXEp8iV07cRyn3lu8u97LzOzMzsy5X37n8JC\/4fvRV3r19ZezxYMzGJqC7bn87fd+wPK9j0j8ECFiqgUTI\/SZOLLA0PdJ4pAsEeRMnUajwskTDyGlCaqqkgjB5evvs7vTQ8oyUpGSNw1GYw9FllAlCFOdre19as0iZx8\/yZ\/94RdQVI0kEbxz9x5KYFYunnrkKKqikNNkLCvPrTtLKICmqsiGga7KGCgUG0WarTpm3qBomZRKFq7jsrndodfr4foBQZSgqhKKolItWYRJiu3FqJpOLmfihYI0FRRrJb7xB89RKRVJ04yN3h7\/+G\/\/hXrz6nt8V5Wo10oYukIchRi6RhDHFKwiKQnVcoWw22e+0katVHAdB9NQMXMa1WKJ4dgkDEIMQ0PCYKU3olTOM1E2qAxgZAcULR3TzLP7oIeqqchSysv\/+xaaYZBmGctL6+zeWUaaWng0M8t5qs0Kuq4gKzKGoWPqKqqiYRoypUoBMR6xv9nl81\/9HCID01ApmDq1Ypkg8Ahigev5XL36IaqRIqsKmayxfn+LjIx83qTXHdHb9zDzBkEs8IKINBbIQvCZdsLhaRPFLFYvSkikaUq+YDE902Zmps3UTBuRCSwzT7FcZPHIIcLeNp2BQ6c3Zn\/okWUSB2anmW436ez2mJhoUSzlaE9UEUlKsWihSIJGpYAnFHq9IdVmjfmFAxg5E1lVccYu486Ath7zPzf3UMrNyYuyIqMoCqVahT\/946\/w+WfP8\/RvnCKVJJwo4chsHW2wwVs3VhmFcPThYxw9ephcvsRPf\/YmE60WRxfnSOKEStlCVxVaE00MVSGfy1EqFnAch2K5wO+cf4KvfvGznH\/iUayCyTvX7\/DkoRK\/WHZwFQOlNjl\/MWfmyMiQVYnt4ZiHFg5SKljMTE7gBC5zyoC\/\/9efMfQzZuemefTEUR47dZLFuQNUKiW+\/+8vMT01RX9vQLNZRcpS2vUKVt6gYBUoFS1MQ6FUKfHM42exRy7d\/SH\/\/P0fY48c1rsuumkQxClKodK4aJoGVsEgS1OiKGR58wErG+ts7Oxw9vAkL\/3gJW7c20NSFEwrR7lcQFEkcoaO69rc\/fUy91c+4slzjxJ4NvVahQ\/vLvGLN94jl9OZmZ3EyuXwbJ9ur8vV23d47a0bdDt9RJJgmDk8P0IWAtWwTGRNQtZ0coZCEkd0Ol00TcEq5FG9AW\/f2sSxQxKRsb2+y1Vusbp6n4mJOpIE4\/0hO\/19CqbCR0vb\/OTl1\/nPV67xwtee55dXPuSHP\/w5D51Y5MDBSVrNIvpujyQMsEwdTVfpD1xyloErK6j1iRpnzp5AljPuLq2DSJAkiTgRzLYn8Ecj6u0DzC5Wub++jq7p7G3v440Dejs9Qt9HRCG6BNf+7ypqGnHl2oeESUbOzKHpFo2pKXa291lZ2ibNEhaPznFwps3ecBWzaHHh9CN4bsSl1y6jnH7y3MVjxxb5+hc\/y4GZJr96fwkjp1Mq5EhJmSubPP9H36LVajIeO+z396mUy7QaTeqVBsV8kXazRSmfx5ACOp0+H6z2ODA7wWS7jusLdCvPe\/sakWyAb+M4DuWJFrKU8ufffIEzJ45x64NlDEVC+uaL38qKeYsH\/T69\/j6GplKtF2nVK7RaVSrDTb7z3VcZ2hFpmiLLIEsShq5iaDLFnEa1pNFqFT9OmGasD2NmDs5SKNcYODGxSLheO8mZZ86x+U9\/R7sAhw5PsbHdYc+NOLp4CMkXpJGL2iga3Hv7Cla1xdPnTuElIV\/6vQs4rsvtlVVK9YeZmb6Gt9ZDiBSJDF1TyOsqOSWlnJMo6xnTDYuFuSZX3l1nbWWH+SOLjOwAFOhud6huv8HG1vvIkY9VbPLJx09x84N7FMp1Xv+PVymZMsfPHEOWNY12zWKwusZuZ0Box\/z40pu8\/MZlskRQqNT5yte\/zORsE6tYoFjMU8rrlHLQLinMluH08QleeP48WuKRlxPMnEYsBFEY4uw7OJKBFoQM7i3hDPocODhBGMYMuyPGIxfZGdIoW4RhhOy4PpmeI5ElLENh9dpVhBdSLVRpNCroqsq5J8\/wN995kd985gy1VoVqJUe9bLAwW+ILXzrPl7\/2HKHj0JqeRFY0ZqbqDPcdAt9D1yRGI5fg+CdIZZV6q04S+axvbCF21jFkCScQuG5AGCeoUSYThxFJAmmWQRhiEfLrW7cJvVnOPnaaKEpYOHSAb7\/4DZQsodPpISc2RTWikMuolQyWrm1w+XaX7T2bpz79Sa7d3GDu4DRr6ztk9pDi1jKKpeB4PrnIRo40SkpKlsRIkoSWU\/BDgdx3Y9aDlIEASTfxlDyqDKaa4XY6vHPjNmtbXSKRUSwYeEHE6dOPUG9OMXfsBGalzb27a2zu2HR6Y+bm2mxs9\/nUb1\/gM7\/\/HJ9+9ndRJI3PPf0kk9UqhqFT0CQkYNeJCaOYHU+wG8n03Rg5SASdQKEfS3hGlU5zHl\/IeLFElKkoCLp7AzqDMVeuvsvtO8tEUUShUkQ18vT39rm3tMmD\/ZhANjl8dIaPNgeceeRh\/vvVV6g1aszMz3Bw7hBLy2vMz9URukHfDdlPFLwwQM1SVro+dpQhG6ZF\/YlnodBAS2PS\/h5ZpcFYMrBzBXwBWSqI\/DEz05NcOP84qqZz9fJNth7ssrGyzP2Ox8hPKZgG\/X0bIWvcvH2H1bX7fO+Vt\/mTv\/prfvTTS2RkNOtFOj4UGm02AhU3luirVcpnP0WUgezZY7I7P0EOxty+fBVPSHyw\/IDx0Ma3PfwoJYljfvnWdf7iL\/+Bbn\/EyLY5\/dhJRCa4u9Zh6CWs7\/ncH0YISUJJE177+SX8IGJHyfEvWzZ3Vu6TySrlUgFXqKys76CYebY3d5EiG\/fGJWLXQc1GA2aylCAcMTN1nI33tymrKbuOTRxZ2GOHriazsHCQb587Q61eZjQcsdftktfh\/pbNbndMnKkI32Wz46MrMk4oCMKQ3K3XuXP3FmZkU6talAsGy6ubVCol9FEXq9imHQxpSAbOUCD7I5tkYFMTCSL00P0B+cCmKAu0JEJFQCaRSRI502BlbR2zYHJo4QDv3lljbxziRBlDJ+Lh+TrvfrgDkkKj1WRvHKJrOtmwSxzGHJlvUSvpWFmAGjrMawGha1OWBHoYgUhRA8dFSAI3TlCChDAGzwsIgwA18gltcEi5n\/hcefNXPPHEKdqtBvZoyPpWh27fxg0S4jhD1TQm2w1kVaeztUvkhcTlCpEXYdZNGrUCne4Qzw8Z2TFEKV4QE2QSuUQQiBDZd33iWBAlCb4ToJEgHAcRBARuQOT5DB2fVNU591uf4PDxeR7s9kgzwdrqFiMvwnUDEmSiDBRSXMcjzCSMU09hPnWBfKWE5\/lMTdcY7I2Qwpi88DCTBN92EJlEEidEQYQsCfHxnDKIPA9VlnEcjzTNUNOPHURxQhhHJEKwNxhy\/fptVN1kcWGWVr2CSGUemq\/xoB8hpTJCZMR+SNKeIJtfwNBVZg5OIKcZIzdAiBQ\/ziiUDNJMxlAkNEVCTlP+H4ABWPHrRyKKAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer_small.png\u0022 alt=\u0022AI-generated illustration: a wrecking ball with OVHcloud logo smashing a server with my blog\u0027s logo\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022343.59375\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA big chunk of my free time in the last week has been consumed by work on restoring a bunch of my projects\nafter my hosting provider, \u003Ca href=\u0022https:\/\/ovh.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E OVH\u003C\/a\u003E, completely removed my server and backups.\nHere\u0027s what happened.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer_big.png\u0022 alt=\u0022AI-generated illustration: a wrecking ball with OVHcloud logo smashing a server with my blog\u0027s logo\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022687.1875\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAZCAYAAABZ5IzrAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAKoUlEQVRIiSXU249c90HA8e+5z5kz99vO3uz17vqWxI5dxzgJKYlrSAVUrdKqalNFiJbSvgCiL6FCSPgRVCRAFZWAB9RKSFRKVSBNCnXaXEp8iV07cRyn3lu8u97LzOzMzsy5X37n8JC\/4fvRV3r19ZezxYMzGJqC7bn87fd+wPK9j0j8ECFiqgUTI\/SZOLLA0PdJ4pAsEeRMnUajwskTDyGlCaqqkgjB5evvs7vTQ8oyUpGSNw1GYw9FllAlCFOdre19as0iZx8\/yZ\/94RdQVI0kEbxz9x5KYFYunnrkKKqikNNkLCvPrTtLKICmqsiGga7KGCgUG0WarTpm3qBomZRKFq7jsrndodfr4foBQZSgqhKKolItWYRJiu3FqJpOLmfihYI0FRRrJb7xB89RKRVJ04yN3h7\/+G\/\/hXrz6nt8V5Wo10oYukIchRi6RhDHFKwiKQnVcoWw22e+0katVHAdB9NQMXMa1WKJ4dgkDEIMQ0PCYKU3olTOM1E2qAxgZAcULR3TzLP7oIeqqchSysv\/+xaaYZBmGctL6+zeWUaaWng0M8t5qs0Kuq4gKzKGoWPqKqqiYRoypUoBMR6xv9nl81\/9HCID01ApmDq1Ypkg8Ahigev5XL36IaqRIqsKmayxfn+LjIx83qTXHdHb9zDzBkEs8IKINBbIQvCZdsLhaRPFLFYvSkikaUq+YDE902Zmps3UTBuRCSwzT7FcZPHIIcLeNp2BQ6c3Zn\/okWUSB2anmW436ez2mJhoUSzlaE9UEUlKsWihSIJGpYAnFHq9IdVmjfmFAxg5E1lVccYu486Ath7zPzf3UMrNyYuyIqMoCqVahT\/946\/w+WfP8\/RvnCKVJJwo4chsHW2wwVs3VhmFcPThYxw9ephcvsRPf\/YmE60WRxfnSOKEStlCVxVaE00MVSGfy1EqFnAch2K5wO+cf4KvfvGznH\/iUayCyTvX7\/DkoRK\/WHZwFQOlNjl\/MWfmyMiQVYnt4ZiHFg5SKljMTE7gBC5zyoC\/\/9efMfQzZuemefTEUR47dZLFuQNUKiW+\/+8vMT01RX9vQLNZRcpS2vUKVt6gYBUoFS1MQ6FUKfHM42exRy7d\/SH\/\/P0fY48c1rsuumkQxClKodK4aJoGVsEgS1OiKGR58wErG+ts7Oxw9vAkL\/3gJW7c20NSFEwrR7lcQFEkcoaO69rc\/fUy91c+4slzjxJ4NvVahQ\/vLvGLN94jl9OZmZ3EyuXwbJ9ur8vV23d47a0bdDt9RJJgmDk8P0IWAtWwTGRNQtZ0coZCEkd0Ol00TcEq5FG9AW\/f2sSxQxKRsb2+y1Vusbp6n4mJOpIE4\/0hO\/19CqbCR0vb\/OTl1\/nPV67xwtee55dXPuSHP\/w5D51Y5MDBSVrNIvpujyQMsEwdTVfpD1xyloErK6j1iRpnzp5AljPuLq2DSJAkiTgRzLYn8Ecj6u0DzC5Wub++jq7p7G3v440Dejs9Qt9HRCG6BNf+7ypqGnHl2oeESUbOzKHpFo2pKXa291lZ2ibNEhaPznFwps3ecBWzaHHh9CN4bsSl1y6jnH7y3MVjxxb5+hc\/y4GZJr96fwkjp1Mq5EhJmSubPP9H36LVajIeO+z396mUy7QaTeqVBsV8kXazRSmfx5ACOp0+H6z2ODA7wWS7jusLdCvPe\/sakWyAb+M4DuWJFrKU8ufffIEzJ45x64NlDEVC+uaL38qKeYsH\/T69\/j6GplKtF2nVK7RaVSrDTb7z3VcZ2hFpmiLLIEsShq5iaDLFnEa1pNFqFT9OmGasD2NmDs5SKNcYODGxSLheO8mZZ86x+U9\/R7sAhw5PsbHdYc+NOLp4CMkXpJGL2iga3Hv7Cla1xdPnTuElIV\/6vQs4rsvtlVVK9YeZmb6Gt9ZDiBSJDF1TyOsqOSWlnJMo6xnTDYuFuSZX3l1nbWWH+SOLjOwAFOhud6huv8HG1vvIkY9VbPLJx09x84N7FMp1Xv+PVymZMsfPHEOWNY12zWKwusZuZ0Box\/z40pu8\/MZlskRQqNT5yte\/zORsE6tYoFjMU8rrlHLQLinMluH08QleeP48WuKRlxPMnEYsBFEY4uw7OJKBFoQM7i3hDPocODhBGMYMuyPGIxfZGdIoW4RhhOy4PpmeI5ElLENh9dpVhBdSLVRpNCroqsq5J8\/wN995kd985gy1VoVqJUe9bLAwW+ILXzrPl7\/2HKHj0JqeRFY0ZqbqDPcdAt9D1yRGI5fg+CdIZZV6q04S+axvbCF21jFkCScQuG5AGCeoUSYThxFJAmmWQRhiEfLrW7cJvVnOPnaaKEpYOHSAb7\/4DZQsodPpISc2RTWikMuolQyWrm1w+XaX7T2bpz79Sa7d3GDu4DRr6ztk9pDi1jKKpeB4PrnIRo40SkpKlsRIkoSWU\/BDgdx3Y9aDlIEASTfxlDyqDKaa4XY6vHPjNmtbXSKRUSwYeEHE6dOPUG9OMXfsBGalzb27a2zu2HR6Y+bm2mxs9\/nUb1\/gM7\/\/HJ9+9ndRJI3PPf0kk9UqhqFT0CQkYNeJCaOYHU+wG8n03Rg5SASdQKEfS3hGlU5zHl\/IeLFElKkoCLp7AzqDMVeuvsvtO8tEUUShUkQ18vT39rm3tMmD\/ZhANjl8dIaPNgeceeRh\/vvVV6g1aszMz3Bw7hBLy2vMz9URukHfDdlPFLwwQM1SVro+dpQhG6ZF\/YlnodBAS2PS\/h5ZpcFYMrBzBXwBWSqI\/DEz05NcOP84qqZz9fJNth7ssrGyzP2Ox8hPKZgG\/X0bIWvcvH2H1bX7fO+Vt\/mTv\/prfvTTS2RkNOtFOj4UGm02AhU3luirVcpnP0WUgezZY7I7P0EOxty+fBVPSHyw\/IDx0Ma3PfwoJYljfvnWdf7iL\/+Bbn\/EyLY5\/dhJRCa4u9Zh6CWs7\/ncH0YISUJJE177+SX8IGJHyfEvWzZ3Vu6TySrlUgFXqKys76CYebY3d5EiG\/fGJWLXQc1GA2aylCAcMTN1nI33tymrKbuOTRxZ2GOHriazsHCQb587Q61eZjQcsdftktfh\/pbNbndMnKkI32Wz46MrMk4oCMKQ3K3XuXP3FmZkU6talAsGy6ubVCol9FEXq9imHQxpSAbOUCD7I5tkYFMTCSL00P0B+cCmKAu0JEJFQCaRSRI502BlbR2zYHJo4QDv3lljbxziRBlDJ+Lh+TrvfrgDkkKj1WRvHKJrOtmwSxzGHJlvUSvpWFmAGjrMawGha1OWBHoYgUhRA8dFSAI3TlCChDAGzwsIgwA18gltcEi5n\/hcefNXPPHEKdqtBvZoyPpWh27fxg0S4jhD1TQm2w1kVaeztUvkhcTlCpEXYdZNGrUCne4Qzw8Z2TFEKV4QE2QSuUQQiBDZd33iWBAlCb4ToJEgHAcRBARuQOT5DB2fVNU591uf4PDxeR7s9kgzwdrqFiMvwnUDEmSiDBRSXMcjzCSMU09hPnWBfKWE5\/lMTdcY7I2Qwpi88DCTBN92EJlEEidEQYQsCfHxnDKIPA9VlnEcjzTNUNOPHURxQhhHJEKwNxhy\/fptVN1kcWGWVr2CSGUemq\/xoB8hpTJCZMR+SNKeIJtfwNBVZg5OIKcZIzdAiBQ\/ziiUDNJMxlAkNEVCTlP+H4ABWPHrRyKKAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer_big.png\u0022 alt=\u0022AI-generated illustration: a wrecking ball with OVHcloud logo smashing a server with my blog\u0027s logo\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022687.1875\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022Illustration generated with ChatGPT-4o\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        Illustration generated with ChatGPT-4o\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA big chunk of my free time in the last week has been consumed by work on restoring a bunch of my projects\nafter my hosting provider, \u003Ca href=\u0022https:\/\/ovh.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E OVH\u003C\/a\u003E, completely removed my server and backups.\nHere\u0027s what happened.\u003C\/p\u003E\n\u003Ch2\u003ETL;DR\u003C\/h2\u003E\n\u003Cp\u003EThis post ended up longer than I was hoping for, so if you don\u0027t wanna read the whole thing, here\u0027s an executive summary:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EOVH has made me start a new account for each country I\u0027ve lived in; it\u0027s annoying to keep track of,\nso I\u0027m starting to clean it all up as well as to slowly move my projects a better competitor.\u003C\/li\u003E\n\u003Cli\u003EI requested removal of one of those accounts, clearly marking which one, and they did remove it\u2026\nand then removed another account too \ud83e\udd26 The one where my server and backups were located and paid for in advance.\u003C\/li\u003E\n\u003Cli\u003EIt\u0027s been over a week and support still hasn\u0027t helped me a bit.\u003C\/li\u003E\n\u003Cli\u003EMy planned move to Hetzner got expedited; and I\u0027ve decided to also make a bunch of improvements\nto my projects along the way: to update language versions, dependencies, licenses, etc., to discontinue some,\nand to make my setup more resilient, easy to restore and less reliant on a single company in the future.\nSo it\u0027s been infuriating, but with silver lining.\u003C\/li\u003E\n\u003Cli\u003EUnfortunately, I also lost some databases in the process \u2013 causing one project to be prematurely discontinued,\nand a few others to lose some less important but cool stats\u2026\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After 17 days I received a call from the claims department: they took responsibility for the incident,\napologised, confirmed that the data is not recoverable, and offered me 136,38\u20ac (six months worth of the cost of the service) \u2013\nwhich would be a reasonable compensation for the trouble, but is a laughable compensation for the unrecoverable loss of data.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Chr \/\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022#what-happened\u0022\u003EWhy would OVH do that? How did they handle the situation?\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022#my-mistakes\u0022\u003EWhat could I have done better?\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022#silver-linings\u0022\u003ESilver linings\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022#databases-lost\u0022\u003EDatabases lost\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022#receipts\u0022\u003EReceipts\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch2\u003EWhy would OVH do that? How did they handle the situation? \u003Ca id=\u0022what-happened\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003EI\u0027ve been using OVH to host my VPS and register my domains for ages now. They used to be good enough,\nbut most importantly cheaper than everyone else. Now, however, I can get better machines\nand better service for less. I was recommended a German company called \u003Ca href=\u0022https:\/\/hetzner.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Hetzner\u003C\/a\u003E\nand I\u0027ve been planning to move there, and procrastinating on that plan, since, *checks notes*, October 2022 \ud83d\ude05\u003C\/p\u003E\n\u003Cdiv class=\u0022table-responsive\u0022\u003E\u003Ctable class=\u0022table table-striped\u0022\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003ECompany\u003C\/th\u003E\n\u003Cth\u003EModel\u003C\/th\u003E\n\u003Cth\u003ECPU\u003C\/th\u003E\n\u003Cth\u003ERAM\u003C\/th\u003E\n\u003Cth\u003EDisk space\u003C\/th\u003E\n\u003Cth\u003EBandwidth\u003C\/th\u003E\n\u003Cth\u003EPrice\u003C\/th\u003E\n\u003C\/tr\u003E\n\u003C\/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EOVH\u003C\/td\u003E\n\u003Ctd\u003EVPS 2018 SSD 3\u003C\/td\u003E\n\u003Ctd\u003E2 vCores\u003C\/td\u003E\n\u003Ctd\u003E8 GB\u003C\/td\u003E\n\u003Ctd\u003E80 GB + 50 GB extension\u003C\/td\u003E\n\u003Ctd\u003EUnlimited (with fair use policy)\u003C\/td\u003E\n\u003Ctd\u003E22.73\u20ac\/month\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EHetzner\u003C\/td\u003E\n\u003Ctd\u003ECX42\u003C\/td\u003E\n\u003Ctd\u003E8 vCores\u003C\/td\u003E\n\u003Ctd\u003E16 GB\u003C\/td\u003E\n\u003Ctd\u003E160 GB\u003C\/td\u003E\n\u003Ctd\u003E20 TB\u003C\/td\u003E\n\u003Ctd\u003E19.84\u20ac\/month\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003C\/tbody\u003E\n\u003C\/table\u003E\u003C\/div\u003E\n\u003Cp\u003EI\u0027ve actually been using Hetzner for a while for a different project,\never since I moved \u003Ca href=\u0022https:\/\/pronouns.page\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Pronouns.page\u003C\/a\u003E\nto its separate setup (see: \u003Ca href=\u0022\/blog\/pronouns-page-migration\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Migrating Pronouns.page to a new server \u2013 a success story\u003C\/a\u003E) \u2013 and I can only recommend them!\u003C\/p\u003E\n\u003Cp\u003EWhich is not the case for OVH at all\u2026 While the price difference is not terrible \u2013\nI could live with this specification for that money \u2013\nthere are so many other things about OVH that kept annoying me greatly. Their dashboard is slow, buggy\nand has terrible user experience. Your account is bound to a country in which you created it,\nmeaning that me, a person who moved from Poland to Germany and then from Germany to Netherlands,\nended up with three separate accounts \u2013 and scary automated emails warning me that if my whois information\nis proved to be inaccurate they will have to take away my domains. That information\nincludes the physical address and phone number, which are bound to a country,\nso it \u003Cem\u003Ewon\u0027t let me\u003C\/em\u003E update them without making me create a brand new account.\u003C\/p\u003E\n\u003Cp\u003EOkay, then just create a new account and move the domains and servers there, how hard can that be?\nWell, hard\u2026 The procedure to move a single domain, at least at the time I did that, required separately\nchanging three contacts (iirc: administrative, billing and technical), confirming each of them via a code\nfrom the email sent to the old owner, then another email sent to the new owner.\nMultiply that by, idk like ten domains?, and you\u0027re stuck for hours with like sixty confirmation codes\nbetween two browsers, two email accounts, waiting for all emails to arrive and verifying which\nidentifier is which. Rather than just letting me say: \u201chey, btw, I live in the Netherlands now\u201d \ud83e\udd26\u200d\nThey seem to have an affinity to spamming people with long plain-text emails \u2013\nto a point one starts just glancing at them briefly and throwing them in archive without giving them too much thought.\u003C\/p\u003E\n\u003Cp\u003EAnyways\u2026 In early June 2024 the status of my accounts is:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ea Polish account that hasn\u0027t been used in like 5 years,\u003C\/li\u003E\n\u003Cli\u003Ea German account that only has a VPS, which I\u0027m planning to just move directly to Hetzner,\u003C\/li\u003E\n\u003Cli\u003Ea Dutch account that hosts a bunch of domains.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003ESo as a person who would like to finally get the ball moving on the Hetzner move I\u0027ve decided to at least\nclean up what I can: instead of three NIC\u0027s (account identifiers) in three countries connected to three email addresses,\nthree password manager entries and three OTP manager entries, I could have two of each \u2013\nand some more motivation to slowly but surely start moving everything.\nI tried looking for a \u201cremove account\u201d button, but to no avail. After a bunch of digging,\nI finally managed to find where to request the removal, via the GDPR procedure.\nAnd I did \u2013 while logged in to the Polish account, specifying the NIC of the Polish account\nin the form, and then again in the text of the request. Over the next week I got a few emails\nthat they\u0027re working on it, and I thought that was it.\u003C\/p\u003E\n\u003Cp\u003EOh how wrong I was. One day my husband let me know that \u003Ca href=\u0022https:\/\/generator.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Generator\u003C\/a\u003E\nis down \u2013 so I tried SSH-ing to the VPS; it didn\u0027t let me, so I logged in to the OVH dashboard\nto debug with their in-browser console or to just reset the server: only to see that\u2026 \u003Cem\u003Ethere is no server\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EI confirmed that the Polish account is indeed entirely gone, but the German one, while still existing,\nis completely empty, except for a history of payments and a support ticket.\nA ticket that I opened from the \u003Cem\u003EPolish\u003C\/em\u003E account, written in Polish, specifying the Polish account\u0027s NIC \u2013\nand their reply, also in Polish, that the German account is being removed.\u003C\/p\u003E\n\u003Cp\u003EI opened a new ticket bringing the situation to their attention.\nI even got over my social anxiety around phone calls and called their customer support \u2013\nafter all the sooner they react, the better the chance that the data is recoverable.\nSurprisingly, they didn\u0027t leave me on hold for ages or pass me through lengthy automated process,\nI actually got to talk to a real person within minutes. They gathered the info, they could see my tickets\nin the system, they told me they\u0027ll forward it to the appropriate department and that I should expect\nsomeone to contact me within \u003Cem\u003Ehours\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EFast forward a week (and an angry nudge in the ticketing system) \u2013 still zero reaction.\u003C\/p\u003E\n\u003Ch2\u003EWhat could I have done better? \u003Ca id=\u0022my-mistakes\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003EI think the reason why someone removed the German account along with the Polish one is that\nwhile the account I was logged into when requesting removal,\nthe NIC I put in the form, the content and the language of my message all pointed to the Polish account,\none item did not: the form asked me for an email address and I mistakenly put in\nthe one associated with the German account.\u003C\/p\u003E\n\u003Cp\u003EWhich is an easy mistake to make when you\u0027re being forced to manage three separate accounts\nthat could\u0027ve easily been one. But more importantly: they didn\u0027t check if the email address entered\nactually belongs to the person making the GDPR request (eg. by them being logged in, by the user sending\nthem an email from that account, by requiring a confirmation code by email);\nin this case both accounts happened to belong to the same person, but what if I put in \u003Cem\u003Esomeone else\u0027s\u003C\/em\u003E email?\nWould someone be able to bulldoze a competitor\u0027s entire infrastructure by simply knowing what email\nthey used for their OVH account? That\u0027s absurd!\u003C\/p\u003E\n\u003Cp\u003EAdmittedly, they \u003Cem\u003Edid\u003C\/em\u003E notify me by email that my account is being removed. Among a spam of various emails,\nin a weird mix of Polish and German text, and in which the account to be removed is referenced solely\nby a NIC: a random string of numbers that I need to either remember or check my notes each time to know which is which.\nI think they also \u003Cem\u003Etried\u003C\/em\u003E to tell me that my VPS is gonna be removed along the account,\nbut the wording is \u003Cem\u003Eabsolutely terrible\u003C\/em\u003E: \u201creferencja do us\u0142ugi na Twoim koncie wymaga niezb\u0119dnych operacji\u201d,\nwhich translates to \u201ca reference to a service in your account requires necessary operations\u201d \ud83e\udd26\nQuite a long way from what I\u0027d expect to be the best practice:\na big, bold \u201chey, your account XYZ still has a VPS that\u0027s running and paid for, are you sure?!\u201d\u003C\/p\u003E\n\u003Cp\u003EI could\u0027ve moved to Hetzner 1,5 year ago. Oh honey, I so wish I had.\nBut that\u0027s not an effort for one afternoon. There used to be 52 (!) projects hosted there along with\n5 third-party web-based apps, and a bunch of dependencies.\nSome of that was using PHP 7.4, some PHP 8.3, some Node 18, some Node 20, some were just statically generated pages.\nIf I were to move it over, I\u0027d rather upgrade to newer version instead of supporting separate ones.\nAnd I\u0027m a busy enby. I wrote earlier that I was \u201cprocrastinating\u201d on the move, but that\u0027s not really accurate \u2013\nI was \u003Cem\u003Edamn\u003C\/em\u003E busy with a bunch of other things, like \u003Ca href=\u0022https:\/\/pronouns.page\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Pronouns.page\u003C\/a\u003E\n(which luckily was on a separate server already), or idk, one of the 153 repos I seem to have on my\n\u003Ca href=\u0022https:\/\/gitlab.com\/users\/Avris\/projects\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Gitlab\u003C\/a\u003E (some of them private, so they won\u0027t show up under the link).\nSo a proper move simply hasn\u0027t been a priority. Until OVH made it my priority.\u003C\/p\u003E\n\u003Cp\u003EI could\u0027ve made the project easier to restore. Keep the configuration and a library of system packages in a repo,\nAnsible-style, or whatnot. Yeah, well, that was the plan for the Hetzner move \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003EAnd yes, I can hear hypothetical people screaming. Yes, I should\u0027ve had backups.\nWell, I did. I had a script that was supposed to zip the most important data and store them on S3,\nbut it broke and I haven\u0027t found time to debug the issue\u2026\nI gave it low prio because I was planning to abandon the server anyway,\nand more crucially because I also had separate backups of the most important thing \u2013 databases.\nOther things I can restore with some effort, but databases would just be \u003Cem\u003Elost\u003C\/em\u003E.\nThe thing is, what I used for those backups is\u2026 OVH\u0027s built-in automatic backups of MySQL databases.\nI wish I could still see any indication in the dashboard that those backups were ever there,\ncause my anxiety whispers in my ear that my memory might be misleading me \u2013\nbut I can\u0027t, because the whole account is wiped.\u003C\/p\u003E\n\u003Cp\u003EAnyways\u2026 the thing is: I know I could\u0027ve handled a bunch of things better.\n\u003Cstrong\u003EBut my biggest mistake was trusting that OVH will handle my account appropriately\u003C\/strong\u003E.\nFor heaven\u0027s sake, that server was even paid for for another month an a half \u2013\nwhy would you wipe customer\u0027s infrastructure that\u0027s paid for, actively running,\nand part of a different account than the one that made the GDPR request?\u003C\/p\u003E\n\u003Cp\u003EUntil now, I simply disliked OVH as a customer. How I actively distrust them, and I doubt that will ever change.\nI could never trust them again with any data or infrastructure.\u003C\/p\u003E\n\u003Ch2\u003ESilver linings \u003Ca id=\u0022silver-linings\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003EBut\u2026 it\u0027s not all shit. I actually managed to find a lot of silver linings in the whole situation.\nObviously, OVH forced me to finally prioritise the changes I\u0027ve been planning to do for over a year \u2013\nso I finally got most of them done, yay. I guess, thank you?\nBut other things on my list are stuff that I would\u0027ve done anyway, eventually\u2026\nStill, I like to think about the positives, so here we go.\u003C\/p\u003E\n\u003Cp\u003EI moved to a faster and cheaper machine. Yay!\u003C\/p\u003E\n\u003Cp\u003EMy IP is finally fully private and protected by Cloudflare\u0027s proxy.\nI\u0027ve had the old server way before I even knew that it\u0027s a thing \u2013 so someone somewhere\ndug it up and used it to DDoS me, circumventing Cloudflare\u0027s protection.\nIronically, they were queerphobes targeting Pronouns.page, but they didn\u0027t know\nthat this project has had its own separate server for a while now, and its IP is still secret.\nNow, so is Avris\u0027s.\u003C\/p\u003E\n\u003Cp\u003EI had a list of 57 projects\/apps\/hosts\/(sub)domains running on the old server.\nNow that list has just 25 items. The remaining ones are those that either got popular, or didn\u0027t at all\nbut I really like them and they aren\u0027t that much effort to maintain.\nI\u0027m following \u003Ca href=\u0022https:\/\/www.youtube.com\/watch?v=9LZEZ5QuyzM\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Tom Scott\u0027s advice\u003C\/a\u003E\nto create a lot of stuff and increase the odds of some of them succeeding \u2013\nbut that also means I need to be ready for a lot of what I do to fail.\nKilling a project is tough, even if no one, including myself, even uses it anymore.\nBut this whole situation made me tear off that band-aid.\u003C\/p\u003E\n\u003Cp\u003EA half-baked idea that I decided to publish way too soon? Poof.\nA framework that helped me learn a lot about PHP, software and software architecture,\nbut that also makes less sense to use than something more established? Poof.\n(Well, the repo is still public, but no need to keep the website up).\nAn app that stopped working after Elon Musk broke Twitter\u0027s API (unless I pay a bazillion euros)? Gone.\nA legacy version of a page that I kept up \u003Cem\u003Ejust in case\u003C\/em\u003E? Bye!\u003C\/p\u003E\n\u003Cp\u003EIt\u0027s not easy to say goodbye to them, but it helps with the overwhelm.\nI no longer maintain a terrifying number of apps I can\u0027t keep track of \u2013\nit\u0027s just two dozen that I actually care about.\u003C\/p\u003E\n\u003Cp\u003EThere\u0027s a bunch of things that I wanted to fix or improve in each and every one of those projects,\nbut doing that to twenty something of them is \u003Cem\u003Eway\u003C\/em\u003E more manageable than to fifty something.\nSo here we go: I upgraded Node, PHP, Symfony and a bunch of dependencies to the latest versions for all of my apps \u2013\nand to the same version across the whole server. I renamed the \u003Ccode\u003Emaster\u003C\/code\u003E branch to \u003Ccode\u003Emain\u003C\/code\u003E in those older\nprojects that still used the outdated name. I changed my name in the READMEs and footers\nto reflect my new legal name (\u003Ca href=\u0022\/blog\/it-s-official-my-name-is-andrea-vos-now\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-heartbeat\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E it\u0027s official! my name is andrea vos now \ud83e\udd73\u003C\/a\u003E) wherever it still needed an update.\nI changed the license of my projects to \u003Ca href=\u0022https:\/\/oql.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E OQL\u003C\/a\u003E wherever it was still MIT.\nI switched from Yarn to pnpm. Stuff like that.\u003C\/p\u003E\n\u003Cp\u003EWhen upgrading \u003Ca href=\u0022https:\/\/cake.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Cake\u003C\/a\u003E I also added better RTL support\nby upgrading Bootstrap and improving keyboard control logic. For \u003Ca href=\u0022https:\/\/oql.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E OQL\u003C\/a\u003E\nI made the dark mode look nicer. For \u003Ca href=\u0022https:\/\/heartbeat.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Heartbeat\u003C\/a\u003E\nI added a way to compress older data to reduce database size and refactored the config\nso that it\u0027s more readable and allows for async calls (like API calls or caching).\n\u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Deployer\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Deployer\u003C\/a\u003E got a bunch of improvements\nthat I\u0027ll release soon as v2.0.\u003C\/p\u003E\n\u003Cp\u003EThe server configuration as a whole got better too. I applied a bunch of the same improvements\nthat I had earlier made for Pronouns.page (\u003Ca href=\u0022\/blog\/pronouns-page-migration\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Migrating Pronouns.page to a new server \u2013 a success story\u003C\/a\u003E) \u2013 including\na switch from Apache to Nginx and organising configs better.\nMy notes from that move were \u003Cem\u003Esuper\u003C\/em\u003E helpful and made this one easier and faster \u2013\nbut this time I wanted to make the process even better, and turn them into a nice little repository\nof scripts and configs that can be used to really boost the process if I ever need to do it again\n(or, more likely, use it as a template for future projects).\u003C\/p\u003E\n\u003Cp\u003EAnd, of course, setting up proper backups in multiple locations (all far away from OVH)\nget a way higher priority on my list after this incident. The new setup is still in the works,\nbut it will be a great improvement.\u003C\/p\u003E\n\u003Ch2\u003EDatabases lost \u003Ca id=\u0022databases-lost\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003ELuckily, most of my projects don\u0027t really need a database \u2013 they\u0027re either landing pages for libraries,\nor tools that encode data in the URL, or something like that. Restoring them was just a matter of\nspending time and effort on configuring everything again. But for those that do need to store data\ngenerated by users, the loss is unfortunately bigger\u2026\u003C\/p\u003E\n\u003Cp\u003EThe biggest by far was \u003Ca href=\u0022\/blog\/redesigning-a-website-naked-adventure\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E naked-adventure.eu\u003C\/a\u003E \u2013\na website that crowdsources information on nudist beaches and establishments.\nOn one hand, so much of mine and other people\u0027s work suddenly got wiped from OVH\u0027s infrastructure,\nbut on another I\u0027m actually a bit relieved\u2026 It\u0027s the kind of page that makes the most sense on a big scale \u2013\nafter all, just under 200 places in our database is almost nothing on the global scale;\nwhat\u0027s the point of even visiting the page if you\u0027re statistically unlikely to find what you\u0027re looking for?\nAnd for me personally, over the years naturism stopped being a new exciting thing that I love,\nand became just a regular part of my life. The enthusiasm and motivation to run this page faded,\nwhile overwhelm from other projects and other aspects of my life grew. I was falling behind on moderation,\nnever gotten to implementing some features I planned for it, I didn\u0027t have ideas or resources\nto advertise the platform and to grow it\u2026 So while it\u0027s sad to see it go, the project had been on life support\nfor a while already. I might resurrect it one day, with some new twist, but for now, rest in peace.\u003C\/p\u003E\n\u003Cp\u003EI also had some pages that collected stats about people\u0027s responses in a quiz,\nlike \u003Ca href=\u0022https:\/\/corevalues.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E CoreValues\u003C\/a\u003E. The pages are back up, but the stats are gone.\u003C\/p\u003E\n\u003Cp\u003EMy husband\u0027s blog got wiped too \u2013 but he has local copies of all texts,\nand he hasn\u0027t published there in a while anyway, so not that much harm.\u003C\/p\u003E\n\u003Cp\u003EI also lost website analytics from \u003Ca href=\u0022https:\/\/plausible.io\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Plausible\u003C\/a\u003E.\nBut to be honest, I haven\u0027t really checked them in a while \u2013 I just let my websites run,\nwithout obsessing about the numbers. I still set up a new instance on the new server\nand I\u0027ll be collecting anonymised analytics, but I won\u0027t cry about that particular spilled milk.\u003C\/p\u003E\n\u003Ch2\u003EMental health impact \u003Ca id=\u0022mental-health\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003ESpeaking of crying, though\u2026 I just wanna take a moment to acknowledge the impact that the whole situation\nhas had on my mental health.\u003C\/p\u003E\n\u003Cp\u003EI\u0027m really proud of how I mostly handled the issue. I kept calm, focused on solutions, on positives,\non opportunities. I managed to focus on fixing one thing at a time, to prioritise not only some projects\nagainst others, but also the whole fix against my personal needs \u2013 all of which are stuff that I\u0027ve\nbeen struggling with. I gave myself time to deal with the situation \u003Cem\u003Eproperly\u003C\/em\u003E, as opposed to panicking\nand frantically trying to fix everything with a hammer and a scotch tape, as fast as I can \u2013\nwhich would\u0027ve been my response a few years, if not months, ago.\nThere was no need to rush \u003Cem\u003Ethat much\u003C\/em\u003E: no one got angry with me, I just got a few messages from friends\nand strangers asking if I know that this or that tool is down; I lost some traffic, but it\u0027s not like\nI was monetising it anyway; none of those projects was an essential, irreplaceable, urgently needed\npart of anyone\u0027s live (I hope).\u003C\/p\u003E\n\u003Cp\u003EBut there are limits to what my head can take. While calm on the outside, I was \u003Cem\u003Eextremely\u003C\/em\u003E irritable\nfor the first two days or so, any minor inconvenience could get me over the edge.\nI had two major breakdowns \u2013 but luckily also two amazing partners that helped me through them.\u003C\/p\u003E\n\u003Cp\u003EBasically: I needed time to grieve. I lost a lot of data, a lot of work, my plans for the upcoming week\ngot turned upside-down. One can\u0027t just brush off stuff like this.\u003C\/p\u003E\n\u003Cp\u003EAnyways\u2026 I\u0027m fine now. But I think sharing my experience might help someone one day, so I wanted to it.\u003C\/p\u003E\n\u003Ch2\u003EReceipts \u003Ca id=\u0022receipts\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003EContext: pa13\u25a0\u25a0\u25a0\u25a0 = Polish account; pa60\u25a0\u25a0\u25a0\u25a0 = German account\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-1-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022947.24637681159\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAjCAYAAAD8BaggAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFsElEQVRYhc2YyXIcxxVFTw5V1TX0gEaDgoKkVhJDnr7AS3vthXb+M+8c4Z1\/Qd75Jxx2OMJSBAXShABUD+gacnheVKOJZoBTCKB8V92V2S9vvXdf5s1WIiIxClor7oJzHm00Rus7x+8bFuBPf\/4bv\/7FU\/7z\/Sva3tF1nuN5xcnxhIvLNecXK6pyxB+\/+S15nj4oISUicn3dEULEWoMPAa0USilEZJikFTEK1mhCiDgXSDOLMZoYImE3hgLnAtZoREAp8D6i9C5eFIoixZi3Z9vefIgihBjRWiNRcN6jlCJJDH3nMUbjJSIISim0UngXht\/GiAe0GsruQ0REMFqj9DC364cYMcZ3ElIiIl0f+e+lQ4DEKpwbMqO1IrGK0+Pkp1big6FkV5emiyjAR8EaRYgQgxAFppX5ZIQswF\/++ne01jxaTHjx8oovniz4\/vk5Rmumk4Jt0\/Orr5\/wm19+8eCElIiIcx4fItaYfY1DiABorQlxELx9R+3vCxbA+ch3350D8NWXp8Pi1nBVX9O1DucjWg\/ktFbEIPgQ+Pz0CGtfk\/zHP88AODkes1iMAeg6zw9nl4xGCcfzMVlm3+RwgL2G7sJq1bBcbVFKkaUW74fuQUGMQj5KOT6ufmJODmEB+t5zve1AYDYr2XUvo1ECqkBrPTwTKIoUpe7e1V+dr8hHydD2UZjPK3yIbLcdEgURMEahtaYss7cT0jvNvJmr18kTYhj2m\/fBuUDvAmZ3FIVvvyVcrYhxF0tB9B755g+o8fjtGXrxsmZ+9Do7MOyyy+WWcZUzmxXvJVPXW1Dw7MvT\/TP1u9\/TXKz35Z6Mczrnmd5BBt6joY\/Fv\/79kqbpGY0SFPDsq88\/Osa9EroPWIDLesPZyyuCjzRtj9YaEHoXyLMEYzRfP3vMKHv4I8QCzGfVoPw8Y9t0hBjJ0teLhxBJ03fvH\/cFJSISBPqfuXACFHqXIWHwLs+fXxCjUJYZzgVCGI4R7wNZmnDyaPJwhG52BRERL+AfbKkPQ5RbGbrBi7MzlFKD4fKeGAKPPvuMru9Z1jVZltF1HfP5nLquSdMUQUhsgjaGzXqNMQZjDFmW0TQNMUaUUozyHNf3xJ0JNNZwvbkmTVMmkwlFNexLB8e3sZaua\/Hek+c5ZVVRL2tEhCSxQyCj6bpu9yxBK03btshuYdf3JGnKarVCRAjeM53N8N4NLtIM3qprO6y1lGVJdWuTPCCkAGuT\/Vs2TUMMg3HTu0BaG\/q+Zzqd4pyjbVvKsqRt26FTq4pRlqEUw4JVRX11RWITxuMxq9WSsqrIRiOePH3KdDY7KN2Bhn54\/hylFGmasjg5uR9xfCBuNHRAKMaAUnqvo5tTXUQG8y+yv43cHgMObym7sZsYb8a7Pffm+52ivry4pGm2JEmK9x6tNVVVsd1uCSGglGKzWfP48ROapsEmCdebDc45xuMxxho26w1JkrDdbinLkhAC3nu8d4xGOd57sizjx\/NzjuZz+r5jcXJCXgy+6oCQ956+7+m7ntnREU2z5fz81eCTjo72c0KMhBjwbaBtW4qioK5rxuMxWZbhnBuuPl3HZDJhuVwCivFkgut7vPeUVcVisSBJ033J4A1R33SOwJABm2BtQlGVeO\/3XfPj+Su6pqVrG6qq2t3lIjZJqOsarTVFVVKUJVdXVygFxhiWdY2xhrZtSZJk33G3cZChGCMxCqPRiLKq2KzXWGtBoG0beuc4PT0lG41Y79q66zoWi8WgEYZMDpY3xTnHZDIhz3PatiXPc0IMTGcz+q6j7TqK4tBnHYh6vV6DCNumIUtTtDF457DWst1uyYuCqqrufLO3YbnckmUJIoKIYK1Ba0XX+Z0ZVBRFeneXPQTOzq5IEoPrPQIsFmNEhMvLa7LMYq1hOi0+HaG74Jxns+mYTPL9Pf9nJXQXbgh9mn+hPgL7LvP\/BwYN4H\/hkzMV8VfChwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-1-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022947.24637681159\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-1-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221132.1544209215\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAkCAYAAACe0YppAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEGUlEQVRYhb2XzXITRxSFv+7p6e4ZyZY0ZRdmQVXINqRSqWzgWdjyPjwA23jHG3ifwJZVKouASQVKxsayZTSj6b8sRkwsl0OqiOyz09XtPn1O\/9w7wseU6sStwghQAErAn2+PKQcG5wJCCISAECLDoWVrq9g4ufAxJbfxab+MjJVigPfv\/kJrQ9M0aKPZ3dkFIW6MvFfsvSfLsi64Ikyp2\/wQAlmWIYToY9flSClX29TlCeDz8RGXRKwpfnt4iHcOWxR9YvAeledkWcZisUBrjXcOmWUIwIeAMaYnBpBCUDcN4\/GY2WxGSgmtNd\/cv7+muCdul0tSSuzs7CCkRClFSommrsmUoigLiqKkqWuklKTV4owxeOe630CIgRECnedoY0gpUVj771b3K17ZdZNYs\/poOsVYS1PXKNWFtTEsmwatNc45vPcopRBSorVmuVySYiTPc2JKpBgJIWCshZRomgZjDM45jDWMx5OevCeOMTI\/P2c0GlHXNc45QgwY3Q0EmFQVRbGZO712qqWUXfCK1SlFhJDEGPv\/LueklLp9X53wtFIvVvN9FpZiJNd63epPFxeddatJc6Vo27a3NXhPTJEYIgBlWXJxcUGmMkhgC8vi04KzswWj0TaLxYIYA1U15vR0jjEapSR7d++sK94Ujo7OyHNFjBGtFVrnHE1njMYDtFZYm5PdBPFVxBBZtp6i0H3sVoivQ7\/H4ZbLYiZAhJiSFHB8MsdajRSCstT\/Pfp\/ICboz3thNbnKEPJLQzaH\/jrN56cURcFsNqMoCh4\/fryW+PTpUx48eLAx4t5q6C65lJK2bTk4OFhLfPToEVVVbYQ0pkuKj4+PEULQNA2DwYCDgwOeP3+OUoo3b95shPAyesVXC\/zJyQkvXrzg4cOHVFW10Yq1png6nZLnOdZa3MuX\/HFxwc\/7+1RVxXfDIdvff78xYrikeDqdMhwOEZnh3bFHfvyInX3AKmDvDtW3exsjjekS8XK5XPVVEue7RyXPBDEmskyQqxu0uixLpJRYa5mfn2NM13XmeY5zjvzDB\/zuLuH0FLu9jVOK\/OSEX1+\/5smTJ+zv7\/PTvXvUW1sIIfDeY60lyzLatkVrzWTSNQP9c6G1xnsPwHw+J6XU910pJSaTCUtjcK9eUThHu5oMKflBKX559owfV+Uzy7KesGkaYozEGHtSuGT14eEhVVVxdnbGcDgkpURd18QY+66jrmu01uR5jjGGsiy\/2uqeeD6fo7WmbVvKsuzU0DV\/zjmUUthrusWvJe6t9t4TQui7zRgjy+Wyj0u52Uf8n766bdna2urtGwwGGyW6irW3ehP47ff3DEpDCIGi0EzGAz4cz5GyK7ej7XJ9j28KddNyevqJu3uT\/hvwVoivw9rhum0oIboV3CaEgL8B9WkqGjRBM8oAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-1-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221132.1544209215\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-2-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221120.7766990291\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAkCAYAAACe0YppAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEf0lEQVRYhc2Xy24VRxCGv+ruuZ2bL8GIgOQQkV0SsWSfTV6FV+IV2GcDyoZ1FLFPFEXBNsYxNrbPZaZ7uiuLOWewIUQksk3+zZnumTp\/VfVfXd2iqnr4pmWFpIqzwvrIYoxwVTAARS6kpOSZUGQGZ7hSUgAH8OTHn\/hsc8x0VuN9i7OGPHdMZzUiwv1vvuCrL29dKrGoqi4WHh9aUlJEhEGVL59B6aI3IrQxYYwgCCIAgqqi2tkBvV03VrLMfTjiECIpKmIETcps3pCSYkSWa25IqqSkZM6iqgCogpjuj2JUrBEUUFVim8gyy9ra3xOLqmpolV93aoalpfYJYyAl2BhbtjayS0zwO8R1E7DGYG3nft0EyiJjNm8YDoorEZoD+OHJzwBs3ZiwWHjaNuJDpCgc1hi+\/+7+pRN3EdeBs2nNoMoZDgsAFnXA+xZrO4U1vkVEcNYQU2I4KMhzx+ujKarK+toQ5wwpKW9OZjhrmUyqf454pUhj36bUGiHPLCynBjZHVXFLcTlnOxsjiBiMkaW6WX4DMSUEEDHLKniHuG0ji4XHGqEqcwC8b5nOGqztjMajkqLI3\/P85GSBqnJ8PGPrxpjBoMA3LUmVELosbW4M6SM4T5xSoq4DW1vj\/sWqHvPcsjYZfHitBIoi4\/Nb671dCBFFcdb25faena6K8j\/ijxevmc8bssxy8+Ya41H5UXZdHYeItQZV7UvqquEAzqYLfvltnzx3OGc5my4ocsf+qzd8+\/U223duXDqxqKom6Dbl64IsI0bhirvgBSRd9uNPAQddltM1pjqm2K2xDy1GpN+NAEIbyc6NLxsOYDZr+P3Fn6Cdwq0zGBEyZ1lfH1766QP+D6oOPvDy1QkbawOcs32XugokXUX8CcqpPxA1TcPe3h6bm5s0TQNAjJGyLBERvPcURcFsNiPPc\/I8Zz6f45xDRBDp2qL3HmstIkIIgfF4TNM0NE3DZDJhPO4aUR9xii2np6c45\/DeMxqNCCGwWCxwzhFCIMbIYDCgbVustRhjiDHSNA3j8ZjRaPTvIxYRYoyoKovFgqZpqKoKYwzGdA2kqiq89zjn2NnZ4dGjRzx8+JDt7W0Ajo+PaduWsiyZz+cURUFd16SUyLKMqqp65\/qda+W5tZbhcEhZlnjvUdXecBV1jJGiKHjw4AFbW1t475lOuyNQjJG6rvtfEaGqKpqm4UIHVlWNSTXGqLu7u3p0dKT7+\/t6cHCgz54909u3b+vTp0\/18PBQLwsxqfZrLO8U8kosz58\/ZzKZcO\/evZWj524NqX9efS8i\/fzq3Wq+f39+jWOMHBwc0LYtWZYhIszncx4\/fszdu3epqooQAmVZYq29kLbT01OKorhA5pyjrutehOvr670Ixdi3qm6DZ3d3lxgjw+GQlBLWWpxzZFlGnueklFBVQgj9OKWEMaZ3KoTQk3nvGQwGfZWcV\/WFVLdt25dKdwyyfU1+LPZeHnd3saQ4Z7hzZ5P9\/ZP+ULi5MbyenUsVDl+fsTapyHP3fsTXvmWq6vJqeX3ECvwFAYX\/aXBmKyMAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-2-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221120.7766990291\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-2-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221094.0648379052\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAkCAYAAABxE+FXAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAECElEQVRYheWWTY4TORiGH9vl+u+QdE8iEEgcgRXbFkeBO3AKNhyFK3ADlkgshwGmJ6TT6dRPKmX7mwWkIAJmekadZqTxxhVVOY\/9vq\/tT4mIbAMoxY02BUQADmiqDVorQhCUUhijEAEJQl4k1w7XO\/huJs55jDGICM4JrvcofThJBnjX1Vhr6bqW4APGGMaTCeqAfigRkSZA8D1Kabx3KKVRSqG1Rmt9EPCe7B\/nH0nTlO12SxRFOOeIogilFN57vPdkWUbbtogI1lpCCPgQKPKc9XqN1posyxAReudABO89cZJwuVqR5znT2WxQc1h5dbmi6zqms9lBVvq9lQ\/wA+bqh\/BB9vPFgqapKcqStmk5OjoCpWjqGhNFtE3D8ckxRVFeGSDyqf9RZq995W275be3C\/Iioe8dRZFSlinn5xVKQZ4njMfFzcne947Lyw3jcY4xn3bPT\/f8MJv4ii0CMD9hFsPFYhWcnV0AYK1hMi4Gbw7Vgnz2PMjNex7kv+A5wHK5JI5jQgiICCEERqPRwS6WPfjz589ZLpc45zDGEELgyZMnPHz48PDw09NTNpvN3ss7d+4cDAxfBe6Ps9\/x3hNFEVproiiibVtCCGitmU6nWGuv\/Md93\/Pu3Ttu375NmqbfvN9L+6ZtWCwWjEYj2rZFa00cx1RVBYAxBmst3nuUUlhrUUrRdR1935Om6XDvW2t5\/fo1jx494sWLF5yentK2LaPRiLIsv4UvPs4Hv0WELMuo65okSdhut2RZRlVVHB0dsVqtEBHu3r2LMeZfSb4HD\/4TeCc9QAgBpRQi8qX6UIoQAiGE4TsRQUS+2Rny+U7d9buxxhiCfBW4i4sL5vM59+7do65rQgjUdU1RFLRty2QyYb1eE8cxWmucc8PkXr58yatXr3j69ClKKVarFbdu3SKEQJ7nbDYbkiRBRCiKYlBrgCdJwv3794cBWmuSJCFNUyaTCc45iqIgjmP6vqcsS5RS1HVNXde8efOGJEmIoghrLVpryrL8y5AOsneblvPzc7IsG4rFqqooy5L5fM50Oh3Cch1tz3OFDN5+3e+e\/+6kExHW6zVpmhLH8ZXge57vDpmyLPHes9lsiON4z\/skSQgh0HUdeZ7T9z1RFPH+\/XsePHjAs2fPePz4MUopnHNDNk5OTmiaBucc0+kUbaIvcADvPXme07btsHd3g9M0xRjDer0efjvn6LqOKIqYTCZ8+PABrTXWWpqmGSxUStE0Dd57ZrPZkPZB9vkfZyRJQlVVwyBjDFVVobWmKApCCPR9T5ZlNE3D8fHxd0+vf+z5dVavv75dUBQJ262jLFNGRxnLi5oQhDyPmYyLmysmtlvH8qJm+ssI\/Rn0P69kQgh4EfwNgxXwJyb5fOkYtNnCAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-2-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221094.0648379052\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-bill-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022607.82122905028\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAWCAYAAACosj4+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEE0lEQVRIic2WS28cRRSFv3r0c9zzsB3Hj0ASgRUQRFmwi4AFOzYs+Q2wYMcPYo\/Chn\/BIgIJFglYRnbs+BnH44ynH1V1WfTgxChODNFInE13q7punTr33lOlRET4H8EC\/PbHLkfHY7wPRLHFOw+AiGCsYTg85WBvix\/vfQfA5198yTurH2KtoXEeBIIIIsLy4iwAeWqREBARQhCM0ZP3gPOBJI6II4ONbEvEKAZF2hJKkgjvnmEjg3eOEFrRjNFICHTyhKrIWVpaahfLMhAhsgZrNGXVkFiDD4IxClBorVnf3GNv75gksRQzOUECw+GYTidhOBwzP1eQpjG9bk6exc8JLfQzfFUBgghordBKtQo0jiiyrFzpcPvWt1hrKMuaoshYXhyck7tpHPuHJ4xOS4p+jyyNWbjSQ2uFiJDYmKbxyESx0ajEGI01GmP085TlWcT1a3MoxZm8WqvX5ts5d+5bKZjt5wx6OVq3C\/gQ0NoQguBcII4sUWRaIpFh0J+h00mxLxIandZs7xzR62Y8G5XMz3Xpd\/NLFeGLEIHHu4eEICxc6WGMppMnaK3xPtA0jl43J4igtUYpyNL4XAwLcHQ05OnTIY93D0liy8bm3tkujNH0uzl\/bh6QZzEf3bl5IaHtnSP2D0+IrCFLI5auDi789yIoEZFHW0PG4wYA50PL1Giq2pHE9h8zXpVKgYmJZFnE4ckJ3gUEqKqGNI2o67ZpjNZoo3hrZf5svfl+1hL619u4BIIIvz54zLiscc6TpTHjsj57KqUmm1UkiWVxoc98P8O+NvIbQOu2UxVQVg3WGpzzzM0W9Hudl86ZMqG2mL0PbU1qzfLS7CvnTC1lAD5cPrSiVVSJiPx0f41no5LPPvlgWtwuT0xEZH37mNPSvf7vKWDz0T6jUcmd2zd491q\/rSEf5KzdX8TO7hFPjk4QEW6tXsNac2Hgsqz5fW0baw15lnD97QUAqrrh4cMtBLh54yobm\/t4H0iTiMXFAeOyofEB79v0KhGR3SenlPV0FFKcWdNLx9bWdwgh8N7qCisLxUShqiZUDd4HlGqPgDxPCCFQ1475uQJtFM4FOnlMFJ1vzqbxVFXDvR++Z293h6++\/gZrDVHU3ga8D23BKkVZNtS1I4oMWRYzWyR458nzBJi0vVLtVUOp1tCqsoGfH+D291leHKDX2mA0Dj+TE3189xwhH1o3tsZgTOs7EoS\/PV0phUi7jlKgjUZPDlOlaL1qcgIoEZHxeIz3\/o3T8zJUVUOSRBeOl1VDCEISR\/R6xXSNEWBj6xCR9q5krWHQ77Aw3wXA+8DG5gE+CEuLfXq9olXo\/i\/rjE5LhPY+NDqtyNKYfjfnZDTmeDimmElJk4iDJyf0ipxP774\/lQ1M1an\/C\/4Cuc7m3cDGDWgAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-bill-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022607.82122905028\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-bill-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022662.62325581395\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADHklEQVRIic2XW08dVRiGn3Ua9okN5aSFTayx1Zio1fTCSzXxR\/ALuPBK\/4Ym\/iK5IzFNmhhJTLxoq4VggQ2EvWEPe2YdPi+GUkmRaruBvjdzMe9a88y33rXmGyUiUvqICNcqpSGzBgvwZKtPPgyUZcBaQwjVVWt94STDYYm1BmM0SqlzPTEmUkpYa4gxEVPC6MpvjObxn1uUZeDe3Xe53ZmsgJ6p9IGNzS7BRzqdGZqN2oVAG5u7AEgS3r+zcK4nhMiT9R2Ghef2ezf56+k+3gfGMsfc3CTr6ztY9xxDiYh09wf4WJGXZcA5gw+RzFmsNcDrrKe6YLyiKEp8iEy2G0y0xqoKDQ5zAGISyiJQV5HG3g4uM9y4dxf+ZTlGo7OroFK3K93dQ8rxCVISUhJijNRqjqlwTK2eoWZnLxHorJSkJBs\/rZK0qXaagjwvaDVrKKNZ\/OJztrZ73L\/\/M999+w3f\/\/AjX335NT5EyjKQOYNQhdc5S4wRhcJYjYjw1tzEaZABvI+nITemioiI4JxFa1Vl6GXUIsLBwQFra2usrq6ysrLygkdrTUqJpaUllpeXz9zzIWKNQSkY5AVlGaiNOer1jINeTkrCRLte7db\/AnSVuviguQZZAO89110opRTOuedAMcZLedCvv63TqGUkEUSE2ek201MtoDo0f3\/4FEnCYmeGxYW5KkNvQoW01lhr37xQW4AHvzzCZZY8L9BaoxRkzjI702bh5tSVAikRkbIMCIJCEWLCaEUSwftAe7xx9UAAG5t7bHd7iAiffnwLZ825A3r9nJ3dPv1+zgd35mk1L+4IXgkoxvhaobbWvtz0f4BGNtsINLpXO9HDP7Y4PBqSOYsxml5\/QLNR46MPF8\/4trs99vaPKArPZ5\/cuhygEAKt5hit5hjOGoaF553ONM5VbfE\/1WpkhFBDUSOEcNLSmtECiQghRI4GQ8ZbdYrCn\/TnL34yfYjkxwXOGlISnrXvIwUaDofs7vXI84J8cMzhYEivf8RBL6czP8XbcxOn3u5uj+5eH0nC9I1GVZ1Rn9SPHu+\/8u9UvW5ZmG\/zN3CfpuNvk\/HsAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-bill-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022662.62325581395\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-emails-pl_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221053.7322834646\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAkCAYAAADo6zjiAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGx0lEQVRYhcWY3W+cRxXGfzPvvO+76\/VGtvFHEpPGVupG0EskxFVVQAhVgqriEhB\/I+K+vapEoL2oipSiJiiCWCbxJrv2et\/P+eJidmbtBKlJUMTcrXdn5plznvOc51jcvXvk+T8t5xwKYGdnhyzLsNYymUzeymUC+EHXs28MAH8dDphBADCZTNjY2MBaS1mWFEWB1hopJXVdv\/GlWZbhnAPgtjasq4wv1kdI4LCqmaksAADYv7lDnuc8\/Mdj7r73Dnkxpqoajo8fI6Wkbdt0qDEmRawoSqw1aK1pmiZdLqVkfX0dAGMME+CZEGEfcF9IaJsVgF5bzs\/nzGYzzs43sLai63pGoxHOecqyTACUUvR9D4Q8CiEugbFkmcQ5h7UWIQRKqSUQi\/ceax1ah\/0iknB7exspJd779EopM7x3KJWjtSbPc5yzGGMoywFChNeFzyV936e9RVFgjFmep7A2\/K3rOrz3TKfTFQkB5vN5Qq2UwhiDEALv306RCCEAVgDu3r1DnuccHz\/l+\/vblIMxi0XNw4cPEEJijE4v8t4jpUzhl1JirU0Hx++3traw1qK1BgRKZRRFgfee+fyCpqlXAIzuqRZzvv32Adf3xlxMWrSx7O3t4T1Ya1hfH5NlkqZpUErhnKOum2WeM5TK6fuOwWBI33copTg\/P6eua4QQGBOIGtKkr3Jgf3+fPM\/R2uCcTSUUStJgrUEISZ7neO\/pupayLJEyo+87pJRIKRFC0Pc9eZ5jjEVKgRCCPC9o22Z5h+bp06cYY1YRODk5eSu5\/q6lnPNIKXj\/\/R8CnrOzCzY2xmRZTlUFDrzJklKysbGBcw5jDC9zYB5SCR4QGF3RNDWff\/4lv\/7VB3Rd+OHh4SFCSLTuKYpyGf6OPA9aIKWkLEtmsxmbm5torXHO0fdBQ+bzOVtb30PrHmsteZ5zenq6JCaIo6M7XkrJ7du3lyUnAI9zLolOKE+HECRCKqXI85yu68iyDCEkfd9TFHmqCufcslpClOPnyWRCVVVXdeD4+DgJUSh9n0oq1izwkja8ila8eEbcB5d04OjoPay11HXN2toag8GApmnemANCCDY3NxMHol6UZfkiB+KGhtl0whdf3uc3n3xI0zq89xwcHCBlRl1XCCEYDAZobei6DqUyrHUMBiVN0zAcDjHGAp66rplOp\/8VXJZlKWqJAzdv3kzhNMaQ5wXO2ZRPISQxLdY6lMoAkfhgrcM5y2AwSGqptcZ7lmcYFovFsiKg7\/urHDg\/P095CY1IpsujwMR8xn6xIlmQZOcci8UiAcjz4hIZgyAFwgqMMVcB3Lr1DlIGzRdCUBTl\/8yB4XCIlOGyEiiFxIxGeO+50XbUl5WwaWqKoqDve\/peI2WFlILRaMT16zeSjAYNyBOxbjQN6yrnwhhulSV\/On6MlRLgCgeM93w8v2CahWiOneezslgBmM1my7w7vA8EPHp3l3+fXHDv3iM++fgD7v\/96dJ4FLRty9raGq3WjLTmVplRl5pH\/\/wXv\/jlTzAmo6od4JceAP64tUVd13RdByzNTCTh5uYWQoQ\/xpcWRUnbNgwGA6QMQhNzL4RIJiW24tjApJRLAnqUype\/D98DtG1LXdeBSzECe3t7OGfTobGrbW9v8\/z5M05PT1+bA1EHQicNFVYUBWtraxhjXtaBuprz6Wd\/4Xe\/\/Yjn0x6tg4gopTg4OKCqKobDYbJdT548SZr+4oq26zuBxhSMx+OlkBj6vufdOzt8\/bcHPHz4mD\/8\/iO++vqYoihTmmKviPIdeRRt+KusKxzY3d2NmIBQ67GGo7gASQO891csWTSzWocyjsJljMW5sCfySAjBfD6\/akgu225rHU1Tc3Z2BgTD+rpLCMF4PE5GNwKLjioa3wRgZ2dMXdX8+d5X\/PxnP6ZpBwyHw6XPz5L1yvMcIFXEYlExGq2R53lqs3FFLxjTEisHeNkP7O7u0LUtxjqGgwKPRIig4RGx1jqVWpgRViUnpQQEQpC0ImiKT2W6svuSqlrQti0yotXaImQWXu3EMsdhYwxbfEkUrNhqYz\/IMpnS2Pd9Glpi\/ceHgE8RSCkAn5qOlEEDFovFa+W9KIoU6njh5RlCSplacZwtE4DDg5ssqopvvnnETz\/8EaeTBc+eTdPG0KhMYnec+\/q+ZzgcIoTEOUvXdSnv8bLY4lfgVu5o1Y7nFfP5nOGw5ORkQtuF8oshVkrRNEGWIyggpSHLFFqHITaO+ZcHV6VUerX3oLW8CmA2C7PhtWvXeD6tEILkB5RSdF2HMWZZFQrn7Evsjrle\/V9AJCW9PClHs3IFwKvI5ttY\/wH9NvCU\/VtUWAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-emails-pl_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221053.7322834646\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-emails-de_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221539.336492891\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAkCAYAAACNBsqdAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFhUlEQVRIiY2WS28cxxWFv3r1YzjDlygqCANZAhyIthLbkAFBWcjJT0+QB7yRY8MbIxsbcWSImiHZHHKmu7q7qrKormIYGKBrM9XdmFvnnnvuuSVevXoZHhweoLRCIIFACNB1HW3bgiAvgZieBUKAEGLai2kPQkq8c2iEZHdvHyUl3ge6rsOHQEAglb6NSuDuEoQAQkAIYXoOFFox9ANaCsEP3\/+AcyNt23HfSuHFz30LgRACOztztNKai\/MV3nu89\/cG\/iWr7Vo0AebzOUVR0DQNQgi89wzDcG+AxGvaSykJITCOIxrAWsunn3zIn\/\/ynj\/98SXvzq64uLjIqUH8k7UdWmu892it0dpgjMZaS9M0GGPw3mNtj3j9+nVYrxv29vYA8qneB7RWOOfQ2tD3PVJG1QAYYxhHRwh+Ojyu1WoFiIg4ycU5B0Df9zRNcy8VWuuMMoSAMYaiKOj7IQYex5GjBzP+\/o9\/8sUXLzk\/32CMmfhySCmmbBTWdjmYUoqyrOi6Fq11pg+4S4VSCuc8QsA4OsqyYBwdEBBC4pzDGJ0VpJQCyAUTQkzBiYiVUhOKQFVVbLdbzs9X91KRUk9UlGVJWZZ0nY2Bh77n4dEOf\/3bG\/7w6jNgxsnJCSGEnEFCmOoRvzm891xfXxNC7NpERSyelPz7xxWPHz\/m7U8XeB+mIOCcQ0qFczHVSJcjhKgg7x2z2YxxHIHoMTmwUprZrGa77djdnXNzs2G5XP4iKsqyZBx6Otszn++glGIYpgbp+47j4z2+\/PJ7Tn79HBDMZjVHD3b4+pt\/8fvffcj6emAYhjtOBgLvHUdHu7x58y0H+w\/58T\/vb1VxeXlOXdc45+60Zjx0oCiivNL79BtCyHxHOUratsU5j7bWUlUVe3v7rNdrHj16RNd1rFbLXBxrozklH0mok9Yj51EVxhics+j1+oq6rthuN2w2G25ubgjBTy0eDX0YBsqyZBiGjDZyOWCtzVr23k\/FE4njHq01VVVyfX2N9+7\/FBCw1ubGSMG11vmw6COxzcfRIQHquuLTT04ZBseLF895+vQpdV0jpcQYQ13XKKWpqgopJWVZUtc1VVVxeHjI\/v4B8\/mC3d1djDGRttPTZ6EoDLu7c9rWsljs0PdjLoaUMqOOuvXE+RHbHMLEu0QpydXV1a3cvA9st1HY6\/VNLlqqeKp+WqmIiZL0TSmdp5COVNQcHOzz9u1PPH\/+McMwsFwuJw+AEGIQpRTWWoqiyJ1XVamo0fm22xBVATAMPV1nOTw84OzsbKJB3fHahK4oSozRjOM4SSvS1DSXxFhDQpzS9ZP3esZx5Orq6t6W1lpn6xQhILWeauIj4phGz7t37\/joo1Oc8xltupR47zj2HhUCfQicT9MjIf5tP2AvLpDB821VR1VUVclischaFCK6lpQK7x1FUdL3lv0QENbijGE9WWg6VEqJEILVanWLWAhBVVWZy77v6fuBpnl\/J\/W7T2BMkX0EoCiK3NLi9PRZqOsKrQ1nZ2c8efIEpST\/e3lJBu+cZxh6yrJktVplKabRlJaU6rZBdnail3ofC5m0mXQaDV9O6kj3tZAbKM287G4JUbLNui7p+x5rOy4vL39WDYvFgkRhssxoVBVaa5zrkyokbduxXC754IPHVFVJWRbM5\/PJn1VGPY7R6dKEScbUdV0eS5kKrVU2GCBfXOR0tZXyloqIkomm27ZOGSQqZKrmb04eEQKcnPyKvb19us7Sti1d17LZbLDWst1u6bqO7XZD226nOwfUtcHajtmsyO6mIU7WQKBpGo4f7hNC4Pj4IYeHFV999R2fv\/g4z7x0IUzSdM6xmNc0zQ1aq2z84tnps2D0bfGkVFOJohrGcUQpdWe+3bVPpndxb61lHB3\/BQoNukgKlpIqAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-emails-de_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221539.336492891\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["ovh","vps","customer support","configuration","gdpr","backup","devops","mental health","breakdown"],"hasMore":true,"image":"https:\/\/avris.it\/image\/ovh-bulldozer_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer_mini.png\u0022 alt=\u0022AI-generated illustration: a wrecking ball with OVHcloud logo smashing a server with my blog\u0027s logo\u0022 width=\u0022240\u0022 height=\u0022171.796875\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA big chunk of my free time in the last week has been consumed by work on restoring a bunch of my projects\nafter my hosting provider, \u003Ca href=\u0022https:\/\/ovh.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E OVH\u003C\/a\u003E, completely removed my server and backups.\nHere\u0027s what happened.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer_mini.png\u0022 alt=\u0022AI-generated illustration: a wrecking ball with OVHcloud logo smashing a server with my blog\u0027s logo\u0022 width=\u0022240\u0022 height=\u0022171.796875\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022Illustration generated with ChatGPT-4o\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003EIllustration generated with ChatGPT-4o\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA big chunk of my free time in the last week has been consumed by work on restoring a bunch of my projects\nafter my hosting provider, \u003Ca href=\u0022https:\/\/ovh.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E OVH\u003C\/a\u003E, completely removed my server and backups.\nHere\u0027s what happened.\u003C\/p\u003E\n\u003Ch2\u003ETL;DR\u003C\/h2\u003E\n\u003Cp\u003EThis post ended up longer than I was hoping for, so if you don\u0027t wanna read the whole thing, here\u0027s an executive summary:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EOVH has made me start a new account for each country I\u0027ve lived in; it\u0027s annoying to keep track of,\nso I\u0027m starting to clean it all up as well as to slowly move my projects a better competitor.\u003C\/li\u003E\n\u003Cli\u003EI requested removal of one of those accounts, clearly marking which one, and they did remove it\u2026\nand then removed another account too \ud83e\udd26 The one where my server and backups were located and paid for in advance.\u003C\/li\u003E\n\u003Cli\u003EIt\u0027s been over a week and support still hasn\u0027t helped me a bit.\u003C\/li\u003E\n\u003Cli\u003EMy planned move to Hetzner got expedited; and I\u0027ve decided to also make a bunch of improvements\nto my projects along the way: to update language versions, dependencies, licenses, etc., to discontinue some,\nand to make my setup more resilient, easy to restore and less reliant on a single company in the future.\nSo it\u0027s been infuriating, but with silver lining.\u003C\/li\u003E\n\u003Cli\u003EUnfortunately, I also lost some databases in the process \u2013 causing one project to be prematurely discontinued,\nand a few others to lose some less important but cool stats\u2026\u003C\/li\u003E\n\u003Cli\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After 17 days I received a call from the claims department: they took responsibility for the incident,\napologised, confirmed that the data is not recoverable, and offered me 136,38\u20ac (six months worth of the cost of the service) \u2013\nwhich would be a reasonable compensation for the trouble, but is a laughable compensation for the unrecoverable loss of data.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Chr \/\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022#what-happened\u0022\u003EWhy would OVH do that? How did they handle the situation?\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022#my-mistakes\u0022\u003EWhat could I have done better?\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022#silver-linings\u0022\u003ESilver linings\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022#databases-lost\u0022\u003EDatabases lost\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022#receipts\u0022\u003EReceipts\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch2\u003EWhy would OVH do that? How did they handle the situation? \u003Ca id=\u0022what-happened\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003EI\u0027ve been using OVH to host my VPS and register my domains for ages now. They used to be good enough,\nbut most importantly cheaper than everyone else. Now, however, I can get better machines\nand better service for less. I was recommended a German company called \u003Ca href=\u0022https:\/\/hetzner.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Hetzner\u003C\/a\u003E\nand I\u0027ve been planning to move there, and procrastinating on that plan, since, *checks notes*, October 2022 \ud83d\ude05\u003C\/p\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003ECompany\u003C\/th\u003E\n\u003Cth\u003EModel\u003C\/th\u003E\n\u003Cth\u003ECPU\u003C\/th\u003E\n\u003Cth\u003ERAM\u003C\/th\u003E\n\u003Cth\u003EDisk space\u003C\/th\u003E\n\u003Cth\u003EBandwidth\u003C\/th\u003E\n\u003Cth\u003EPrice\u003C\/th\u003E\n\u003C\/tr\u003E\n\u003C\/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EOVH\u003C\/td\u003E\n\u003Ctd\u003EVPS 2018 SSD 3\u003C\/td\u003E\n\u003Ctd\u003E2 vCores\u003C\/td\u003E\n\u003Ctd\u003E8 GB\u003C\/td\u003E\n\u003Ctd\u003E80 GB + 50 GB extension\u003C\/td\u003E\n\u003Ctd\u003EUnlimited (with fair use policy)\u003C\/td\u003E\n\u003Ctd\u003E22.73\u20ac\/month\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EHetzner\u003C\/td\u003E\n\u003Ctd\u003ECX42\u003C\/td\u003E\n\u003Ctd\u003E8 vCores\u003C\/td\u003E\n\u003Ctd\u003E16 GB\u003C\/td\u003E\n\u003Ctd\u003E160 GB\u003C\/td\u003E\n\u003Ctd\u003E20 TB\u003C\/td\u003E\n\u003Ctd\u003E19.84\u20ac\/month\u003C\/td\u003E\n\u003C\/tr\u003E\n\u003C\/tbody\u003E\n\u003C\/table\u003E\n\u003Cp\u003EI\u0027ve actually been using Hetzner for a while for a different project,\never since I moved \u003Ca href=\u0022https:\/\/pronouns.page\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Pronouns.page\u003C\/a\u003E\nto its separate setup (see: \u003Ca href=\u0022\/blog\/pronouns-page-migration.lite\u0022\u003E Migrating Pronouns.page to a new server \u2013 a success story\u003C\/a\u003E) \u2013 and I can only recommend them!\u003C\/p\u003E\n\u003Cp\u003EWhich is not the case for OVH at all\u2026 While the price difference is not terrible \u2013\nI could live with this specification for that money \u2013\nthere are so many other things about OVH that kept annoying me greatly. Their dashboard is slow, buggy\nand has terrible user experience. Your account is bound to a country in which you created it,\nmeaning that me, a person who moved from Poland to Germany and then from Germany to Netherlands,\nended up with three separate accounts \u2013 and scary automated emails warning me that if my whois information\nis proved to be inaccurate they will have to take away my domains. That information\nincludes the physical address and phone number, which are bound to a country,\nso it \u003Cem\u003Ewon\u0027t let me\u003C\/em\u003E update them without making me create a brand new account.\u003C\/p\u003E\n\u003Cp\u003EOkay, then just create a new account and move the domains and servers there, how hard can that be?\nWell, hard\u2026 The procedure to move a single domain, at least at the time I did that, required separately\nchanging three contacts (iirc: administrative, billing and technical), confirming each of them via a code\nfrom the email sent to the old owner, then another email sent to the new owner.\nMultiply that by, idk like ten domains?, and you\u0027re stuck for hours with like sixty confirmation codes\nbetween two browsers, two email accounts, waiting for all emails to arrive and verifying which\nidentifier is which. Rather than just letting me say: \u201chey, btw, I live in the Netherlands now\u201d \ud83e\udd26\u200d\nThey seem to have an affinity to spamming people with long plain-text emails \u2013\nto a point one starts just glancing at them briefly and throwing them in archive without giving them too much thought.\u003C\/p\u003E\n\u003Cp\u003EAnyways\u2026 In early June 2024 the status of my accounts is:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ea Polish account that hasn\u0027t been used in like 5 years,\u003C\/li\u003E\n\u003Cli\u003Ea German account that only has a VPS, which I\u0027m planning to just move directly to Hetzner,\u003C\/li\u003E\n\u003Cli\u003Ea Dutch account that hosts a bunch of domains.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003ESo as a person who would like to finally get the ball moving on the Hetzner move I\u0027ve decided to at least\nclean up what I can: instead of three NIC\u0027s (account identifiers) in three countries connected to three email addresses,\nthree password manager entries and three OTP manager entries, I could have two of each \u2013\nand some more motivation to slowly but surely start moving everything.\nI tried looking for a \u201cremove account\u201d button, but to no avail. After a bunch of digging,\nI finally managed to find where to request the removal, via the GDPR procedure.\nAnd I did \u2013 while logged in to the Polish account, specifying the NIC of the Polish account\nin the form, and then again in the text of the request. Over the next week I got a few emails\nthat they\u0027re working on it, and I thought that was it.\u003C\/p\u003E\n\u003Cp\u003EOh how wrong I was. One day my husband let me know that \u003Ca href=\u0022https:\/\/generator.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Generator\u003C\/a\u003E\nis down \u2013 so I tried SSH-ing to the VPS; it didn\u0027t let me, so I logged in to the OVH dashboard\nto debug with their in-browser console or to just reset the server: only to see that\u2026 \u003Cem\u003Ethere is no server\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EI confirmed that the Polish account is indeed entirely gone, but the German one, while still existing,\nis completely empty, except for a history of payments and a support ticket.\nA ticket that I opened from the \u003Cem\u003EPolish\u003C\/em\u003E account, written in Polish, specifying the Polish account\u0027s NIC \u2013\nand their reply, also in Polish, that the German account is being removed.\u003C\/p\u003E\n\u003Cp\u003EI opened a new ticket bringing the situation to their attention.\nI even got over my social anxiety around phone calls and called their customer support \u2013\nafter all the sooner they react, the better the chance that the data is recoverable.\nSurprisingly, they didn\u0027t leave me on hold for ages or pass me through lengthy automated process,\nI actually got to talk to a real person within minutes. They gathered the info, they could see my tickets\nin the system, they told me they\u0027ll forward it to the appropriate department and that I should expect\nsomeone to contact me within \u003Cem\u003Ehours\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EFast forward a week (and an angry nudge in the ticketing system) \u2013 still zero reaction.\u003C\/p\u003E\n\u003Ch2\u003EWhat could I have done better? \u003Ca id=\u0022my-mistakes\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003EI think the reason why someone removed the German account along with the Polish one is that\nwhile the account I was logged into when requesting removal,\nthe NIC I put in the form, the content and the language of my message all pointed to the Polish account,\none item did not: the form asked me for an email address and I mistakenly put in\nthe one associated with the German account.\u003C\/p\u003E\n\u003Cp\u003EWhich is an easy mistake to make when you\u0027re being forced to manage three separate accounts\nthat could\u0027ve easily been one. But more importantly: they didn\u0027t check if the email address entered\nactually belongs to the person making the GDPR request (eg. by them being logged in, by the user sending\nthem an email from that account, by requiring a confirmation code by email);\nin this case both accounts happened to belong to the same person, but what if I put in \u003Cem\u003Esomeone else\u0027s\u003C\/em\u003E email?\nWould someone be able to bulldoze a competitor\u0027s entire infrastructure by simply knowing what email\nthey used for their OVH account? That\u0027s absurd!\u003C\/p\u003E\n\u003Cp\u003EAdmittedly, they \u003Cem\u003Edid\u003C\/em\u003E notify me by email that my account is being removed. Among a spam of various emails,\nin a weird mix of Polish and German text, and in which the account to be removed is referenced solely\nby a NIC: a random string of numbers that I need to either remember or check my notes each time to know which is which.\nI think they also \u003Cem\u003Etried\u003C\/em\u003E to tell me that my VPS is gonna be removed along the account,\nbut the wording is \u003Cem\u003Eabsolutely terrible\u003C\/em\u003E: \u201creferencja do us\u0142ugi na Twoim koncie wymaga niezb\u0119dnych operacji\u201d,\nwhich translates to \u201ca reference to a service in your account requires necessary operations\u201d \ud83e\udd26\nQuite a long way from what I\u0027d expect to be the best practice:\na big, bold \u201chey, your account XYZ still has a VPS that\u0027s running and paid for, are you sure?!\u201d\u003C\/p\u003E\n\u003Cp\u003EI could\u0027ve moved to Hetzner 1,5 year ago. Oh honey, I so wish I had.\nBut that\u0027s not an effort for one afternoon. There used to be 52 (!) projects hosted there along with\n5 third-party web-based apps, and a bunch of dependencies.\nSome of that was using PHP 7.4, some PHP 8.3, some Node 18, some Node 20, some were just statically generated pages.\nIf I were to move it over, I\u0027d rather upgrade to newer version instead of supporting separate ones.\nAnd I\u0027m a busy enby. I wrote earlier that I was \u201cprocrastinating\u201d on the move, but that\u0027s not really accurate \u2013\nI was \u003Cem\u003Edamn\u003C\/em\u003E busy with a bunch of other things, like \u003Ca href=\u0022https:\/\/pronouns.page\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Pronouns.page\u003C\/a\u003E\n(which luckily was on a separate server already), or idk, one of the 153 repos I seem to have on my\n\u003Ca href=\u0022https:\/\/gitlab.com\/users\/Avris\/projects\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Gitlab\u003C\/a\u003E (some of them private, so they won\u0027t show up under the link).\nSo a proper move simply hasn\u0027t been a priority. Until OVH made it my priority.\u003C\/p\u003E\n\u003Cp\u003EI could\u0027ve made the project easier to restore. Keep the configuration and a library of system packages in a repo,\nAnsible-style, or whatnot. Yeah, well, that was the plan for the Hetzner move \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003EAnd yes, I can hear hypothetical people screaming. Yes, I should\u0027ve had backups.\nWell, I did. I had a script that was supposed to zip the most important data and store them on S3,\nbut it broke and I haven\u0027t found time to debug the issue\u2026\nI gave it low prio because I was planning to abandon the server anyway,\nand more crucially because I also had separate backups of the most important thing \u2013 databases.\nOther things I can restore with some effort, but databases would just be \u003Cem\u003Elost\u003C\/em\u003E.\nThe thing is, what I used for those backups is\u2026 OVH\u0027s built-in automatic backups of MySQL databases.\nI wish I could still see any indication in the dashboard that those backups were ever there,\ncause my anxiety whispers in my ear that my memory might be misleading me \u2013\nbut I can\u0027t, because the whole account is wiped.\u003C\/p\u003E\n\u003Cp\u003EAnyways\u2026 the thing is: I know I could\u0027ve handled a bunch of things better.\n\u003Cstrong\u003EBut my biggest mistake was trusting that OVH will handle my account appropriately\u003C\/strong\u003E.\nFor heaven\u0027s sake, that server was even paid for for another month an a half \u2013\nwhy would you wipe customer\u0027s infrastructure that\u0027s paid for, actively running,\nand part of a different account than the one that made the GDPR request?\u003C\/p\u003E\n\u003Cp\u003EUntil now, I simply disliked OVH as a customer. How I actively distrust them, and I doubt that will ever change.\nI could never trust them again with any data or infrastructure.\u003C\/p\u003E\n\u003Ch2\u003ESilver linings \u003Ca id=\u0022silver-linings\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003EBut\u2026 it\u0027s not all shit. I actually managed to find a lot of silver linings in the whole situation.\nObviously, OVH forced me to finally prioritise the changes I\u0027ve been planning to do for over a year \u2013\nso I finally got most of them done, yay. I guess, thank you?\nBut other things on my list are stuff that I would\u0027ve done anyway, eventually\u2026\nStill, I like to think about the positives, so here we go.\u003C\/p\u003E\n\u003Cp\u003EI moved to a faster and cheaper machine. Yay!\u003C\/p\u003E\n\u003Cp\u003EMy IP is finally fully private and protected by Cloudflare\u0027s proxy.\nI\u0027ve had the old server way before I even knew that it\u0027s a thing \u2013 so someone somewhere\ndug it up and used it to DDoS me, circumventing Cloudflare\u0027s protection.\nIronically, they were queerphobes targeting Pronouns.page, but they didn\u0027t know\nthat this project has had its own separate server for a while now, and its IP is still secret.\nNow, so is Avris\u0027s.\u003C\/p\u003E\n\u003Cp\u003EI had a list of 57 projects\/apps\/hosts\/(sub)domains running on the old server.\nNow that list has just 25 items. The remaining ones are those that either got popular, or didn\u0027t at all\nbut I really like them and they aren\u0027t that much effort to maintain.\nI\u0027m following \u003Ca href=\u0022https:\/\/www.youtube.com\/watch?v=9LZEZ5QuyzM\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Tom Scott\u0027s advice\u003C\/a\u003E\nto create a lot of stuff and increase the odds of some of them succeeding \u2013\nbut that also means I need to be ready for a lot of what I do to fail.\nKilling a project is tough, even if no one, including myself, even uses it anymore.\nBut this whole situation made me tear off that band-aid.\u003C\/p\u003E\n\u003Cp\u003EA half-baked idea that I decided to publish way too soon? Poof.\nA framework that helped me learn a lot about PHP, software and software architecture,\nbut that also makes less sense to use than something more established? Poof.\n(Well, the repo is still public, but no need to keep the website up).\nAn app that stopped working after Elon Musk broke Twitter\u0027s API (unless I pay a bazillion euros)? Gone.\nA legacy version of a page that I kept up \u003Cem\u003Ejust in case\u003C\/em\u003E? Bye!\u003C\/p\u003E\n\u003Cp\u003EIt\u0027s not easy to say goodbye to them, but it helps with the overwhelm.\nI no longer maintain a terrifying number of apps I can\u0027t keep track of \u2013\nit\u0027s just two dozen that I actually care about.\u003C\/p\u003E\n\u003Cp\u003EThere\u0027s a bunch of things that I wanted to fix or improve in each and every one of those projects,\nbut doing that to twenty something of them is \u003Cem\u003Eway\u003C\/em\u003E more manageable than to fifty something.\nSo here we go: I upgraded Node, PHP, Symfony and a bunch of dependencies to the latest versions for all of my apps \u2013\nand to the same version across the whole server. I renamed the \u003Ccode\u003Emaster\u003C\/code\u003E branch to \u003Ccode\u003Emain\u003C\/code\u003E in those older\nprojects that still used the outdated name. I changed my name in the READMEs and footers\nto reflect my new legal name (\u003Ca href=\u0022\/blog\/it-s-official-my-name-is-andrea-vos-now.lite\u0022\u003E it\u0027s official! my name is andrea vos now \ud83e\udd73\u003C\/a\u003E) wherever it still needed an update.\nI changed the license of my projects to \u003Ca href=\u0022https:\/\/oql.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E OQL\u003C\/a\u003E wherever it was still MIT.\nI switched from Yarn to pnpm. Stuff like that.\u003C\/p\u003E\n\u003Cp\u003EWhen upgrading \u003Ca href=\u0022https:\/\/cake.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Cake\u003C\/a\u003E I also added better RTL support\nby upgrading Bootstrap and improving keyboard control logic. For \u003Ca href=\u0022https:\/\/oql.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E OQL\u003C\/a\u003E\nI made the dark mode look nicer. For \u003Ca href=\u0022https:\/\/heartbeat.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Heartbeat\u003C\/a\u003E\nI added a way to compress older data to reduce database size and refactored the config\nso that it\u0027s more readable and allows for async calls (like API calls or caching).\n\u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Deployer\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Deployer\u003C\/a\u003E got a bunch of improvements\nthat I\u0027ll release soon as v2.0.\u003C\/p\u003E\n\u003Cp\u003EThe server configuration as a whole got better too. I applied a bunch of the same improvements\nthat I had earlier made for Pronouns.page (\u003Ca href=\u0022\/blog\/pronouns-page-migration.lite\u0022\u003E Migrating Pronouns.page to a new server \u2013 a success story\u003C\/a\u003E) \u2013 including\na switch from Apache to Nginx and organising configs better.\nMy notes from that move were \u003Cem\u003Esuper\u003C\/em\u003E helpful and made this one easier and faster \u2013\nbut this time I wanted to make the process even better, and turn them into a nice little repository\nof scripts and configs that can be used to really boost the process if I ever need to do it again\n(or, more likely, use it as a template for future projects).\u003C\/p\u003E\n\u003Cp\u003EAnd, of course, setting up proper backups in multiple locations (all far away from OVH)\nget a way higher priority on my list after this incident. The new setup is still in the works,\nbut it will be a great improvement.\u003C\/p\u003E\n\u003Ch2\u003EDatabases lost \u003Ca id=\u0022databases-lost\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003ELuckily, most of my projects don\u0027t really need a database \u2013 they\u0027re either landing pages for libraries,\nor tools that encode data in the URL, or something like that. Restoring them was just a matter of\nspending time and effort on configuring everything again. But for those that do need to store data\ngenerated by users, the loss is unfortunately bigger\u2026\u003C\/p\u003E\n\u003Cp\u003EThe biggest by far was \u003Ca href=\u0022\/blog\/redesigning-a-website-naked-adventure.lite\u0022\u003E naked-adventure.eu\u003C\/a\u003E \u2013\na website that crowdsources information on nudist beaches and establishments.\nOn one hand, so much of mine and other people\u0027s work suddenly got wiped from OVH\u0027s infrastructure,\nbut on another I\u0027m actually a bit relieved\u2026 It\u0027s the kind of page that makes the most sense on a big scale \u2013\nafter all, just under 200 places in our database is almost nothing on the global scale;\nwhat\u0027s the point of even visiting the page if you\u0027re statistically unlikely to find what you\u0027re looking for?\nAnd for me personally, over the years naturism stopped being a new exciting thing that I love,\nand became just a regular part of my life. The enthusiasm and motivation to run this page faded,\nwhile overwhelm from other projects and other aspects of my life grew. I was falling behind on moderation,\nnever gotten to implementing some features I planned for it, I didn\u0027t have ideas or resources\nto advertise the platform and to grow it\u2026 So while it\u0027s sad to see it go, the project had been on life support\nfor a while already. I might resurrect it one day, with some new twist, but for now, rest in peace.\u003C\/p\u003E\n\u003Cp\u003EI also had some pages that collected stats about people\u0027s responses in a quiz,\nlike \u003Ca href=\u0022https:\/\/corevalues.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E CoreValues\u003C\/a\u003E. The pages are back up, but the stats are gone.\u003C\/p\u003E\n\u003Cp\u003EMy husband\u0027s blog got wiped too \u2013 but he has local copies of all texts,\nand he hasn\u0027t published there in a while anyway, so not that much harm.\u003C\/p\u003E\n\u003Cp\u003EI also lost website analytics from \u003Ca href=\u0022https:\/\/plausible.io\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Plausible\u003C\/a\u003E.\nBut to be honest, I haven\u0027t really checked them in a while \u2013 I just let my websites run,\nwithout obsessing about the numbers. I still set up a new instance on the new server\nand I\u0027ll be collecting anonymised analytics, but I won\u0027t cry about that particular spilled milk.\u003C\/p\u003E\n\u003Ch2\u003EMental health impact \u003Ca id=\u0022mental-health\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003ESpeaking of crying, though\u2026 I just wanna take a moment to acknowledge the impact that the whole situation\nhas had on my mental health.\u003C\/p\u003E\n\u003Cp\u003EI\u0027m really proud of how I mostly handled the issue. I kept calm, focused on solutions, on positives,\non opportunities. I managed to focus on fixing one thing at a time, to prioritise not only some projects\nagainst others, but also the whole fix against my personal needs \u2013 all of which are stuff that I\u0027ve\nbeen struggling with. I gave myself time to deal with the situation \u003Cem\u003Eproperly\u003C\/em\u003E, as opposed to panicking\nand frantically trying to fix everything with a hammer and a scotch tape, as fast as I can \u2013\nwhich would\u0027ve been my response a few years, if not months, ago.\nThere was no need to rush \u003Cem\u003Ethat much\u003C\/em\u003E: no one got angry with me, I just got a few messages from friends\nand strangers asking if I know that this or that tool is down; I lost some traffic, but it\u0027s not like\nI was monetising it anyway; none of those projects was an essential, irreplaceable, urgently needed\npart of anyone\u0027s live (I hope).\u003C\/p\u003E\n\u003Cp\u003EBut there are limits to what my head can take. While calm on the outside, I was \u003Cem\u003Eextremely\u003C\/em\u003E irritable\nfor the first two days or so, any minor inconvenience could get me over the edge.\nI had two major breakdowns \u2013 but luckily also two amazing partners that helped me through them.\u003C\/p\u003E\n\u003Cp\u003EBasically: I needed time to grieve. I lost a lot of data, a lot of work, my plans for the upcoming week\ngot turned upside-down. One can\u0027t just brush off stuff like this.\u003C\/p\u003E\n\u003Cp\u003EAnyways\u2026 I\u0027m fine now. But I think sharing my experience might help someone one day, so I wanted to it.\u003C\/p\u003E\n\u003Ch2\u003EReceipts \u003Ca id=\u0022receipts\u0022\/\u003E\u003C\/h2\u003E\n\u003Cp\u003EContext: pa13\u25a0\u25a0\u25a0\u25a0 = Polish account; pa60\u25a0\u25a0\u25a0\u25a0 = German account\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-1-2_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-1-2_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022236.8115942029\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-1-1_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-1-1_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022283.03860523039\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-2-2_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-2-2_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022280.19417475728\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-2-1_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-ticket-2-1_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022273.51620947631\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-bill-1_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-bill-1_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022151.95530726257\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-bill-2_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-bill-2_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022165.65581395349\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-emails-pl_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-emails-pl_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022263.43307086614\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-emails-de_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ovh-bulldozer-emails-de_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022384.83412322275\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E","words":3377,"readTime":14,"lang":"en"}}},"blog\/technology\/ads-suck":{"key":"blog\/technology\/ads-suck","type":"article","published":true,"meta":{"createdAt":"2023-09-11T09:55:06+02:00","publishedAt":"2023-09-11T09:55:06+02:00","group":null,"category":"blog","subcategory":"technology","slug":"ads-suck"},"content":{"en":{"slug":"ads-suck","title":"Ads suck\u2026 also for the publishers","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/frustration-computer-unsplash_small.jpg\u0022 alt=\u0022illustration: a business woman who is stressed and frustrated\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAIXklEQVRIiVWWW4wlRR3Gf\/Wvqu4+lzlnbntHZhd2cVkhwF64ChExivrog8SExMQHEx8NQZ+MxgckMWDim4kvJiQ+SGSVRBIkQWSRRBcC2c3CsrjXmdnZmZ2dObe+VVf50L0Dnk6lu87pVH31\/b\/v+x91+xcPhNXVVbQoQFGFEhtH\/OiHP+ZPf36J+f4cixcuUJUVP3jiIVaGY8oAetsennr6abbv2kmRF0wmKVmakmU5ZVFQFCWlczhXUhQFZZ43c0ea1e+WlcPaiCe\/\/k12795FWZSY9fV1lEDlKyrnQBQUJS8f\/yOD62usXl7m6N4FfJUzMzPF3l1zTLc7nLsx5OO332D+O99DaYUSBSIgQlAKpPlO1cM3d6UUCgUAQaFE0EZQohCtEVdUVN4TAiAKHwLOOVaXFrEB2tbw7aN38sSX9rHQ1eyZ77LpCt56\/zR3zXSJzn9Qb9JsrqAB9zkASiHq8wAhAKiAFoUxBtEaJYIgHi0KTyCEgCgh0oZYaYIP7JzuItbTbxmkLJiNLaFyPPXoffzhjbc4c+bU1sZyk5nmWbYA1SCVEqQBFRSAQkRjjMFojdaCaBGMaJSAEsFYTTuylGVJWlQsb4xYXL6GhArnPZubAxLleeHl17ChIDZS068UCJ8x0pSsHnoLjBL5DKwoxBiMtYjWNcDhYMx4lCIIIhoAQRECZEVB5T2D0Zi5VsT0dJf2bB833OSn3zrGx\/+9SG9+282ToZtTaqMR0bUmpAZS3wUtunlPY7UhthZrLVqEqnIYrQ2gKfPQCM0zth7vA4RAPzHcs3uebXMz7N63l9\/\/7QSdImW61yFDIdu+gDYGaw3OWYyrCD7gTS0BbzS6MhjjUaIw2lCWJVFU4n0gimNMox8tgmhjUSK1w0IgBBhPiroKohhknn98ssx6KbzyzgfsSBKmuj1+9eoJvvv4EXbM9THaYI2ttWCbYQzGWKyxaGvQzfzYgw+ysHcv1liiKCZKEnTDpFIKHUXJz4W67j7ULFWuwlUVYixFBR+t3OCVf3\/EhaUVDs32yb1wenmF\/bfsYry6xG9fOs7Dj3wZrTXeBxqua8ID4D0+BOZm55iZmWa6P42OLIPBgG6ny2237aOVJBR5iYFQ5waK4FzjGNDagNJU3qOVgIJRXvL2+Yt8vLLOpKz43asnaLfbrG4MeOYnz9LtdtDGYbytyxYCxnsqbzE+MDc\/T55m+BDYuWMnRVaQF8WW81BgalICBPAhELyvXaLNlmMCAUFhVMXppVWmp1r4Ai5fXSOaZFsiFa3RxuArjzca4z1eG0Q5lAjtJGY0GtX7VJ5Tpz4kabehico6dhQNGN+kKFgbo7VB3byUwrkSRJHEFgUcPXIYhcI5RwCWl5YRJWilmyyqNUETtP1en\/FwgMtzqrxgMBgQJwm37NlDE0moAE2IhC02ojhGa83NdK\/XrBe9McrYnOTcmBS89fY7aK1RCnxV8dfjf6nL3rSEQKCqPHlZUhQlnSQmm4wpy4KyLFlaXqIoCtIsI1CbqS5xqMEE7xGtCfV6qBDqNFUKo4VQCWlekRWOMC4oncP7gI0iKu85efI9QgiE4PHe40pHnufkeU4IHk3FME2p0CgCKysreB9otTv4m4kDiAq1FRSgRepedNMmIXBw\/z76vR6l8zhXEScditI1zShQOYcoxblPznLxwkVc6SjynCzNSNOU0eYmiTVsXL9GNhmSpTlrq6tMshwRwWhN8L7Wjwjig29OVttViTRzMFrz1a88gjUWpcBGEc+\/+CIPP\/roVkSE4HGVw1eeVqdN1oDJ0ozxaMRoc41uK2G0uUk6HjPZvMbyygrOOZz3+ADOVVRNXEjwNRglwv9\/Ag\/cf5ik1UZM3WduP3CAfq\/Pc88\/x89++Qs63W6dxo3FRQlZmjEZj9i4fo31a8u0Wx3cZECejrfGOMupvKcoCgbDAatr10mzjMkkw\/hQIUEjbOkYpWCq2+HwvXczHqfNL4Fjx+7nxvXrJJHm4QceYO755\/jNr1\/gypVFpqenef\/Em6xdXSKSilAVeJex49ARNtfXKIuMPMsRY8ivnkVrg4hlcs1y7fIULaMYjwtM3b4qPGzZ3jfaWbp8heFgQBRyds31OP2ff3HpkzOIMUwmORvDIShh3759zG3fxrnLyww3B6RZweraGgrFnUf6bKwuM5ykXFlZR7uUMBlhxdNqJbTzLuOlc3y6scZ4PEHNT3eDD4Gy8vigAKGTWHZvn+Xue45y7KHHOHDoLrbv2IE2msuXLvLG31\/nw\/dOsufWBYbDIStXlxkNR3Snpuqu7z1FgIMHD3L40H7OX1rk3IVF1jY26SeaB2+17OoneDHEU9to93fiKo8rStT9B7YHqwWjBaMVk9xzPdOMy0DpIYpbtJKEfq\/Pvffdy5NPfoM4jnn2mWeIkoSFWxeYnZul0+kQJwmECieGMB5j44hPz19Ce00VHPNxzmN3dInwpGVJhSGemidp9fFKyNMUs326veWq4D1RS5juKEQJErXJg2WcO9Y3rmI2LuE+ehMf4Ptfu487FnYRWYvWlk6vx9rmiLI3y+69+zl1epHXXzvOztlprq6OuGM2sH\/nHL7MGZQlk6xEWYVuebwStFigwLjKg691QwiIKKxStBPDTM+iTURRRayPNGfOnmVhdopebwptLP88eYbtczMgBmVjLi5eZX2cYnQN8rY9u1hcvMjjB2+BULA2njDTCgxGBVUI6KokW9tAjytaUUKaTjDeB+LI0I4NkdVopTACRkE7FiIb8JWnFwkzkfDu++8yHBW4ytOyhnORoaig07KMQoxTmkK1iXXEfAfu3t1iMBxQes+NjQFpx5LEmsjWf2cRRy8OJG1N21j+B+AfUXTdiTyCAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/frustration-computer-unsplash_small.jpg\u0022 alt=\u0022illustration: a business woman who is stressed and frustrated\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022320\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ENobody likes ads, obviously.\nBut what came as a painful surprise for me is that they don\u0027t just annoy people who see them\n\u2013 but also those who try to monetise their projects.\nIt\u0027s not just a matter of putting a few tags on your page and waiting for a big fat wire transfer.\u003C\/p\u003E\n\u003Cp\u003EThe process is exhausting and I feel the need to rant about it,\nas well as maybe warn people who might be embarking on a similar journey\u2026 so here we go.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/frustration-computer-unsplash_big.jpg\u0022 alt=\u0022illustration: a business woman who is stressed and frustrated\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022640\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAIXklEQVRIiVWWW4wlRR3Gf\/Wvqu4+lzlnbntHZhd2cVkhwF64ChExivrog8SExMQHEx8NQZ+MxgckMWDim4kvJiQ+SGSVRBIkQWSRRBcC2c3CsrjXmdnZmZ2dObe+VVf50L0Dnk6lu87pVH31\/b\/v+x91+xcPhNXVVbQoQFGFEhtH\/OiHP+ZPf36J+f4cixcuUJUVP3jiIVaGY8oAetsennr6abbv2kmRF0wmKVmakmU5ZVFQFCWlczhXUhQFZZ43c0ea1e+WlcPaiCe\/\/k12795FWZSY9fV1lEDlKyrnQBQUJS8f\/yOD62usXl7m6N4FfJUzMzPF3l1zTLc7nLsx5OO332D+O99DaYUSBSIgQlAKpPlO1cM3d6UUCgUAQaFE0EZQohCtEVdUVN4TAiAKHwLOOVaXFrEB2tbw7aN38sSX9rHQ1eyZ77LpCt56\/zR3zXSJzn9Qb9JsrqAB9zkASiHq8wAhAKiAFoUxBtEaJYIgHi0KTyCEgCgh0oZYaYIP7JzuItbTbxmkLJiNLaFyPPXoffzhjbc4c+bU1sZyk5nmWbYA1SCVEqQBFRSAQkRjjMFojdaCaBGMaJSAEsFYTTuylGVJWlQsb4xYXL6GhArnPZubAxLleeHl17ChIDZS068UCJ8x0pSsHnoLjBL5DKwoxBiMtYjWNcDhYMx4lCIIIhoAQRECZEVB5T2D0Zi5VsT0dJf2bB833OSn3zrGx\/+9SG9+282ToZtTaqMR0bUmpAZS3wUtunlPY7UhthZrLVqEqnIYrQ2gKfPQCM0zth7vA4RAPzHcs3uebXMz7N63l9\/\/7QSdImW61yFDIdu+gDYGaw3OWYyrCD7gTS0BbzS6MhjjUaIw2lCWJVFU4n0gimNMox8tgmhjUSK1w0IgBBhPiroKohhknn98ssx6KbzyzgfsSBKmuj1+9eoJvvv4EXbM9THaYI2ttWCbYQzGWKyxaGvQzfzYgw+ysHcv1liiKCZKEnTDpFIKHUXJz4W67j7ULFWuwlUVYixFBR+t3OCVf3\/EhaUVDs32yb1wenmF\/bfsYry6xG9fOs7Dj3wZrTXeBxqua8ID4D0+BOZm55iZmWa6P42OLIPBgG6ny2237aOVJBR5iYFQ5waK4FzjGNDagNJU3qOVgIJRXvL2+Yt8vLLOpKz43asnaLfbrG4MeOYnz9LtdtDGYbytyxYCxnsqbzE+MDc\/T55m+BDYuWMnRVaQF8WW81BgalICBPAhELyvXaLNlmMCAUFhVMXppVWmp1r4Ai5fXSOaZFsiFa3RxuArjzca4z1eG0Q5lAjtJGY0GtX7VJ5Tpz4kabehico6dhQNGN+kKFgbo7VB3byUwrkSRJHEFgUcPXIYhcI5RwCWl5YRJWilmyyqNUETtP1en\/FwgMtzqrxgMBgQJwm37NlDE0moAE2IhC02ojhGa83NdK\/XrBe9McrYnOTcmBS89fY7aK1RCnxV8dfjf6nL3rSEQKCqPHlZUhQlnSQmm4wpy4KyLFlaXqIoCtIsI1CbqS5xqMEE7xGtCfV6qBDqNFUKo4VQCWlekRWOMC4oncP7gI0iKu85efI9QgiE4PHe40pHnufkeU4IHk3FME2p0CgCKysreB9otTv4m4kDiAq1FRSgRepedNMmIXBw\/z76vR6l8zhXEScditI1zShQOYcoxblPznLxwkVc6SjynCzNSNOU0eYmiTVsXL9GNhmSpTlrq6tMshwRwWhN8L7Wjwjig29OVttViTRzMFrz1a88gjUWpcBGEc+\/+CIPP\/roVkSE4HGVw1eeVqdN1oDJ0ozxaMRoc41uK2G0uUk6HjPZvMbyygrOOZz3+ADOVVRNXEjwNRglwv9\/Ag\/cf5ik1UZM3WduP3CAfq\/Pc88\/x89++Qs63W6dxo3FRQlZmjEZj9i4fo31a8u0Wx3cZECejrfGOMupvKcoCgbDAatr10mzjMkkw\/hQIUEjbOkYpWCq2+HwvXczHqfNL4Fjx+7nxvXrJJHm4QceYO755\/jNr1\/gypVFpqenef\/Em6xdXSKSilAVeJex49ARNtfXKIuMPMsRY8ivnkVrg4hlcs1y7fIULaMYjwtM3b4qPGzZ3jfaWbp8heFgQBRyds31OP2ff3HpkzOIMUwmORvDIShh3759zG3fxrnLyww3B6RZweraGgrFnUf6bKwuM5ykXFlZR7uUMBlhxdNqJbTzLuOlc3y6scZ4PEHNT3eDD4Gy8vigAKGTWHZvn+Xue45y7KHHOHDoLrbv2IE2msuXLvLG31\/nw\/dOsufWBYbDIStXlxkNR3Snpuqu7z1FgIMHD3L40H7OX1rk3IVF1jY26SeaB2+17OoneDHEU9to93fiKo8rStT9B7YHqwWjBaMVk9xzPdOMy0DpIYpbtJKEfq\/Pvffdy5NPfoM4jnn2mWeIkoSFWxeYnZul0+kQJwmECieGMB5j44hPz19Ce00VHPNxzmN3dInwpGVJhSGemidp9fFKyNMUs326veWq4D1RS5juKEQJErXJg2WcO9Y3rmI2LuE+ehMf4Ptfu487FnYRWYvWlk6vx9rmiLI3y+69+zl1epHXXzvOztlprq6OuGM2sH\/nHL7MGZQlk6xEWYVuebwStFigwLjKg691QwiIKKxStBPDTM+iTURRRayPNGfOnmVhdopebwptLP88eYbtczMgBmVjLi5eZX2cYnQN8rY9u1hcvMjjB2+BULA2njDTCgxGBVUI6KokW9tAjytaUUKaTjDeB+LI0I4NkdVopTACRkE7FiIb8JWnFwkzkfDu++8yHBW4ytOyhnORoaig07KMQoxTmkK1iXXEfAfu3t1iMBxQes+NjQFpx5LEmsjWf2cRRy8OJG1N21j+B+AfUXTdiTyCAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/frustration-computer-unsplash_big.jpg\u0022 alt=\u0022illustration: a business woman who is stressed and frustrated\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022640\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/unsplash.com\/photos\/bmJAXAz6ads\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        unsplash.com\/photos\/bmJAXAz6ads\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ENobody likes ads, obviously.\nBut what came as a painful surprise for me is that they don\u0027t just annoy people who see them\n\u2013 but also those who try to monetise their projects.\nIt\u0027s not just a matter of putting a few tags on your page and waiting for a big fat wire transfer.\u003C\/p\u003E\n\u003Cp\u003EThe process is exhausting and I feel the need to rant about it,\nas well as maybe warn people who might be embarking on a similar journey\u2026 so here we go.\u003C\/p\u003E\n\u003Ch2\u003EThe system\u003C\/h2\u003E\n\u003Cp\u003EIn a perfect world, if I create a popular website, I could easily find someone who wants to use\nthat advertising space, they give me money, I add their banner, everyone is happy.\nThe ad is simply relevant to the page content, not the personal info about any particular user.\nIn practice, though, unless you\u0027re a huge company with enough resources, finding advertisers\nand negotiating deals is a tedious task that a random programmer or creator just isn\u0027t equipped to do.\u003C\/p\u003E\n\u003Cp\u003EThat\u0027s why ad networks exist \u2013 they facilitate the process, act as proxies between publishers and advertisers,\nand they take their cut. Cool concept, it really is. The problem, though, is the capitalist approach\nof squeezing the last bits of value from the process, at the cost of user experience, privacy and simplicity.\u003C\/p\u003E\n\u003Cp\u003EWhen I was researching ad networks last year, I only found one that was plain and simple:\n\u003Ca href=\u0022https:\/\/www.ethicalads.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E EthicalAds\u003C\/a\u003E. It would\u0027ve been perfect for my needs, if it wasn\u0027t for the fact\nthat it\u0027s only applicable for websites that target software developers.\nI run a few of those, but they\u0027re too tiny to join the network, while the popular project\nthat me and the rest of the collective wanted to use it for,\n\u003Ca href=\u0022https:\/\/en.pronouns.page\/blog\/why-ads\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Pronouns.Page\u003C\/a\u003E, is for a totally different audience.\u003C\/p\u003E\n\u003Cp\u003ESo it was more a choice of lesser evil than finding an ad network that we\u0027d be totally comfortable with.\nPersonally, I wanted to avoid dealing with Google, but it looks like most networks are strongly relying\non AdSense anyway. We ended up trying three different networks so far, and today I\u0027ve sent\nthe third one a termination notice after having been in talks with the fourth network to switch to them.\nLet\u0027s hope that the fourth time will be the charm \ud83d\ude05\u003C\/p\u003E\n\u003Ch2\u003EHard to test for all users\u003C\/h2\u003E\n\u003Cp\u003EI don\u0027t really wanna name and shame any specific companies, cause it seems like the issues\nare there all over the industry, plus some of our problems \u003Cem\u003Emight\u003C\/em\u003E be stemming from our own inexperience\nin the advertisement world (although that shows how inaccessible the process is to an average publisher).\u003C\/p\u003E\n\u003Cp\u003EOne inherent problem with ad networks is that it\u0027s practically impossible to \u003Cem\u003Efully\u003C\/em\u003E test\nhow they will look on your website. I can put seven empty placeholders on the page,\nas instructed by an expert from the network, and then test it and see that three of them got\nfilled out with ads \u2013 while you load the same page and see all seven.\nI might be shown ads of food delivery companies \u2013 while you get shown some disgusting foot fungus medication ad.\nSome networks let you pick the categories that will and will not be shown, and even review post-factum\nwhich specific ads have been shown to users and block those advertisers for the future \u2013\nbut others give you zero flexibility in that area.\nIn general, algorithms, mathematical models, AI and real-time bidding have more say than humans.\u003C\/p\u003E\n\u003Ch2\u003ETechnical issues\u003C\/h2\u003E\n\u003Cp\u003EBut that\u0027s something that\u0027s, admittedly, hard to avoid in the existing ecosystem.\nOther issues were more avoidable. For example, when we first tried one network, it utterly broke our website.\nThey offered a super simple setup \u2013 just give them access to your Cloudflare and they\u0027ll proxy\neverything, not only adding the necessary ad scripts, but also optimising the traffic and speeding up your page.\nSounds cool, didn\u0027t work. Well, it probably does for most of their publishers, but in case of our\n\u003Ca href=\u0022https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Progressive_web_apps\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PWA\u003C\/a\u003E and some DNS entries their scripts\nwere not expecting, we ended up with no ads and no ability to log in. Not fun.\u003C\/p\u003E\n\u003Cp\u003EYou\u0027d think that adding a script that\u0027s loaded after the rest of the page and should limit its\nimpact for a bunch of clearly defined placeholder shouldn\u0027t really affect the performance of the page much.\nHowever, one network\u0027s scripts were somehow affecting us so much that we ended up switching to another\nmainly for that reason. Another broke an essential feature of the page in a way that was troublesome to debug. \u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After installing Sentry we\u0027ve found out \u003Cem\u003Ejust how much\u003C\/em\u003E JS errors ad scripts produced, geeeez\u2026\u003C\/p\u003E\n\u003Ch2\u003EVolatile and unclear revenue\u003C\/h2\u003E\n\u003Cp\u003EAll the networks looked at our traffic numbers and \u003Cem\u003Epredicted\u003C\/em\u003E monthly revenue in the lower five digits area \u2013\nthe kind of money that we could set up a proper foundation with, run educational campaigns, spread our mission,\nemploy people, make the project a full-time job, not just a side project of passion created in spare time.\nBut in practice it was not just lower, but an order of magnitude lower. Still not bad,\nenough to cover the server, domains, cloud and other maintenance costs,\ndo occasional offline stuff like printing \u003Ca href=\u0022https:\/\/zaimki.pl\/zin\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E our zine\u003C\/a\u003E, creating pins, stickers and flyers\nand handing them out at Herts Pride and Toru\u0144 Pride, and distributing the rest among the contributors\nin a form of volunteer allowance. Basically, it\u0027s not some wild, life-changing money,\nbut it keeps the project running while also rewarding contributors for our time and effort,\nand helping us pay our bills. So we\u0027re really grateful to be in that position.\u003C\/p\u003E\n\u003Cp\u003EWhat\u0027s really bugging us, though, is how volatile and unpredictable the whole thing is.\nOf course we\u0027re expecting ups and downs, but sometimes it can just randomly drop by half\nin the span of two months, with no explanation.\nOne that we did get, I\u0027m not kidding, is that after we\u0027ve spent a lot of time optimising the setup with A\/B testing,\nour ad units performed so well that the system counts the traffic as suspicious and just doesn\u0027t pay for it.\nTheir proposed solutions (adding padding and labels to ads so that users are less likely to click on them accidentally)\ndidn\u0027t help at all. And there\u0027s no one to complain about it, you just have to deal with it.\u003C\/p\u003E\n\u003Cp\u003EThere are so many variables at play, it\u0027s super confusing and unclear. Our current ad network tripled (!)\nthe number of ad impressions they were showing our users compared to the previous company,\nwithout it being proportionally reflected in the revenue or becoming more optimised for user experience with time.\u003C\/p\u003E\n\u003Ch2\u003EUnclear reporting, inflexible setups\u003C\/h2\u003E\n\u003Cp\u003EOne network wouldn\u0027t show us any reporting for the first month, we were completely in the dark.\nAnd once we finally got access to the dashboard, it was way less useful than what other networks provided\n(eg. even trying to figure out which ad unit is which was not easy, because the dashboard\nsimply didn\u0027t show their unique identifiers that are used in the code) \u2013 which we couldn\u0027t have known\nuntil we\u0027re a month in.\u003C\/p\u003E\n\u003Cp\u003EThe flexibility of the setup varies a lot between the networks. For example, one has a simple button\nto switch their consent box from \u201cAccept \/ More options\u201d to \u201cAccept \/ Decline \/ More options\u201d,\nwhile another took two weeks to fulfil our simple request \u201cwe\u0027re not going live until declining is\njust as simple as accepting\u201d. And none had an option to show the consent banner to everyone,\nnot just people who are in jurisdictions where it\u0027s required by law, unless we implemented\na big chunk ourselves.\u003C\/p\u003E\n\u003Ch2\u003ESumming up, and the future\u003C\/h2\u003E\n\u003Cp\u003EI\u0027m sure we \u003Cem\u003Ecould\u003C\/em\u003E make our setup better in one way or another. There might be a good balance somewhere,\nthere\u0027s probably an ad network that\u0027s the best match for us that we haven\u0027t tried yet.\nBut I don\u0027t want to be spending more time on making monetisation bearable\nthan I spend working on the actual website.\nIt\u0027s already a way more annoying and complicated project than I was expecting it to be\u2026\u003C\/p\u003E\n\u003Cp\u003EWe\u0027re currently onboarding with a fourth company, hopefully to be accomplished this week.\nThey look very promising, so keep fingers crossed that they\u0027re actually what they seem to be\nand that this switch will be the last one \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EWe\u0027re also working on implementing an idea (which was also independently proposed by a user)\nto offer a subscription for a few bucks which would remove all ads for them and the visitors of their profile,\nadd a \u201csupporter\u201d badge in their card, and support the project.\u003C\/p\u003E\n\u003Cp\u003EI really hope that works out, because dealing with the ads setup (even though personally\nI\u0027m mainly helping with the technical side and am shielded from a lot of other bs)\nis really sucking the joy out of creating this passion project.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["ads","adverts","publishers","problems"],"hasMore":true,"image":"https:\/\/avris.it\/image\/frustration-computer-unsplash_small.jpg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/frustration-computer-unsplash_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/frustration-computer-unsplash_mini.jpg\u0022 alt=\u0022illustration: a business woman who is stressed and frustrated\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ENobody likes ads, obviously.\nBut what came as a painful surprise for me is that they don\u0027t just annoy people who see them\n\u2013 but also those who try to monetise their projects.\nIt\u0027s not just a matter of putting a few tags on your page and waiting for a big fat wire transfer.\u003C\/p\u003E\n\u003Cp\u003EThe process is exhausting and I feel the need to rant about it,\nas well as maybe warn people who might be embarking on a similar journey\u2026 so here we go.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/frustration-computer-unsplash_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/frustration-computer-unsplash_mini.jpg\u0022 alt=\u0022illustration: a business woman who is stressed and frustrated\u0022 width=\u0022240\u0022 height=\u0022160\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/unsplash.com\/photos\/bmJAXAz6ads\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Eunsplash.com\/photos\/bmJAXAz6ads\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ENobody likes ads, obviously.\nBut what came as a painful surprise for me is that they don\u0027t just annoy people who see them\n\u2013 but also those who try to monetise their projects.\nIt\u0027s not just a matter of putting a few tags on your page and waiting for a big fat wire transfer.\u003C\/p\u003E\n\u003Cp\u003EThe process is exhausting and I feel the need to rant about it,\nas well as maybe warn people who might be embarking on a similar journey\u2026 so here we go.\u003C\/p\u003E\n\u003Ch2\u003EThe system\u003C\/h2\u003E\n\u003Cp\u003EIn a perfect world, if I create a popular website, I could easily find someone who wants to use\nthat advertising space, they give me money, I add their banner, everyone is happy.\nThe ad is simply relevant to the page content, not the personal info about any particular user.\nIn practice, though, unless you\u0027re a huge company with enough resources, finding advertisers\nand negotiating deals is a tedious task that a random programmer or creator just isn\u0027t equipped to do.\u003C\/p\u003E\n\u003Cp\u003EThat\u0027s why ad networks exist \u2013 they facilitate the process, act as proxies between publishers and advertisers,\nand they take their cut. Cool concept, it really is. The problem, though, is the capitalist approach\nof squeezing the last bits of value from the process, at the cost of user experience, privacy and simplicity.\u003C\/p\u003E\n\u003Cp\u003EWhen I was researching ad networks last year, I only found one that was plain and simple:\n\u003Ca href=\u0022https:\/\/www.ethicalads.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E EthicalAds\u003C\/a\u003E. It would\u0027ve been perfect for my needs, if it wasn\u0027t for the fact\nthat it\u0027s only applicable for websites that target software developers.\nI run a few of those, but they\u0027re too tiny to join the network, while the popular project\nthat me and the rest of the collective wanted to use it for,\n\u003Ca href=\u0022https:\/\/en.pronouns.page\/blog\/why-ads\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Pronouns.Page\u003C\/a\u003E, is for a totally different audience.\u003C\/p\u003E\n\u003Cp\u003ESo it was more a choice of lesser evil than finding an ad network that we\u0027d be totally comfortable with.\nPersonally, I wanted to avoid dealing with Google, but it looks like most networks are strongly relying\non AdSense anyway. We ended up trying three different networks so far, and today I\u0027ve sent\nthe third one a termination notice after having been in talks with the fourth network to switch to them.\nLet\u0027s hope that the fourth time will be the charm \ud83d\ude05\u003C\/p\u003E\n\u003Ch2\u003EHard to test for all users\u003C\/h2\u003E\n\u003Cp\u003EI don\u0027t really wanna name and shame any specific companies, cause it seems like the issues\nare there all over the industry, plus some of our problems \u003Cem\u003Emight\u003C\/em\u003E be stemming from our own inexperience\nin the advertisement world (although that shows how inaccessible the process is to an average publisher).\u003C\/p\u003E\n\u003Cp\u003EOne inherent problem with ad networks is that it\u0027s practically impossible to \u003Cem\u003Efully\u003C\/em\u003E test\nhow they will look on your website. I can put seven empty placeholders on the page,\nas instructed by an expert from the network, and then test it and see that three of them got\nfilled out with ads \u2013 while you load the same page and see all seven.\nI might be shown ads of food delivery companies \u2013 while you get shown some disgusting foot fungus medication ad.\nSome networks let you pick the categories that will and will not be shown, and even review post-factum\nwhich specific ads have been shown to users and block those advertisers for the future \u2013\nbut others give you zero flexibility in that area.\nIn general, algorithms, mathematical models, AI and real-time bidding have more say than humans.\u003C\/p\u003E\n\u003Ch2\u003ETechnical issues\u003C\/h2\u003E\n\u003Cp\u003EBut that\u0027s something that\u0027s, admittedly, hard to avoid in the existing ecosystem.\nOther issues were more avoidable. For example, when we first tried one network, it utterly broke our website.\nThey offered a super simple setup \u2013 just give them access to your Cloudflare and they\u0027ll proxy\neverything, not only adding the necessary ad scripts, but also optimising the traffic and speeding up your page.\nSounds cool, didn\u0027t work. Well, it probably does for most of their publishers, but in case of our\n\u003Ca href=\u0022https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Progressive_web_apps\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PWA\u003C\/a\u003E and some DNS entries their scripts\nwere not expecting, we ended up with no ads and no ability to log in. Not fun.\u003C\/p\u003E\n\u003Cp\u003EYou\u0027d think that adding a script that\u0027s loaded after the rest of the page and should limit its\nimpact for a bunch of clearly defined placeholder shouldn\u0027t really affect the performance of the page much.\nHowever, one network\u0027s scripts were somehow affecting us so much that we ended up switching to another\nmainly for that reason. Another broke an essential feature of the page in a way that was troublesome to debug. \u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After installing Sentry we\u0027ve found out \u003Cem\u003Ejust how much\u003C\/em\u003E JS errors ad scripts produced, geeeez\u2026\u003C\/p\u003E\n\u003Ch2\u003EVolatile and unclear revenue\u003C\/h2\u003E\n\u003Cp\u003EAll the networks looked at our traffic numbers and \u003Cem\u003Epredicted\u003C\/em\u003E monthly revenue in the lower five digits area \u2013\nthe kind of money that we could set up a proper foundation with, run educational campaigns, spread our mission,\nemploy people, make the project a full-time job, not just a side project of passion created in spare time.\nBut in practice it was not just lower, but an order of magnitude lower. Still not bad,\nenough to cover the server, domains, cloud and other maintenance costs,\ndo occasional offline stuff like printing \u003Ca href=\u0022https:\/\/zaimki.pl\/zin\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E our zine\u003C\/a\u003E, creating pins, stickers and flyers\nand handing them out at Herts Pride and Toru\u0144 Pride, and distributing the rest among the contributors\nin a form of volunteer allowance. Basically, it\u0027s not some wild, life-changing money,\nbut it keeps the project running while also rewarding contributors for our time and effort,\nand helping us pay our bills. So we\u0027re really grateful to be in that position.\u003C\/p\u003E\n\u003Cp\u003EWhat\u0027s really bugging us, though, is how volatile and unpredictable the whole thing is.\nOf course we\u0027re expecting ups and downs, but sometimes it can just randomly drop by half\nin the span of two months, with no explanation.\nOne that we did get, I\u0027m not kidding, is that after we\u0027ve spent a lot of time optimising the setup with A\/B testing,\nour ad units performed so well that the system counts the traffic as suspicious and just doesn\u0027t pay for it.\nTheir proposed solutions (adding padding and labels to ads so that users are less likely to click on them accidentally)\ndidn\u0027t help at all. And there\u0027s no one to complain about it, you just have to deal with it.\u003C\/p\u003E\n\u003Cp\u003EThere are so many variables at play, it\u0027s super confusing and unclear. Our current ad network tripled (!)\nthe number of ad impressions they were showing our users compared to the previous company,\nwithout it being proportionally reflected in the revenue or becoming more optimised for user experience with time.\u003C\/p\u003E\n\u003Ch2\u003EUnclear reporting, inflexible setups\u003C\/h2\u003E\n\u003Cp\u003EOne network wouldn\u0027t show us any reporting for the first month, we were completely in the dark.\nAnd once we finally got access to the dashboard, it was way less useful than what other networks provided\n(eg. even trying to figure out which ad unit is which was not easy, because the dashboard\nsimply didn\u0027t show their unique identifiers that are used in the code) \u2013 which we couldn\u0027t have known\nuntil we\u0027re a month in.\u003C\/p\u003E\n\u003Cp\u003EThe flexibility of the setup varies a lot between the networks. For example, one has a simple button\nto switch their consent box from \u201cAccept \/ More options\u201d to \u201cAccept \/ Decline \/ More options\u201d,\nwhile another took two weeks to fulfil our simple request \u201cwe\u0027re not going live until declining is\njust as simple as accepting\u201d. And none had an option to show the consent banner to everyone,\nnot just people who are in jurisdictions where it\u0027s required by law, unless we implemented\na big chunk ourselves.\u003C\/p\u003E\n\u003Ch2\u003ESumming up, and the future\u003C\/h2\u003E\n\u003Cp\u003EI\u0027m sure we \u003Cem\u003Ecould\u003C\/em\u003E make our setup better in one way or another. There might be a good balance somewhere,\nthere\u0027s probably an ad network that\u0027s the best match for us that we haven\u0027t tried yet.\nBut I don\u0027t want to be spending more time on making monetisation bearable\nthan I spend working on the actual website.\nIt\u0027s already a way more annoying and complicated project than I was expecting it to be\u2026\u003C\/p\u003E\n\u003Cp\u003EWe\u0027re currently onboarding with a fourth company, hopefully to be accomplished this week.\nThey look very promising, so keep fingers crossed that they\u0027re actually what they seem to be\nand that this switch will be the last one \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EWe\u0027re also working on implementing an idea (which was also independently proposed by a user)\nto offer a subscription for a few bucks which would remove all ads for them and the visitors of their profile,\nadd a \u201csupporter\u201d badge in their card, and support the project.\u003C\/p\u003E\n\u003Cp\u003EI really hope that works out, because dealing with the ads setup (even though personally\nI\u0027m mainly helping with the technical side and am shielded from a lot of other bs)\nis really sucking the joy out of creating this passion project.\u003C\/p\u003E","words":1477,"readTime":6,"lang":"en"}}},"blog\/technology\/privacy-friendly-location-field":{"key":"blog\/technology\/privacy-friendly-location-field","type":"article","published":true,"meta":{"createdAt":"2022-12-17T11:53:21+01:00","publishedAt":"2022-12-17T11:53:21+01:00","group":null,"category":"blog","subcategory":"technology","slug":"privacy-friendly-location-field"},"content":{"en":{"slug":"privacy-friendly-location-field","title":"Privacy-friendly location field?","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_small.png\u0022 alt=\u0022Screenshot of the profile editor on pronouns.page, the timezone section. Header: \u0022Timezone\u0022. Description: \u0022If you fill out this field, your card will tell people what time it is where you live. Optionally, you can also chose to publish your approximate location.\u0022. Then a select box with list of timezones along with a button \u0022Detect\u0022. Then two switches: \u0022Publish the continent in your card: Europe\u0022 and \u0022Publish the area in your card: Amsterdam\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022147.25099601594\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAALCAYAAAAX+i97AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABq0lEQVQ4ja2UwXLTUAxFjyTbExvKhmEKKR\/A\/\/8Dn8GmTNmUKQw0xLEtiYX7TNJMp5NQrWy9J+m+qyuJuycnmLsf+UQEETklzWIRQUQs\/1X5uL7+Ste1bDZ\/5qIifLxa0zTNQfBL2+OHSGHo7sdPzAwzY5qmGW1lkOARZCZkkiS73UBVGSJCRKKq830z3B0RoW5qMpOIQEWJCESEyZ26rshIIpPMpF2tMNNDhlQVVeX1q25BmwnlAfvUvrk4bk9pW2buAT28V84y84Add\/\/nKwxNmx1iOgcA0hj76SKT51Ryjo6i78lMsq6BPYamX\/1M4zDRvLvg9u6W8EBVSRJBWK8\/nFzwWUC7YW7FA6CFoe+fv9B8ekvvI2pKU9fshgFVnZkRYRxHBHAPPJz3l5cHrPzPtJW2LQz5dsAqwwjMFBGlXa0W3UzuyEPTVIXI48JFI+dY0Vb12AGJmeE+4R6LMIV56vq+J5O5jWcWfwoQ7GkoI\/HR6Yee3\/f3dG1LZNJvt7RdxzROqCmq82hXZtzcfAOBq\/V6SXwuSyVGntrUGUHkSUt8sbKXTrWI4C+Jjve8K9+BKQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_small.png\u0022 alt=\u0022Screenshot of the profile editor on pronouns.page, the timezone section. Header: \u0022Timezone\u0022. Description: \u0022If you fill out this field, your card will tell people what time it is where you live. Optionally, you can also chose to publish your approximate location.\u0022. Then a select box with list of timezones along with a button \u0022Detect\u0022. Then two switches: \u0022Publish the continent in your card: Europe\u0022 and \u0022Publish the area in your card: Amsterdam\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022147.25099601594\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA user suggested adding a timezone field to \u003Ca href=\u0022https:\/\/pronouns.page\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Pronouns.page\u003C\/a\u003E.\nThis website lets people, among other things, create a card with info about how they want to be referred \u2013\ntheir pronouns, names, etc. But it also has some generic fields, like age or links,\nso the team was onboard with the idea of adding some more basic info: not just timezone,\nbut while we\u0027re at it, why not also a location?\u003C\/p\u003E\n\u003Cp\u003EWell, adding a location is not as easy as it seems\u2026\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_big.png\u0022 alt=\u0022Screenshot of the profile editor on pronouns.page, the timezone section. Header: \u0022Timezone\u0022. Description: \u0022If you fill out this field, your card will tell people what time it is where you live. Optionally, you can also chose to publish your approximate location.\u0022. Then a select box with list of timezones along with a button \u0022Detect\u0022. Then two switches: \u0022Publish the continent in your card: Europe\u0022 and \u0022Publish the area in your card: Amsterdam\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022294.50199203187\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAALCAYAAAAX+i97AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABq0lEQVQ4ja2UwXLTUAxFjyTbExvKhmEKKR\/A\/\/8Dn8GmTNmUKQw0xLEtiYX7TNJMp5NQrWy9J+m+qyuJuycnmLsf+UQEETklzWIRQUQs\/1X5uL7+Ste1bDZ\/5qIifLxa0zTNQfBL2+OHSGHo7sdPzAwzY5qmGW1lkOARZCZkkiS73UBVGSJCRKKq830z3B0RoW5qMpOIQEWJCESEyZ26rshIIpPMpF2tMNNDhlQVVeX1q25BmwnlAfvUvrk4bk9pW2buAT28V84y84Add\/\/nKwxNmx1iOgcA0hj76SKT51Ryjo6i78lMsq6BPYamX\/1M4zDRvLvg9u6W8EBVSRJBWK8\/nFzwWUC7YW7FA6CFoe+fv9B8ekvvI2pKU9fshgFVnZkRYRxHBHAPPJz3l5cHrPzPtJW2LQz5dsAqwwjMFBGlXa0W3UzuyEPTVIXI48JFI+dY0Vb12AGJmeE+4R6LMIV56vq+J5O5jWcWfwoQ7GkoI\/HR6Yee3\/f3dG1LZNJvt7RdxzROqCmq82hXZtzcfAOBq\/V6SXwuSyVGntrUGUHkSUt8sbKXTrWI4C+Jjve8K9+BKQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_big.png\u0022 alt=\u0022Screenshot of the profile editor on pronouns.page, the timezone section. Header: \u0022Timezone\u0022. Description: \u0022If you fill out this field, your card will tell people what time it is where you live. Optionally, you can also chose to publish your approximate location.\u0022. Then a select box with list of timezones along with a button \u0022Detect\u0022. Then two switches: \u0022Publish the continent in your card: Europe\u0022 and \u0022Publish the area in your card: Amsterdam\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022294.50199203187\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA user suggested adding a timezone field to \u003Ca href=\u0022https:\/\/pronouns.page\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Pronouns.page\u003C\/a\u003E.\nThis website lets people, among other things, create a card with info about how they want to be referred \u2013\ntheir pronouns, names, etc. But it also has some generic fields, like age or links,\nso the team was onboard with the idea of adding some more basic info: not just timezone,\nbut while we\u0027re at it, why not also a location?\u003C\/p\u003E\n\u003Cp\u003EWell, adding a location is not as easy as it seems\u2026\u003C\/p\u003E\n\u003Ch3\u003EPrevious experiences\u003C\/h3\u003E\n\u003Cp\u003EFirst thing that comes to mind when I think of adding a location field in a profile\nis my experience running \u003Ca href=\u0022https:\/\/teamlocked.men\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E #TeamLocked\u003C\/a\u003E (NSFW).\nI thought I implemented it in a pretty neat way \u2013 but turns out I still couldn\u0027t avoid issues.\u003C\/p\u003E\n\u003Cp\u003EI wanted the data to be structured, not just a free text field \u2013\nthat way I could add some smaller or bigger features around it:\nfrom displaying a little emoji flag next to a country name,\nto allowing people to search users by country and province.\u003C\/p\u003E\n\u003Cp\u003ESo I split it into three levels: \u003Ccode\u003Ecountry\u003C\/code\u003E, \u003Ccode\u003Eprovince\u003C\/code\u003E (which depending on context can mean a state, a province, a wojew\u00f3dztwo, etc.) and \u003Ccode\u003Ecity\u003C\/code\u003E.\nFirst two being a selection from predefined lists, while the last one a free text input \u2013\ncause I\u0027m not going to manage a database of all cities, municipalities and villages in the world \ud83d\ude05\nBut even for countries and provinces, I didn\u0027t want to manually manage that list either \u2013\nthose things change constantly, and I\u0027d rather focus on actually running the page.\nSo I delegated the issue to the United Nations. I wrote a script that fetches the list of countries from\n\u003Ca href=\u0022https:\/\/unece.org\/trade\/cefact\/unlocode-code-list-country-and-territory\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E here\u003C\/a\u003E\nand the list of provinces from \u003Ca href=\u0022https:\/\/unece.org\/trade\/cefact\/UNLOCODE-Download\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E here\u003C\/a\u003E,\nputs it into a neat JSON file, and then gets used to generate the select fields.\u003C\/p\u003E\n\u003Cp\u003EI thought that would be simple and unproblematic\u2026 until someone messaged me,\nangry that my website calls his country \u201cTaiwan, Province of China\u201d.\nWhich is not something I stand for, but I checked and indeed that\u0027s how UNECE describes the country code \u201cTW\u201d.\nIt\u0027s some kind of a weird compromise between recognising Taiwan\u0027s independence and pleasing China.\nLet\u0027s give it a separate country code while still calling it a part of another country\u2026 Ugh\u2026\u003C\/p\u003E\n\u003Cp\u003EI changed my script to rename that item on the fly, but then more of similar issues kept coming.\nI checked if Kosovo is on a list \u2013 nope, despite having an ISO country code (XK) and an emoji flag (\ud83c\uddfd\ud83c\uddf0),\nit isn\u0027t included on UNECE\u0027s list. So I added it. The list of British provinces didn\u0027t include London for some reason.\nNorth Macedonia\u0027s name didn\u0027t get updated for a while, and Czechia\u0027s still isn\u0027t.\nEven though I had an automated script and was delegating responsibility to an international authority \u2013\nI still ended up needing to put in manual effort into it.\u003C\/p\u003E\n\u003Ch3\u003EOn Pronouns.page it gets even more complicated\u003C\/h3\u003E\n\u003Cp\u003EDespite unexpected issues, it ended up working really well in the end.\nBut simply applying a similar approach (well, probably just reusing the very same script)\nwouldn\u0027t really fit Pronouns.page well.\u003C\/p\u003E\n\u003Cp\u003EFirst of all, unlike #TeamLocked, an adult dating website, Pronouns.page is family friendly,\nand a lot of its users are minors. I want to make sure that I don\u0027t create a feature\nthat could inadvertedly cause harm. What if a 13-year-old queer kid sees a free text input field\ncalled \u201clocation\u201d and without thinking much just puts in their full home address?\u003C\/p\u003E\n\u003Cp\u003EWe\u0027d also like to avoid unnecessary political conflicts. Don\u0027t get me wrong, we\u0027re quite a political team,\nbut our mission is to tell enbies (and queers in general) that they\u0027re amazing, that they deserve respect\nand recognition of their identity, and that they have a right to shape their language to meet their needs;\nnot to get tangled in endless discussions over which government has jurisdiction over which piece of land.\nActually, many of us are anarchists, so we\u0027d rather see those governments fall than start showing their\nflags as a location indicator and validating the notion that artificial political borders are the best way\nto describe where you are \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003EThen there\u0027s a question of localisation. In the database we\u0027d of course save the country info\nas a simple country code, but when displaying it \u2013 on a page so heavily focused on language and localisation \u2013\nwe\u0027d have to take into account wheter \u201cDE\u201d should get shown as \u201cGermany\u201d, \u201cDeutschland\u201d, \u201cDuitsland\u201d, \u201cNiemcy\u201d, \u2026\nThere\u0027s databases online that we could use for that, but it\u0027s adding another layer of complexity\u2026\u003C\/p\u003E\n\u003Ch3\u003ELatitude, longitude?\u003C\/h3\u003E\n\u003Cp\u003EThere is a way to describe one\u0027s location that\u0027s super simple and (mainly) independent from politics\n\u2013 just use latitude and longitude, right? Other than the prime meridian being an arbitrary choice,\nit literally just describes one\u0027s location on a globe using simple geometry.\u003C\/p\u003E\n\u003Cp\u003EThere is one problem though, at least for our use case: it\u0027s way too accurate.\nWe want to allow users to share some \u003Cem\u003Every basic\u003C\/em\u003E info about themselves,\nto let others know whether they live nearby or across an ocean \u2013 and not to be their GPS \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003EWhat if we rounded it to the nearest degree, though? Or 5 degrees?\nThat way we\u0027d only know that someone lives within a rectangle of few hundred kilometers by few hundred kilometers,\ngiving us a healthy dose of inaccuracy and therefore privacy.\u003C\/p\u003E\n\u003Cp\u003EWell, I made a little proof of concept of how selecting one\u0027s location would look like,\nand TBH it\u0027s not too nice or intuitive. It\u0027s just a map with some arbitrary rectangle following your mouse,\nit looks confusing when you live near an edge of such a rectangle,\nit would require some fancier projection than Mercator, it wouldn\u0027t be too easy to use on mobile, etc. etc.\u003C\/p\u003E\n\u003Cp\u003EAll of those potential issues can be overcome, of course, but I\u0027d rather settle for something easier,\nif possible.\u003C\/p\u003E\n\u003Ch3\u003ETimezones to the rescue!\u003C\/h3\u003E\n\u003Cp\u003EWell, the answer has been there all along! We were going to implement timezones anyway, right?\nWe can use that for location information. After all, time and space are very closely related!\u003C\/p\u003E\n\u003Cp\u003EThe simplest way to approach storing one\u0027s timezone would be to save the offset, like \u003Ccode\u003EUTC-5\u003C\/code\u003E.\nBut offset \u2260 timezone! My timezone is UTC+1 now, but in March it will switch\nto UTC+2 even if I don\u0027t move anywhere \u2013 thanks DST \ud83d\ude44\nIt\u0027s more accurate to use \u003Ca href=\u0022https:\/\/www.iana.org\/time-zones\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E IANA\u0027s timezones\u003C\/a\u003E,\nin my case \u003Ccode\u003EEurope\/Amsterdam\u003C\/code\u003E \u2013 that way a library can just calculate the proper offset itself.\u003C\/p\u003E\n\u003Cp\u003EBut as you can see, that format already includes some location information!\nWhy don\u0027t we just use it? Here\u0027s how those timezones look on a map:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/tz-database-map_big.png\u0022 alt=\u0022A map of IANA timezones\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022414.375\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAPCAYAAACMa21tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFS0lEQVRIiY2TXWyT1xnHf+c97\/v6K3b8Ecc2cUKKFxzyMQIV0FKgzdSWcjHEtKjahoQ6bZPQtptJu5l2k6na7b6ktbsp2lWp+qnSlDRdN9iglPKRilWsgTRNwMHJcOLYJHZi+33fswsDUUrV5Xd1dM7\/HP2f5\/wfoZRSrAcFiLtLpXAsB6EJNKmt6\/p60b9qs2LlyS6+i3c4wKu3Uviyi+wJS8b8OvGCwC5YYIOjFK0HW2h7qgUEFHOjOEonEO5E1WqUxq8g\/GFkPE65MEMuex5fQxNGcA\/+Bj8VUcOybSIeD4Yu64YuLt4hem2OP8kMmtfke0MXWT54GqYs4p\/20JatkKMJlbPoPOom5Ovi82OTBLYEMJMeQpvDKOWgKhXyr9ykMPU5ye0jyIYAy9kvuLy3xvj8dXqn2ghVvHz0nyR\/PdsB4jY7D13kuTMnuNYX4Ur793HaO5AvPP\/8IKUVZg2b\/mgrqiA5\/lo351o3E9j+T\/7y1hE2BG02dl1gUpaIbNvGxh1Rkk9uIJJuxGw0eP3sFI25US58kaM8KwgXL5HPLjCyq8i0AZWCjyqz1FZSvCj2oVsS\/Y5FpKtE94H9hCdm2HNH8nBnF7qNTTjdwlFa6v\/13TiLXXmOf3yeVGYO0VUCPcOYJ040dIer1lUOtO26\/71CgK9tml8WX6I\/2kWmtZdA+TnM6X\/h+TRIprSV5FSU4u4RfKe9dNsBZKrIlt2jBJofJqQ5bDz4C4xAI5Zjobuk64EM7ejwc8IpYL1Xxdng4pJM0709RP9jLWhaPdkKqFo2piZwF8f5TaIFW6a4UV1iZG4TkVgjO1eynE+Os+l8J\/OhRUoD1zj6\/if8YcdP6A70EI9P0N48gK7VPeiajq6UAgXKstHMesaDusGv2w5wPJ7iUIOfvT0C3\/UJEAmgHj4BuHTJ23+fobr8Een4B\/zj9zMU0rNkYv0MnXia3r5T\/DxkUkqP41tJMCO3Me+ZIKZJvrE5TWvT3rulrSLujb1Ts9EMef9AAfPlGiOTC2wtXMaX6mYuZ9O3JYmhGwCUShbDFz9Azw4z1NTG8IVH+dV4ln0dNzmX1tjfsY+H+rYzNvoSydTTvLtcJTP6MT\/Yt58pVWK3vw2raqObEqtSRXeZyMHBwcF7YRBCrDoFvIakN+qloTnGOxOnOfXmMuVinkQsgcejYZoaicZWfAtuvN0JfJcX6DMvcfObOiu9Gt\/qPoQmBMKM4nc3U7azBDUPYxmBmV8hGQmAFDg1G6dmgabQlFLYtnO\/cY5tr22hENwow1tnkxysvEfx1A1+d\/gMN05eByAUcrF5\/5MMtPTT6WnFY3xGeNHFD5M\/o2bV6prgBqTHxdZwmtnYLNWxJRpPFJl750PGfvQsY1cmwHTh2KDPV+YIyiBoktv\/LdPQYOD1yTWmusIBNu2MMaTG2fU3H7d2Pku5J7FGI4VGoxnhZPTHeGJJZiovc8R1GBRosv6eW7g50jyAfXiRz66+zDF3nkNPfZuU0c5CNoc7aaKHzDBSkyilaIp6Uc5qyJSqjzXAH3e1M\/TT3Sw0d3LkkRY6W\/0PTGdvMoh7WJB64iHcfh3TMNcK7r61+O9juG5N0rO0jdPh14i4HyeSbMeQGqh1UspMqj9\/51V1+8zwmn3HcZRSjlJKqWrZUblr1Qfu1jWrVIvTqro0r5auFtVvR95QNaemHOWosflPlHBsSwlNPlDtl5k+dQ6RmSc28Ay61\/ha7b3OKuWgHAtNM1Zb\/SXKTg2vZnBraZImT2J17P8f1bJNPr9CPOkDoOZYKEdh6l9vbj04SqHdNfw\/\/2J3PxbskhoAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/tz-database-map_big.png\u0022 alt=\u0022A map of IANA timezones\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022414.375\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/commons.wikimedia.org\/wiki\/File:2017a.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        commons.wikimedia.org\/wiki\/File:2017a.png\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt looks exactly like what we need! It splits the Earth into chunks that look less arbitrary and clunky\nthan some purely geometric lat\/long rectangles. Chunks that are big enough not to give away too much of someone\u0027s location,\nbut small enough to give a pretty good understanding of how far away from you someone is.\nSure, in many cases those splits follow country borders, but at least the assocciated labels focus mostly\non cities and geographical names rather than political ones.\u003C\/p\u003E\n\u003Ch2\u003EImplementing the feature\u003C\/h2\u003E\n\u003Cp\u003ESo, let\u0027s get to actually implementing the timezone field! It ended up being way simpler than I imagined.\nHere\u0027s how the form looks:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_big.png\u0022 alt=\u0022Screenshot of the profile editor on pronouns.page, the timezone section. Header: \u0022Timezone\u0022. Description: \u0022If you fill out this field, your card will tell people what time it is where you live. Optionally, you can also chose to publish your approximate location.\u0022. Then a select box with list of timezones along with a button \u0022Detect\u0022. Then two switches: \u0022Publish the continent in your card: Europe\u0022 and \u0022Publish the area in your card: Amsterdam\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022294.50199203187\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAALCAYAAAAX+i97AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABq0lEQVQ4ja2UwXLTUAxFjyTbExvKhmEKKR\/A\/\/8Dn8GmTNmUKQw0xLEtiYX7TNJMp5NQrWy9J+m+qyuJuycnmLsf+UQEETklzWIRQUQs\/1X5uL7+Ste1bDZ\/5qIifLxa0zTNQfBL2+OHSGHo7sdPzAwzY5qmGW1lkOARZCZkkiS73UBVGSJCRKKq830z3B0RoW5qMpOIQEWJCESEyZ26rshIIpPMpF2tMNNDhlQVVeX1q25BmwnlAfvUvrk4bk9pW2buAT28V84y84Add\/\/nKwxNmx1iOgcA0hj76SKT51Ryjo6i78lMsq6BPYamX\/1M4zDRvLvg9u6W8EBVSRJBWK8\/nFzwWUC7YW7FA6CFoe+fv9B8ekvvI2pKU9fshgFVnZkRYRxHBHAPPJz3l5cHrPzPtJW2LQz5dsAqwwjMFBGlXa0W3UzuyEPTVIXI48JFI+dY0Vb12AGJmeE+4R6LMIV56vq+J5O5jWcWfwoQ7GkoI\/HR6Yee3\/f3dG1LZNJvt7RdxzROqCmq82hXZtzcfAOBq\/V6SXwuSyVGntrUGUHkSUt8sbKXTrWI4C+Jjve8K9+BKQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_big.png\u0022 alt=\u0022Screenshot of the profile editor on pronouns.page, the timezone section. Header: \u0022Timezone\u0022. Description: \u0022If you fill out this field, your card will tell people what time it is where you live. Optionally, you can also chose to publish your approximate location.\u0022. Then a select box with list of timezones along with a button \u0022Detect\u0022. Then two switches: \u0022Publish the continent in your card: Europe\u0022 and \u0022Publish the area in your card: Amsterdam\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022294.50199203187\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ETurns out we can just use a built-in JavaScript feature to list all the IANA timezone codes:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.timezones = \u003Cspan class=\u0022hljs-built_in\u0022\u003EIntl\u003C\/span\u003E.supportedValuesOf(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027timeZone\u0027\u003C\/span\u003E);\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EI\u0027m already using \u003Ca href=\u0022https:\/\/moment.github.io\/luxon\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Luxon\u003C\/a\u003E in the project,\nso let\u0027s leverage its timezone features to add the \u201cDetect automatically\u201d button:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E.timezone = DateTime.local().zone.name;\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EYup, that\u0027s it. Well, setting aside all the boring stuff,\nlike migrations, server-side handling, autocomplete component, etc. \u2013\nbut the timezone part itself was incredibly easy!\u003C\/p\u003E\n\u003Cp\u003EI also added switches to let users choose whether their continent\/ocean and location field should be explicitly displayed on their card\n(the full timezone code needs to be published by the API anyway, in order to correctly calculate the offset,\nbut we can decide whether to show it in an easily accessible way).\u003C\/p\u003E\n\u003Cp\u003EAnd here\u0027s how it shows up in the profile:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-card_big.png\u0022 alt=\u0022Screenshot of @andrea card on pronouns.page. The timezone section says: \u0022It\u0027s 1:36 PM on a Saturday in my timezone (UTC+01:00)\u0022, next line: \u0022Europe \/ Amsterdam\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022562.82958199357\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAVCAYAAAAuJkyQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEC0lEQVRIiZ2WS29bVRDHf+d1H\/b1tZM4TUp4SJRuEF2wAKniG7DjS\/E9kGCNhBBrVrACNoCE1KYJUVtqkrRNm\/s8DxbObW3HdlJmeXVm5j+\/MzPnirZtA4C1Lc550jTl\/5i1FiEEQoi570IIlFJX+ocQcM6hAY4O7\/PTt1\/zfg82737O3u07nJyckqYpzjmUkpgoYpjnKwNKKVcmCiFcErpo3vtpHICHR\/uYsiSXge+++YqiKGnaBuccVVXx8vycoijWBlxHIYSw1rcTDUwJPTj8m8ODfcZ6h5O6wf76hBc\/\/M55pHBli1ASYRT\/1C13vvwCncWXgq4jcJWgjg6AaNs2VGXJHz\/\/yNu5Yvuju6g0vxLxrHXX5ZxbmVxrvVKsc25e0GQyoShL4ijGGE0I0ybX2tA0DUorCDP3LCXOOXq9lPF4\/Er8n799z3u7nxGcR2iFbxwqh5OjX9ja+hTdi6ibBlqPURqkwGz15orQAAGITEQInqqqSHs99nb2rkVnlmSSvovOEoJ1yEhT24ZnZyU2\/gSdxYjEMHlyzM5GjhkkeB8IzoN8HUN3FVssSRxzXhS0Tcvx8TF1XSOlJATo9VJevHhJmiY0TYuUgvF4TBRFF+zh7HnMW9sO11pcbSETqMixjccWNSYxjHfHRB6aZyVBBHSeICM9L2g0HF4kDoxGozkC3fT4EBgMBh0XICz0RSBtnuCrG9OpcZ6X1XMmBwfc+uBj7KMjqr9Kklu3cULgCZhROidGCDHtodPTp7S2RStFWVYEAkmSYFtLCB4hJNpovPcEH\/DekQ0GKKVxzpHEMb1eurRJZ01K+apw7\/2lARBCTAk554iMuaCQ0baWQCCKIozRl6h1wZfZdcZ\/du8s+mmAPB\/gL1RrpUiSCydAL1l4V60EIcTS8e+EzO6dS77dW7Yu+KKAVXRmE6+6tmViZ+NrgEePH5MPBpyePkUbDSGQD4dk\/f6ld8g5x71798myjBCmjW2MpqprtjY3ieP40vn9\/Qfs7e0x+XdCv9dne3u8shgNsDkcESUx1rppMAFqBQVjDKPhkOFoiHMOax1t25D1+0ynb56EtZad3R0CYenjvEhfAzQHzwh5gq4tyW6O7s+\/VR2lzlk+LKieOoSU6DQif2draaLuaorTM0ZxhjqriW8M5s4sJZR\/eHMpjVWCyhuaIliMNty8ubHUpztbFAVFUZLrHvFFsd55cAGpJd46pFYIJV8Luo7NViOFpKgK5Jpp684HIPiALVvseU2bGKRWSARCS4L1ROMM9SaCFtEOBhlxHJFl2Vo\/KSWyaYi8RyUaYRRCCqKNHtqYpT7XFjQ7bfmaP8dFP50kpBs50ThDmtc7bdVf5BvtoWU76Sqr63rp9+4ZWbT\/AHQe\/FJjtHuyAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-card_big.png\u0022 alt=\u0022Screenshot of @andrea card on pronouns.page. The timezone section says: \u0022It\u0027s 1:36 PM on a Saturday in my timezone (UTC+01:00)\u0022, next line: \u0022Europe \/ Amsterdam\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022562.82958199357\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe clock is of course dynamic. I used Luxon\u0027s built-in localisation to be able to show for example\n\u201c1:35 PM\u201d on the English version while Polish says \u201c13:35\u201d. I also had to remember to include weekday,\nso that it\u0027s clearer if someone is a day ahead or behind you. One nice extra touch is that since\n\u003Ca href=\u0022https:\/\/fontawesome.com\/v5\/search?q=globe\u0026o=r\u0026s=light\u0026f=classic\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E FontAwesome has multiple \u201cglobe\u201d icons\u003C\/a\u003E,\neach focusing on a different continent, I could even make the icon dynamic \ud83d\ude09\u003C\/p\u003E\n\u003Ch3\u003ESummary\u003C\/h3\u003E\n\u003Cp\u003EDifferent use cases might require different solutions, but if yours is similar to ours\n\u2013 relatively low accuracy by design, hard to abuse, easy to localise, etc. \u2013\nkeep in mind that timezones could be super helpful.\u003C\/p\u003E\n\u003Cp\u003EIANA timezone encodes so much information: if you know it,\nyou know both approximately \u003Cstrong\u003Ewhere someone is\u003C\/strong\u003E and also \u003Cstrong\u003Ewhat time\u003C\/strong\u003E is it there.\nPretty cool, huh?\u003C\/p\u003E\n\u003Ch3\u003EUpdate\u003C\/h3\u003E\n\u003Cp\u003ETurns out there are still problems with the IANA timezones database.\nKind of expectedly, huh? I knew life can\u0027t be too easy,\nthere\u0027s definitely gonna be controversies around city names,\nI\u0027m just excpecting that there would be \u003Cem\u003Efewer\u003C\/em\u003E than with countries.\u003C\/p\u003E\n\u003Cp\u003ESo the first one we found is this:\nfor the capital of Ukraine IANA uses\u2026 the Russian spelling \ud83e\udd26 (\u003Cdel\u003EKiev\u003C\/del\u003E).\nWe\u0027ve replaced it with the more appropriate one: Kyiv.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["timezone","location","privacy","card","profile","luxon"],"hasMore":true,"image":"https:\/\/avris.it\/image\/zaimki-timezone-editor_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_mini.png\u0022 alt=\u0022Screenshot of the profile editor on pronouns.page, the timezone section. Header: \u0022Timezone\u0022. Description: \u0022If you fill out this field, your card will tell people what time it is where you live. Optionally, you can also chose to publish your approximate location.\u0022. Then a select box with list of timezones along with a button \u0022Detect\u0022. Then two switches: \u0022Publish the continent in your card: Europe\u0022 and \u0022Publish the area in your card: Amsterdam\u0022\u0022 width=\u0022240\u0022 height=\u002273.625498007968\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA user suggested adding a timezone field to \u003Ca href=\u0022https:\/\/pronouns.page\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Pronouns.page\u003C\/a\u003E.\nThis website lets people, among other things, create a card with info about how they want to be referred \u2013\ntheir pronouns, names, etc. But it also has some generic fields, like age or links,\nso the team was onboard with the idea of adding some more basic info: not just timezone,\nbut while we\u0027re at it, why not also a location?\u003C\/p\u003E\n\u003Cp\u003EWell, adding a location is not as easy as it seems\u2026\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_mini.png\u0022 alt=\u0022Screenshot of the profile editor on pronouns.page, the timezone section. Header: \u0022Timezone\u0022. Description: \u0022If you fill out this field, your card will tell people what time it is where you live. Optionally, you can also chose to publish your approximate location.\u0022. Then a select box with list of timezones along with a button \u0022Detect\u0022. Then two switches: \u0022Publish the continent in your card: Europe\u0022 and \u0022Publish the area in your card: Amsterdam\u0022\u0022 width=\u0022240\u0022 height=\u002273.625498007968\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EA user suggested adding a timezone field to \u003Ca href=\u0022https:\/\/pronouns.page\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Pronouns.page\u003C\/a\u003E.\nThis website lets people, among other things, create a card with info about how they want to be referred \u2013\ntheir pronouns, names, etc. But it also has some generic fields, like age or links,\nso the team was onboard with the idea of adding some more basic info: not just timezone,\nbut while we\u0027re at it, why not also a location?\u003C\/p\u003E\n\u003Cp\u003EWell, adding a location is not as easy as it seems\u2026\u003C\/p\u003E\n\u003Ch3\u003EPrevious experiences\u003C\/h3\u003E\n\u003Cp\u003EFirst thing that comes to mind when I think of adding a location field in a profile\nis my experience running \u003Ca href=\u0022https:\/\/teamlocked.men\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E #TeamLocked\u003C\/a\u003E (NSFW).\nI thought I implemented it in a pretty neat way \u2013 but turns out I still couldn\u0027t avoid issues.\u003C\/p\u003E\n\u003Cp\u003EI wanted the data to be structured, not just a free text field \u2013\nthat way I could add some smaller or bigger features around it:\nfrom displaying a little emoji flag next to a country name,\nto allowing people to search users by country and province.\u003C\/p\u003E\n\u003Cp\u003ESo I split it into three levels: \u003Ccode\u003Ecountry\u003C\/code\u003E, \u003Ccode\u003Eprovince\u003C\/code\u003E (which depending on context can mean a state, a province, a wojew\u00f3dztwo, etc.) and \u003Ccode\u003Ecity\u003C\/code\u003E.\nFirst two being a selection from predefined lists, while the last one a free text input \u2013\ncause I\u0027m not going to manage a database of all cities, municipalities and villages in the world \ud83d\ude05\nBut even for countries and provinces, I didn\u0027t want to manually manage that list either \u2013\nthose things change constantly, and I\u0027d rather focus on actually running the page.\nSo I delegated the issue to the United Nations. I wrote a script that fetches the list of countries from\n\u003Ca href=\u0022https:\/\/unece.org\/trade\/cefact\/unlocode-code-list-country-and-territory\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E here\u003C\/a\u003E\nand the list of provinces from \u003Ca href=\u0022https:\/\/unece.org\/trade\/cefact\/UNLOCODE-Download\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E here\u003C\/a\u003E,\nputs it into a neat JSON file, and then gets used to generate the select fields.\u003C\/p\u003E\n\u003Cp\u003EI thought that would be simple and unproblematic\u2026 until someone messaged me,\nangry that my website calls his country \u201cTaiwan, Province of China\u201d.\nWhich is not something I stand for, but I checked and indeed that\u0027s how UNECE describes the country code \u201cTW\u201d.\nIt\u0027s some kind of a weird compromise between recognising Taiwan\u0027s independence and pleasing China.\nLet\u0027s give it a separate country code while still calling it a part of another country\u2026 Ugh\u2026\u003C\/p\u003E\n\u003Cp\u003EI changed my script to rename that item on the fly, but then more of similar issues kept coming.\nI checked if Kosovo is on a list \u2013 nope, despite having an ISO country code (XK) and an emoji flag (\ud83c\uddfd\ud83c\uddf0),\nit isn\u0027t included on UNECE\u0027s list. So I added it. The list of British provinces didn\u0027t include London for some reason.\nNorth Macedonia\u0027s name didn\u0027t get updated for a while, and Czechia\u0027s still isn\u0027t.\nEven though I had an automated script and was delegating responsibility to an international authority \u2013\nI still ended up needing to put in manual effort into it.\u003C\/p\u003E\n\u003Ch3\u003EOn Pronouns.page it gets even more complicated\u003C\/h3\u003E\n\u003Cp\u003EDespite unexpected issues, it ended up working really well in the end.\nBut simply applying a similar approach (well, probably just reusing the very same script)\nwouldn\u0027t really fit Pronouns.page well.\u003C\/p\u003E\n\u003Cp\u003EFirst of all, unlike #TeamLocked, an adult dating website, Pronouns.page is family friendly,\nand a lot of its users are minors. I want to make sure that I don\u0027t create a feature\nthat could inadvertedly cause harm. What if a 13-year-old queer kid sees a free text input field\ncalled \u201clocation\u201d and without thinking much just puts in their full home address?\u003C\/p\u003E\n\u003Cp\u003EWe\u0027d also like to avoid unnecessary political conflicts. Don\u0027t get me wrong, we\u0027re quite a political team,\nbut our mission is to tell enbies (and queers in general) that they\u0027re amazing, that they deserve respect\nand recognition of their identity, and that they have a right to shape their language to meet their needs;\nnot to get tangled in endless discussions over which government has jurisdiction over which piece of land.\nActually, many of us are anarchists, so we\u0027d rather see those governments fall than start showing their\nflags as a location indicator and validating the notion that artificial political borders are the best way\nto describe where you are \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003EThen there\u0027s a question of localisation. In the database we\u0027d of course save the country info\nas a simple country code, but when displaying it \u2013 on a page so heavily focused on language and localisation \u2013\nwe\u0027d have to take into account wheter \u201cDE\u201d should get shown as \u201cGermany\u201d, \u201cDeutschland\u201d, \u201cDuitsland\u201d, \u201cNiemcy\u201d, \u2026\nThere\u0027s databases online that we could use for that, but it\u0027s adding another layer of complexity\u2026\u003C\/p\u003E\n\u003Ch3\u003ELatitude, longitude?\u003C\/h3\u003E\n\u003Cp\u003EThere is a way to describe one\u0027s location that\u0027s super simple and (mainly) independent from politics\n\u2013 just use latitude and longitude, right? Other than the prime meridian being an arbitrary choice,\nit literally just describes one\u0027s location on a globe using simple geometry.\u003C\/p\u003E\n\u003Cp\u003EThere is one problem though, at least for our use case: it\u0027s way too accurate.\nWe want to allow users to share some \u003Cem\u003Every basic\u003C\/em\u003E info about themselves,\nto let others know whether they live nearby or across an ocean \u2013 and not to be their GPS \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003EWhat if we rounded it to the nearest degree, though? Or 5 degrees?\nThat way we\u0027d only know that someone lives within a rectangle of few hundred kilometers by few hundred kilometers,\ngiving us a healthy dose of inaccuracy and therefore privacy.\u003C\/p\u003E\n\u003Cp\u003EWell, I made a little proof of concept of how selecting one\u0027s location would look like,\nand TBH it\u0027s not too nice or intuitive. It\u0027s just a map with some arbitrary rectangle following your mouse,\nit looks confusing when you live near an edge of such a rectangle,\nit would require some fancier projection than Mercator, it wouldn\u0027t be too easy to use on mobile, etc. etc.\u003C\/p\u003E\n\u003Cp\u003EAll of those potential issues can be overcome, of course, but I\u0027d rather settle for something easier,\nif possible.\u003C\/p\u003E\n\u003Ch3\u003ETimezones to the rescue!\u003C\/h3\u003E\n\u003Cp\u003EWell, the answer has been there all along! We were going to implement timezones anyway, right?\nWe can use that for location information. After all, time and space are very closely related!\u003C\/p\u003E\n\u003Cp\u003EThe simplest way to approach storing one\u0027s timezone would be to save the offset, like \u003Ccode\u003EUTC-5\u003C\/code\u003E.\nBut offset \u2260 timezone! My timezone is UTC+1 now, but in March it will switch\nto UTC+2 even if I don\u0027t move anywhere \u2013 thanks DST \ud83d\ude44\nIt\u0027s more accurate to use \u003Ca href=\u0022https:\/\/www.iana.org\/time-zones\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E IANA\u0027s timezones\u003C\/a\u003E,\nin my case \u003Ccode\u003EEurope\/Amsterdam\u003C\/code\u003E \u2013 that way a library can just calculate the proper offset itself.\u003C\/p\u003E\n\u003Cp\u003EBut as you can see, that format already includes some location information!\nWhy don\u0027t we just use it? Here\u0027s how those timezones look on a map:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/tz-database-map_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/tz-database-map_mini.png\u0022 alt=\u0022A map of IANA timezones\u0022 width=\u0022240\u0022 height=\u0022103.59375\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/commons.wikimedia.org\/wiki\/File:2017a.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Ecommons.wikimedia.org\/wiki\/File:2017a.png\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt looks exactly like what we need! It splits the Earth into chunks that look less arbitrary and clunky\nthan some purely geometric lat\/long rectangles. Chunks that are big enough not to give away too much of someone\u0027s location,\nbut small enough to give a pretty good understanding of how far away from you someone is.\nSure, in many cases those splits follow country borders, but at least the assocciated labels focus mostly\non cities and geographical names rather than political ones.\u003C\/p\u003E\n\u003Ch2\u003EImplementing the feature\u003C\/h2\u003E\n\u003Cp\u003ESo, let\u0027s get to actually implementing the timezone field! It ended up being way simpler than I imagined.\nHere\u0027s how the form looks:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-editor_mini.png\u0022 alt=\u0022Screenshot of the profile editor on pronouns.page, the timezone section. Header: \u0022Timezone\u0022. Description: \u0022If you fill out this field, your card will tell people what time it is where you live. Optionally, you can also chose to publish your approximate location.\u0022. Then a select box with list of timezones along with a button \u0022Detect\u0022. Then two switches: \u0022Publish the continent in your card: Europe\u0022 and \u0022Publish the area in your card: Amsterdam\u0022\u0022 width=\u0022240\u0022 height=\u002273.625498007968\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ETurns out we can just use a built-in JavaScript feature to list all the IANA timezone codes:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Ethis.timezones = Intl.supportedValuesOf(\u0027timeZone\u0027);\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EI\u0027m already using \u003Ca href=\u0022https:\/\/moment.github.io\/luxon\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Luxon\u003C\/a\u003E in the project,\nso let\u0027s leverage its timezone features to add the \u201cDetect automatically\u201d button:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Ethis.timezone = DateTime.local().zone.name;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EYup, that\u0027s it. Well, setting aside all the boring stuff,\nlike migrations, server-side handling, autocomplete component, etc. \u2013\nbut the timezone part itself was incredibly easy!\u003C\/p\u003E\n\u003Cp\u003EI also added switches to let users choose whether their continent\/ocean and location field should be explicitly displayed on their card\n(the full timezone code needs to be published by the API anyway, in order to correctly calculate the offset,\nbut we can decide whether to show it in an easily accessible way).\u003C\/p\u003E\n\u003Cp\u003EAnd here\u0027s how it shows up in the profile:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/zaimki-timezone-card_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/zaimki-timezone-card_mini.png\u0022 alt=\u0022Screenshot of @andrea card on pronouns.page. The timezone section says: \u0022It\u0027s 1:36 PM on a Saturday in my timezone (UTC+01:00)\u0022, next line: \u0022Europe \/ Amsterdam\u0022\u0022 width=\u0022240\u0022 height=\u0022140.70739549839\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe clock is of course dynamic. I used Luxon\u0027s built-in localisation to be able to show for example\n\u201c1:35 PM\u201d on the English version while Polish says \u201c13:35\u201d. I also had to remember to include weekday,\nso that it\u0027s clearer if someone is a day ahead or behind you. One nice extra touch is that since\n\u003Ca href=\u0022https:\/\/fontawesome.com\/v5\/search?q=globe\u0026o=r\u0026s=light\u0026f=classic\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E FontAwesome has multiple \u201cglobe\u201d icons\u003C\/a\u003E,\neach focusing on a different continent, I could even make the icon dynamic \ud83d\ude09\u003C\/p\u003E\n\u003Ch3\u003ESummary\u003C\/h3\u003E\n\u003Cp\u003EDifferent use cases might require different solutions, but if yours is similar to ours\n\u2013 relatively low accuracy by design, hard to abuse, easy to localise, etc. \u2013\nkeep in mind that timezones could be super helpful.\u003C\/p\u003E\n\u003Cp\u003EIANA timezone encodes so much information: if you know it,\nyou know both approximately \u003Cstrong\u003Ewhere someone is\u003C\/strong\u003E and also \u003Cstrong\u003Ewhat time\u003C\/strong\u003E is it there.\nPretty cool, huh?\u003C\/p\u003E\n\u003Ch3\u003EUpdate\u003C\/h3\u003E\n\u003Cp\u003ETurns out there are still problems with the IANA timezones database.\nKind of expectedly, huh? I knew life can\u0027t be too easy,\nthere\u0027s definitely gonna be controversies around city names,\nI\u0027m just excpecting that there would be \u003Cem\u003Efewer\u003C\/em\u003E than with countries.\u003C\/p\u003E\n\u003Cp\u003ESo the first one we found is this:\nfor the capital of Ukraine IANA uses\u2026 the Russian spelling \ud83e\udd26 (\u003Cdel\u003EKiev\u003C\/del\u003E).\nWe\u0027ve replaced it with the more appropriate one: Kyiv.\u003C\/p\u003E","words":1554,"readTime":7,"lang":"en"}}},"blog\/technology\/pronouns-page-migration":{"key":"blog\/technology\/pronouns-page-migration","type":"article","published":true,"meta":{"createdAt":"2022-08-13T10:27:16+02:00","publishedAt":"2022-08-13T10:27:16+02:00","group":null,"category":"blog","subcategory":"technology","slug":"pronouns-page-migration"},"content":{"en":{"slug":"pronouns-page-migration","title":"Migrating Pronouns.page to a new server \u2013 a success story","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration_small.png\u0022 alt=\u0022Terminal with `ls -lah \/etc\/nginx\/sites-enabled\/` executed on the new server\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022273.17773788151\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHjElEQVRIiT2Uy28kVxnFf\/dVVd3V7Xbbbj9mPA9lwgx5KORBkGADkVBYsWHDgj0S\/xMSyg4JiSXZICEkpAwRRAkkkSbJTDzjGbvtdr+7Hrdu3XtZOGJ3Ft\/ifEfnd8Rvf\/ebuDfapw0z8v4hril48Op7yO4hn60eENYnrJ\/8lV5SoE2PuraU8yly9FPc3s+4dahZF4EffT\/h6ekZcfOYd1\/f5V\/\/\/pDpeMb+\/iEnpx\/z4vyUpm1pW08vPcRFyfxqzPHRAcv1nBenV\/S3+sjj27sYAwRJr284uDlApyt++NZr\/PIt6BZ\/49bBJaO9c5Qf44tT2rbFzT8nSQJXyxap4OGnT9m8eMh+Hz788C98\/eWnvHTnJheTR0gNWzsddkbbpGmf8dkljx99SfCOrR3JerVhZz\/n8HgL8cGf\/hAfP\/oM79d0ejvs7r2E0iXvvvE+g6TlopqiI0ipqasI0dC2noYuTg5RJqV1DdhLMt2SaiiqBSEEunmXGD3aKFzraNuAEIrFbM4Hf\/w9g70u2aClrgSLyw0v3b2B7u9lbC9Tri4v6I0Cs1nJrePX+MdHf2a+tNRNTWNLtO8QgyQEkEIRkTi1Q2E9Irb4ekaaaIx0rFdzhIQQA1JGhFQ45zFaI4TAh0iaZ1hbcv5lSZoa5lclNOfo8eQjekMN8ojFZIlSNVfTzylWkk8efsNqWRFji0ki3Wyb9bpksamwMSWYAUoItEmQCIgt0k4QOIrNkqJaUJYWJRU+BCBCBG0099+8i0kU0+mcLNUs50vyziF6Pq7Z2x9weJgSrCNET7GCr796zmJeMhh0mc3mRAKDgcBYQW9vh57uEpHkFHR6QyBjvZjg0wFVMWddrIFImqT40CKRxBiIRBrXoGRL2wjSRJHnCYQhQgnkfLrh\/OyKYt1wfHePZyeX7Ix6ON9gbU1RVCijaKwnRk+SKoQIOGGp7JRiNUWFKdFO6aiSTuLodhVaR5TSJJkhSRPSzCCVIEk1Uko6\/QHKaLrdLZLegAdvvEpnu48UMmE4GCKFpFhZ3nv\/Lfr9Lu\/\/4m1u3RnRzTOMUoQg8D4CAZMAtDjvCd4hgkcLi1ICKUAKiXMtbeuwlaWxjmJd4mxLY1uMMQyGQ97+8TtsDbYZ7HSpqpI8z9GziyWvvHyHTh7QRtK4AmUMp08XiChITEJNTZJqXBMoqwa5lSFiiypWZHkfrQ3GaKwVnJ2cM7m6wvtA8IHgI5GISQyNdYgoCS6gXMn0cgyh4ezxhsn4goPjA+T+1i4yJFxdFIwvllSlp9PNyDoK2ziKoqQsK7RSpJlBxEi5LkiznIqUxWJxnYaPaC3Y2ztgZ2cP7wEk2iiUkogAqU7o5zkCgWscD\/\/+T87HY6bjCSB4\/uQ5crQ\/JOsIOmmXjuhBVEjlefD6DbYGXdI0wdYNIgR6iWE4yOl2UlxjESrBR0FjW2zlcA20rcfojLybE2LEtYEQoPUB17YsVisqW\/Of\/z5GJwmL2YrGO4SUDHYH6M4g4cnJOWcnlxzdHZHlCTQSdEGInjQz1LUleMf+\/pAkkUgfSI0iz6BZt1jbkmUZTVPTWItvW5bzFSFeo+7bgBACpSXee4SExWRFt58htGS4t40tGqqNRU+vKuqN5+jOiNWsQqqEJgmsi4rzyQRtNPu3B0ibsFkXCOEJIeKaAsqSfi8hxIr5wuK9Zz7bsF5vEAhEEN+tsyDGa2PBB6QSDPa20MZQbWomz2ZY5zA6Qe8e5WxWghzJbq\/HctNwdrrEaM35ySWuaZEi0skMna5hvbHEAN1eh+WiJARP3kuRSuJsy3pT09gW7z2Na\/5vAiDNEqQQxBBZnJXXj7UtPnrqqqHTydCLieP27veYTqfcOBhRzL5gmAQeffsVSkZMxyAEGKOp6oCSCdIIWteitcB7CVFgqxbvA1JKtJJsD7ao64rGNTSNp7EOax2DrT4hBPK8Q6dvWC0qBBo\/9FSrGj0\/eY4bj5mu1yyutpGpoHKOu\/fu8vEnT2gaD1yjK5UmxpYQI0SJENcURRQq6UPrkH4DwtOGljRLSRKN1Q1GS6xtKYqCLMu4\/\/IDIoIxY549fcaDB\/dJb2n00e0hmyIw6kk6WwPybp\/FckpvsI3SGhMlUqnvYg\/XOkSQCUprhJToJMP5DK389Y3weB\/wPhKRmCS5LrVSNE2DlJKTp89ompbdnV3u338FISRSpuhWSnYPc4oNEB2XkwsObgxIsoxf\/frnNFWLFAlNY1EmYssGZbZxrSGkR2j3BdnOT6jbXUy4oF4+wlYT5rMLlFTUNazWNVeTSxKtGA1zhMr59vQF3V4P1zpenDwFBKP9fbT3grpuCd6jM0OeSDrdjBhhNDrAWUldlQihSIymrjWrlSXtDunffBMZ7hHEAQedDsPOIdVin8nlI5z1LFdrfvD2K3QzxcXFjLKqsGXJarHg8GBAXTckMuX2zXd49M0TJpcXyBs39xEqkA\/3qW2FMR2E3EapXUKbsNmU33UowYcuIUjqusQ1NWVRE+jh3RJvp0gRqMorvvnqMT4qujmsFjOsrTi+dUyWKo5uDullPQ4OhmiTEmQgUjDYSrh37w7\/A2YLLsjoRLMdAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration_small.png\u0022 alt=\u0022Terminal with `ls -lah \/etc\/nginx\/sites-enabled\/` executed on the new server\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022273.17773788151\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWhen it comes to \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/DevOps\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DevOps\u003C\/a\u003E, I\u0027m just the \u201cdev\u201d.\nI write code, but I\u0027d rather have someone else worry about making sure it keeps running as intended.\nI manage my personal VPS, I manage some servers at work, but I wouldn\u0027t call myself an expert in that area at all.\nSo I\u0027m super proud of myself and how well it went when I migrated a big project to a new machine \ud83d\ude0a\nThe downtime was just 15 minutes! Here\u0027s the story, if you\u0027re interested.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration_big.png\u0022 alt=\u0022Terminal with `ls -lah \/etc\/nginx\/sites-enabled\/` executed on the new server\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022546.35547576302\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHjElEQVRIiT2Uy28kVxnFf\/dVVd3V7Xbbbj9mPA9lwgx5KORBkGADkVBYsWHDgj0S\/xMSyg4JiSXZICEkpAwRRAkkkSbJTDzjGbvtdr+7Hrdu3XtZOGJ3Ft\/ifEfnd8Rvf\/ebuDfapw0z8v4hril48Op7yO4hn60eENYnrJ\/8lV5SoE2PuraU8yly9FPc3s+4dahZF4EffT\/h6ekZcfOYd1\/f5V\/\/\/pDpeMb+\/iEnpx\/z4vyUpm1pW08vPcRFyfxqzPHRAcv1nBenV\/S3+sjj27sYAwRJr284uDlApyt++NZr\/PIt6BZ\/49bBJaO9c5Qf44tT2rbFzT8nSQJXyxap4OGnT9m8eMh+Hz788C98\/eWnvHTnJheTR0gNWzsddkbbpGmf8dkljx99SfCOrR3JerVhZz\/n8HgL8cGf\/hAfP\/oM79d0ejvs7r2E0iXvvvE+g6TlopqiI0ipqasI0dC2noYuTg5RJqV1DdhLMt2SaiiqBSEEunmXGD3aKFzraNuAEIrFbM4Hf\/w9g70u2aClrgSLyw0v3b2B7u9lbC9Tri4v6I0Cs1nJrePX+MdHf2a+tNRNTWNLtO8QgyQEkEIRkTi1Q2E9Irb4ekaaaIx0rFdzhIQQA1JGhFQ45zFaI4TAh0iaZ1hbcv5lSZoa5lclNOfo8eQjekMN8ojFZIlSNVfTzylWkk8efsNqWRFji0ki3Wyb9bpksamwMSWYAUoItEmQCIgt0k4QOIrNkqJaUJYWJRU+BCBCBG0099+8i0kU0+mcLNUs50vyziF6Pq7Z2x9weJgSrCNET7GCr796zmJeMhh0mc3mRAKDgcBYQW9vh57uEpHkFHR6QyBjvZjg0wFVMWddrIFImqT40CKRxBiIRBrXoGRL2wjSRJHnCYQhQgnkfLrh\/OyKYt1wfHePZyeX7Ix6ON9gbU1RVCijaKwnRk+SKoQIOGGp7JRiNUWFKdFO6aiSTuLodhVaR5TSJJkhSRPSzCCVIEk1Uko6\/QHKaLrdLZLegAdvvEpnu48UMmE4GCKFpFhZ3nv\/Lfr9Lu\/\/4m1u3RnRzTOMUoQg8D4CAZMAtDjvCd4hgkcLi1ICKUAKiXMtbeuwlaWxjmJd4mxLY1uMMQyGQ97+8TtsDbYZ7HSpqpI8z9GziyWvvHyHTh7QRtK4AmUMp08XiChITEJNTZJqXBMoqwa5lSFiiypWZHkfrQ3GaKwVnJ2cM7m6wvtA8IHgI5GISQyNdYgoCS6gXMn0cgyh4ezxhsn4goPjA+T+1i4yJFxdFIwvllSlp9PNyDoK2ziKoqQsK7RSpJlBxEi5LkiznIqUxWJxnYaPaC3Y2ztgZ2cP7wEk2iiUkogAqU7o5zkCgWscD\/\/+T87HY6bjCSB4\/uQ5crQ\/JOsIOmmXjuhBVEjlefD6DbYGXdI0wdYNIgR6iWE4yOl2UlxjESrBR0FjW2zlcA20rcfojLybE2LEtYEQoPUB17YsVisqW\/Of\/z5GJwmL2YrGO4SUDHYH6M4g4cnJOWcnlxzdHZHlCTQSdEGInjQz1LUleMf+\/pAkkUgfSI0iz6BZt1jbkmUZTVPTWItvW5bzFSFeo+7bgBACpSXee4SExWRFt58htGS4t40tGqqNRU+vKuqN5+jOiNWsQqqEJgmsi4rzyQRtNPu3B0ibsFkXCOEJIeKaAsqSfi8hxIr5wuK9Zz7bsF5vEAhEEN+tsyDGa2PBB6QSDPa20MZQbWomz2ZY5zA6Qe8e5WxWghzJbq\/HctNwdrrEaM35ySWuaZEi0skMna5hvbHEAN1eh+WiJARP3kuRSuJsy3pT09gW7z2Na\/5vAiDNEqQQxBBZnJXXj7UtPnrqqqHTydCLieP27veYTqfcOBhRzL5gmAQeffsVSkZMxyAEGKOp6oCSCdIIWteitcB7CVFgqxbvA1JKtJJsD7ao64rGNTSNp7EOax2DrT4hBPK8Q6dvWC0qBBo\/9FSrGj0\/eY4bj5mu1yyutpGpoHKOu\/fu8vEnT2gaD1yjK5UmxpYQI0SJENcURRQq6UPrkH4DwtOGljRLSRKN1Q1GS6xtKYqCLMu4\/\/IDIoIxY549fcaDB\/dJb2n00e0hmyIw6kk6WwPybp\/FckpvsI3SGhMlUqnvYg\/XOkSQCUprhJToJMP5DK389Y3weB\/wPhKRmCS5LrVSNE2DlJKTp89ompbdnV3u338FISRSpuhWSnYPc4oNEB2XkwsObgxIsoxf\/frnNFWLFAlNY1EmYssGZbZxrSGkR2j3BdnOT6jbXUy4oF4+wlYT5rMLlFTUNazWNVeTSxKtGA1zhMr59vQF3V4P1zpenDwFBKP9fbT3grpuCd6jM0OeSDrdjBhhNDrAWUldlQihSIymrjWrlSXtDunffBMZ7hHEAQedDsPOIdVin8nlI5z1LFdrfvD2K3QzxcXFjLKqsGXJarHg8GBAXTckMuX2zXd49M0TJpcXyBs39xEqkA\/3qW2FMR2E3EapXUKbsNmU33UowYcuIUjqusQ1NWVRE+jh3RJvp0gRqMorvvnqMT4qujmsFjOsrTi+dUyWKo5uDullPQ4OhmiTEmQgUjDYSrh37w7\/A2YLLsjoRLMdAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration_big.png\u0022 alt=\u0022Terminal with `ls -lah \/etc\/nginx\/sites-enabled\/` executed on the new server\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022546.35547576302\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWhen it comes to \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/DevOps\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DevOps\u003C\/a\u003E, I\u0027m just the \u201cdev\u201d.\nI write code, but I\u0027d rather have someone else worry about making sure it keeps running as intended.\nI manage my personal VPS, I manage some servers at work, but I wouldn\u0027t call myself an expert in that area at all.\nSo I\u0027m super proud of myself and how well it went when I migrated a big project to a new machine \ud83d\ude0a\nThe downtime was just 15 minutes! Here\u0027s the story, if you\u0027re interested.\u003C\/p\u003E\n\u003Ch3\u003EWhy move?\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003EPronouns.page gets lots of traffic:\n\u003Ca href=\u0022https:\/\/stats.pronouns.page\/en.pronouns.page?period=30d\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E around 4 million pageviews a month\u003C\/a\u003E\nfor the English version alone. And on top of that, as an unapologetically queer website, we\u0027re a target of regular DDoS attacks.\nThe previous server didn\u0027t handle it well. We need an upgrade.\u003C\/li\u003E\n\u003Cli\u003EPronouns.page used to run on my personal VPS together with all my other pet projects.\nThey might not need many resources in comparison\n(damn, PP has outgrown everything else, including my wildest dreams \ud83d\ude05),\nbut it\u0027s still gonna be useful to give PP dedicated resources.\u003C\/li\u003E\n\u003Cli\u003EI used to be a bottleneck when it comes to fixing any issues on the server.\nNow that my personal stuff is on a different server, multiple people can have SSH access to the PP instance\nand intervene when necessary.\u003C\/li\u003E\n\u003Cli\u003EWe moved from OVH to Hetzner, getting a way better deal.\nInstead of 21.5\u20ac\/m\u003Csup\u003E[1]\u003C\/sup\u003E for 2 vCPU, 8GB RAM and 130GB drive\nwe\u0027ll now pay 27.25\u20ac\/m for 8 vCPU, 16GB RAM and 240GB drive.\u003Csup\u003E[2]\u003C\/sup\u003E\u003C\/li\u003E\n\u003Cli\u003EThe cost can now be charged directly to the \u003Ca href=\u0022https:\/\/en.pronouns.page\/team\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E NLC\u003C\/a\u003E account,\nI won\u0027t have to manage reimbusements (well, as soon as I figure out AWS migration).\u003C\/li\u003E\n\u003Cli\u003EI could use the opportunity to migrate to a new stack,\nwhich would\u0027ve been hard to do on a running server with tens of active projects.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EThe plan\u003C\/h3\u003E\n\u003Cp\u003EI bought the server on Wednesday and started setting it up, completely independently of the old machine.\nI created a setup that from the outside was indistinguishable from the old one, except for using an older database backup.\nUntil Saturday morning they were running simultaneously \u2013 the DNS were pointing to the old IP,\nbut my local \u003Ccode\u003E\/etc\/hosts\u003C\/code\u003E to the new one.\u003C\/p\u003E\n\u003Cp\u003EI picked Saturday morning, because mornings are when our traffic is lowest,\nand that day I\u0027m free and can focus on the migration,\neven if something goes wrong and takes more time than expected.\u003C\/p\u003E\n\u003Cp\u003EAn important part of the plan was taking notes \u2013 every important command I had run, I documented for myself.\nIn case anything goes wrong and I have to start over, or in case I wanted to later migrate my other projects to Hetzner too\n(and I do), I\u0027d have a recepe basically ready.\u003C\/p\u003E\n\u003Ch3\u003ECool things\u003C\/h3\u003E\n\u003Cp\u003EThe old configs were\u2026 meh. Long, repetitive and messy.\nJust switching from \u003Ca href=\u0022https:\/\/apache.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Apache\u003C\/a\u003E to \u003Ca href=\u0022https:\/\/nginx.org\/en\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E nginx\u003C\/a\u003E simplified them massively,\nbut I went further and extracted common parts for all domains and subdomains to make them reusable.\nSetting up everything for a new language version used to be a half-an-hour-or-so long process \u2013 now it takes me a few minutes.\u003C\/p\u003E\n\u003Cp\u003EThere\u0027s two things that were really annoying for me to figure out: analytics and monitoring.\nThose things are \u003Cem\u003Eexpensive\u003C\/em\u003E when your traffic is as big as ours.\nCorporations with such traffic can afford it easily, but we\u0027re not a business,\nwe have no considerable income other than donations and an \u003Ca href=\u0022https:\/\/arc.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E arc.io\u003C\/a\u003E widget.\nWe need to self-host those things, then.\u003C\/p\u003E\n\u003Cp\u003EFor traffic analytics, I\u0027ve recently switched from \u003Ca href=\u0022https:\/\/matomo.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Matomo\u003C\/a\u003E to \u003Ca href=\u0022https:\/\/plausible.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Plausible\u003C\/a\u003E.\nAs much as Matomo is better than Google Analytics from the privicy perspective\n(and it\u0027s \u003Cem\u003Ea lot\u003C\/em\u003E better), it\u0027s still really heavy and has way more features than I\u0027ll probably ever need.\nI needed to pay 11\u20ac\/m extra for a separate database server just for Matomo to store its logs.\nPlausible, on the other hand, is \u003Cem\u003Eexactly\u003C\/em\u003E what I need. So neat!\u003C\/p\u003E\n\u003Cp\u003EFor monitoring\u2026 We used to have one, hosted on AWS Lambda, but it kept causing trouble\nthat I had no time to fix, and in the end I disabled it.\nMonitoring is quite hard, because it needs to run on a dedicated and super reliable infrastructure\n\u2013 we can\u0027t monitor ourselves after all; if the server is down, so is the monitor that\u0027s supposed to let us know.\nI found out a really cool tool that keeps blowing my mind with its ingenuity:\n\u003Ca href=\u0022https:\/\/upptime.js.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Upptime\u003C\/a\u003E. It runs entirely on GitHub pages and actions,\ntotally for free (as long as you keep it public).\u003C\/p\u003E\n\u003Ch3\u003EIssues\u003C\/h3\u003E\n\u003Cp\u003EWe have multiple node servers running for different language versions.\nEach needs to run at some port and then nginx needs to be configured as a reverse proxy to that specific port.\nBefore it was really tediuos, I\u0027d just enumerate the ports starting at 3001 and for each new version\nI\u0027d first need to sift through configs to find what the current max value was.\nI kept looking up which port was related to which domain. Annoying shit.\u003C\/p\u003E\n\u003Cp\u003EIn the new setup, I wanted to have some single source of truth for the domain-port pairs,\nbut it turned out to be near impossible (at least for my skills). Nginx is strict about\nits configs being static. I couldn\u0027t find an easy way to pass data about those ports to it.\u003C\/p\u003E\n\u003Cp\u003EUltimately, I settled for a compromise system: I unambiguously map each version to a port\nby convering each letter of its ISO code to its index in the English alphabet.\nFor example for Japanese, \u003Ccode\u003Eja\u003C\/code\u003E, the port would be \u003Ccode\u003E31001\u003C\/code\u003E because \u201cj\u201d is the 10\u003Csup\u003Eth\u003C\/sup\u003E letter of the alphabet,\nand \u201ca\u201d is the 1\u003Csup\u003Est\u003C\/sup\u003E. Not a perfect system, but it\u0027s gonna simplify my flow a lot.\u003C\/p\u003E\n\u003Cp\u003EI wanted to switch from \u003Ca href=\u0022http:\/\/supervisord.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E supervisor\u003C\/a\u003E to \u003Ca href=\u0022https:\/\/pm2.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E pm2\u003C\/a\u003E\nfor its nicer interface and cool features, but for some reason it kept dropping a significant percentage of requests at (seemingly) random.\nI couldn\u0027t figure out the root cause, so I gave up. That switch wasn\u0027t worth that much of my time, I reverted back to supervisor.\u003C\/p\u003E\n\u003Cp\u003EA huge issue was that\u2026 no emails were getting sent from the new server.\nEvery SMTP request would just time out. I tried everything I could think of,\nI figured I must\u0027ve misconfigured something. I asked the team for help, but we couldn\u0027t find a root cause.\nBut then I got this random hypothesis \u2013 what if Hetzner is blocking port 465 regardless of our firewall settings?\nA quick seach \u2013 \u003Ca href=\u0022https:\/\/docs.hetzner.com\/cloud\/servers\/faq\/#why-can-i-not-send-any-mails-from-my-server\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E turns out they do\u003C\/a\u003E!\nUgh\u2026 I get their reasoning, seems like a perfectly reasonable approach. Switching ports worked.\nI just wish they somehow gave notice more visibly, not just an unexplained timeout,\nso that I wouldn\u0027t waste so much time figuring it out.\u003C\/p\u003E\n\u003Cp\u003EI struggled with moving Plausible too\u2026 It runs in Docker containers \u2013 but my knowlege of Docker is pretty limited.\nI spent way too much time trying to \u003Ccode\u003Epg_dump\u003C\/code\u003E and \u003Ccode\u003Epg_restore\u003C\/code\u003E my way from one container to host to another host via \u003Ccode\u003Escp\u003C\/code\u003E\nto another container, only to finally succeed and then\u2026 realise that the Postgres database is just half of the story.\nThe main chunk of data resides in \u003Ca href=\u0022https:\/\/clickhouse.com\/clickhouse\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E ClickHouse\u003C\/a\u003E.\nInstead of struggling with the whole thing again, I took a different approach: backing up and restoring entire Docker volumes.\nIt worked like a charm! Here are the commands, if you\u0027re interested:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-comment\u0022\u003E# old host\u003C\/span\u003E\ndocker run -v plausible_db-data:\/volume --rm loomchild\/volume-backup backup - \u0026gt; .\/db-data.tar.bz2\ndocker run -v plausible_event-data:\/volume --rm loomchild\/volume-backup backup - \u0026gt; .\/event-data.tar.bz2\n\nscp .\/db-data.tar.bz2 pp:\/home\/admin\/www\/stats.pronouns.page\nscp .\/event-data.tar.bz2 pp:\/home\/admin\/www\/stats.pronouns.page\n\n\u003Cspan class=\u0022hljs-comment\u0022\u003E# new host\u003C\/span\u003E\ncat .\/db-data.tar.bz2 | sudo docker run -i -v statspronounspage_db-data:\/volume --rm loomchild\/volume-backup restore -f -\ncat .\/event-data.tar.bz2 | sudo docker run -i -v statspronounspage_event-data:\/volume --rm loomchild\/volume-backup restore -f -\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EThe switch\u003C\/h3\u003E\n\u003Cp\u003EWhen everything was ready, on Friday evening, I announced the upcoming maintanance and waited.\nI had all the commands ready in a notepad.\u003C\/p\u003E\n\u003Cp\u003EWhen the time came, I just\u2026 stopped both servers, moved the database, moved plausible volumes,\nstarted the new server, and then updated the DNS entries. Simple as that.\u003C\/p\u003E\n\u003Cp\u003EIt was tons of work over a couple of evenings, but good preparation made wonders:\nit only took a quarter to actually switch.\nConsidering how ops is not my forte at all,\nI\u0027m so proud of having accomplished such a smooth transition \ud83e\udd70\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-cpu_big.png\u0022 alt=\u0022Screenshot of a CPU usage graph, dropping from ~50% to ~20%\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022538.96006028636\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACy0lEQVRIic2VzW7bRhCAv9klKcmRJaVC\/oAWRQ9FEyA99ZSnyHPmDXoreuw9QJs2aRIngt1KjCmapkQuudMDRVpynABJHKcDLLiD2Z9vZmeGcjBb6DLNWRcOY4T94YCTbEWWFzz46XvCwHKVItoIzjnCMOwM68LR74Xv2foZYEQaIABVRUSuFOAiCdpJWZZEUfQlWRARzBcluED+d0\/WRcg5h6ryanmKV0W3xvPjbEf\/XGMHqKhqAP5cpPz69xG1Kk\/fnLDIC9J1uePF6zQnKyt+eXZInBcAJGt3KRHqknq+cvyV5Pz2dMYkDJilOQdxyjUjOGCWnDKKAv7JVsxPVuwNeiyXGS8XKbcnQ9Ky4t7NMT\/cGNOzH5+aoqpaVRXPj2IePT7gjhUEyCrPwArBJq9KBFWPAWptQhuZxnbkPH0BYw3Tr0Y8\/PE7hlHwzkvfCdNWWRAEgBDUzYUC7AemgwGIUHoihCL0jXQwALdCwyQwjATcccphkn0QyKtl3s07N6y17NuPq7Lzu2rvP6hiT13Vre+AvPfsfcLbb0vh6q5qWqm8UqvSs4bKK16V5bpkutcjL1zXdjogVX8pMAC\/z5eMhgPm2YrAWm4P+xwkGbmr+fb6kH9PVmSFYzKImC1znhy+4UWccu\/m5AzImMv7q8eLhJ8XCUaEEhj3QvKyQgT+eNY8p1ElEDCbp5rXnqmwDXR5Xfra1lk9wJeOPoACre1cjo026dIB7YWG+19PURRjGqP6Tfc0BkXx3iNIo6videOtvK179agqRgwicqYbgwDeK4pijUVR1Hum4\/2zPpQkyQ6xiOB9k1eqirW2a\/EispO0rd5+W5u1FmstdV3vrDt\/Tyvj8Rgpy1LjOG483JRru+i8Xtd14+HmYO891toOvouASAfRRrt1rtW3zwKYTqdEUUTw+vCYeXzKaDgAEaqq5v7dby5OjiuQ\/wAsXdPKiHvexAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-cpu_big.png\u0022 alt=\u0022Screenshot of a CPU usage graph, dropping from ~50% to ~20%\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022538.96006028636\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-ram_big.png\u0022 alt=\u0022Screenshot of a RAM usage graph, dropping from almost 100% to under 40%\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022537.31343283582\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACyUlEQVRIic2VW29bRRDHf7t7LnZuTpOoLQKqSqBSLi9IvPI5eOiX6wvfAokH4BEhIQjqQyWUVC2kru04ts9td6YPx+fYJg5Kmogw0pFmdndm\/\/ufyzGzrNBfD4+w1rCz3WUyLfjs0ft0Owm3IUZEVUSoqhKMYzrLudPbxBjz34MxBqOqCiCifPvTb4Q0YS92bHRTjDWMZgWVD3zz1SMaiNPSEzvLYFbw7O8hexspmQ88PxnRix1fP37Adhq\/E6ioUSpf4fOCWelRCbwBzrwQW4MFsspzmlccvnxDVZS8mmQMzjK2UCoF6yxOhNwaxg\/vs5VEF9\/6LwwtvGqiEJF2aTuy9RZwPJzw47NjqqwAVRTYswYwJM0pW3P4\/fNXPPnyoysDArCNkiR12MqH88iBH\/44QrKc1EBqDR17cY0NB2N+OX5d18QVPlhKmfe+fuecqXPIy\/LSha4ijKfZhbEuEmPMgiGZO3etXX\/4CoF9EFQuD+bFeNbqi5TFdVd03fXbXeY1dtlU9Sf5asq89yvFfF2x1GMk94HUWcogJG6V+VFe0okczpqaUdVFl0VRRFmWNwYoMoYgwu9\/Dfn4YIej4QRnLWlkeXhni8OTEf2znPs7XfY2O5QhMMgK9jc6i8Goqjz97uebA5XETLxwb3eTOIoYZznOGHY3OvzZPyUWIQQh6aaEylP5wKcP7i4Nxqq6MTAAvqzoAKeD8cp6Np6SznVrQPMCC6QGtPSsb6lblBaQc+42cbTyv2NoqYY8X3x4ACz+Z3Y+JM\/ZqjBvU2MMqtq27XXsg93tustUldFoRAj1f6w5BJxzFpF2iDXry2KMaeM453DOtQ9ajvtPH1Wl1+vVDPX7fbz37UZzaXPZOru5sDm\/jlERaYeuqrb7jc9y3e7v7xNFEZGI8vJkxnRW8N69XfKiIgTh808+WGGiecmyve7V72o3sd8C0UCqwVDzC1oAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-ram_big.png\u0022 alt=\u0022Screenshot of a RAM usage graph, dropping from almost 100% to under 40%\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022537.31343283582\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-network_big.png\u0022 alt=\u0022Screenshot of a network activity usage graph\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022529.55538809344\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAATCAYAAAD4f6+NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACQElEQVRIicWV224TMRCGv7H3lE0iCi0ScMcF7\/8gPAOVeoMKbRq6UbIne4aLsEvaUtomkTrSSh7bMzv+\/NuWq0Vl5xc\/UTPen865Wa45eVPy5fMHXsPEzGy3o+8DIkKS+CeDLVSYgSRzqibiBaa5R0T2LigB2Gw2qCrT6XQs5F6d\/zTVgMZI13k6TfAC1tfkkympf3lRInKXkJkdtLrBvt92fHqT7RX7gNBzyDxlfdC98ojItqCyLIHjEYrG3nkSgLquiTEejVBUO4zQZDIBjkfIOICQmVHX9VE1pHYAobZtj64hkP0JFUVB0zSEEI5GyA4hBFAUxZjoOIRepiHtrnHZGfDnlDVNQ4yRsixfRUPaV0h6iojgALIsI89zLqseEUENgkLVRNadcttEFuuAGmw6pQ2GIRjC+aIFhGUdt1e\/CIOGnvthYSSaAMQYiTHy7brlsuqo6yWSzNj0Qpl6skRogxIVJknACdS9omRMc8fXixUDkDSRF2vINIxySQDSNMV7z5k\/51e15mO5Bskgi5i47dXrHPgECQuQhLeimD9B+hXmpiAGrgQN3HRzLq7ekXohRKWPRp44eoUyhaiQJ8KyDjhxdKsbqH4wLYq\/j+tqtaJt2zsrc84RYxzbIoKqjuMi8oDEMGfYAufcGDP0DTH3\/fl8vtVQ0zS0bfvgZKgqzjnMDFUdEw\/tIdHu2LBdMcYx325eEcE5N84VEbz3TCYTiqLYblnf9+PzsbuaXSKP+bt6GYr\/n\/\/YP2azGQC\/AdK2jZUbYES7AAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-network_big.png\u0022 alt=\u0022Screenshot of a network activity usage graph\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022529.55538809344\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Chr \/\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Csup\u003E[1]\u003C\/sup\u003E \u003Csmall\u003EOr more precisely: 80% of the old price (based on traffic ratio),\nwas paid by \u003Ca href=\u0022https:\/\/en.pronouns.page\/team\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E NLC\u003C\/a\u003E\nand 20% by me \u2013 now that it\u0027s just my personal server again I\u0027m gonna pay 100% \ud83d\ude05\u003C\/small\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Csup\u003E[2]\u003C\/sup\u003E \u003Csmall\u003EThat\u0027s just VPS costs, AWS bill is a whole other story.\u003C\/small\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["devops","server","nginx","apache","pm2","supervisor","ovh","hetzner","node"],"hasMore":true,"image":"https:\/\/avris.it\/image\/pronouns-page-migration_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/pronouns-page-migration_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration_mini.png\u0022 alt=\u0022Terminal with `ls -lah \/etc\/nginx\/sites-enabled\/` executed on the new server\u0022 width=\u0022240\u0022 height=\u0022136.58886894075\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWhen it comes to \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/DevOps\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DevOps\u003C\/a\u003E, I\u0027m just the \u201cdev\u201d.\nI write code, but I\u0027d rather have someone else worry about making sure it keeps running as intended.\nI manage my personal VPS, I manage some servers at work, but I wouldn\u0027t call myself an expert in that area at all.\nSo I\u0027m super proud of myself and how well it went when I migrated a big project to a new machine \ud83d\ude0a\nThe downtime was just 15 minutes! Here\u0027s the story, if you\u0027re interested.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/pronouns-page-migration_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration_mini.png\u0022 alt=\u0022Terminal with `ls -lah \/etc\/nginx\/sites-enabled\/` executed on the new server\u0022 width=\u0022240\u0022 height=\u0022136.58886894075\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWhen it comes to \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/DevOps\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DevOps\u003C\/a\u003E, I\u0027m just the \u201cdev\u201d.\nI write code, but I\u0027d rather have someone else worry about making sure it keeps running as intended.\nI manage my personal VPS, I manage some servers at work, but I wouldn\u0027t call myself an expert in that area at all.\nSo I\u0027m super proud of myself and how well it went when I migrated a big project to a new machine \ud83d\ude0a\nThe downtime was just 15 minutes! Here\u0027s the story, if you\u0027re interested.\u003C\/p\u003E\n\u003Ch3\u003EWhy move?\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003EPronouns.page gets lots of traffic:\n\u003Ca href=\u0022https:\/\/stats.pronouns.page\/en.pronouns.page?period=30d\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E around 4 million pageviews a month\u003C\/a\u003E\nfor the English version alone. And on top of that, as an unapologetically queer website, we\u0027re a target of regular DDoS attacks.\nThe previous server didn\u0027t handle it well. We need an upgrade.\u003C\/li\u003E\n\u003Cli\u003EPronouns.page used to run on my personal VPS together with all my other pet projects.\nThey might not need many resources in comparison\n(damn, PP has outgrown everything else, including my wildest dreams \ud83d\ude05),\nbut it\u0027s still gonna be useful to give PP dedicated resources.\u003C\/li\u003E\n\u003Cli\u003EI used to be a bottleneck when it comes to fixing any issues on the server.\nNow that my personal stuff is on a different server, multiple people can have SSH access to the PP instance\nand intervene when necessary.\u003C\/li\u003E\n\u003Cli\u003EWe moved from OVH to Hetzner, getting a way better deal.\nInstead of 21.5\u20ac\/m\u003Csup\u003E[1]\u003C\/sup\u003E for 2 vCPU, 8GB RAM and 130GB drive\nwe\u0027ll now pay 27.25\u20ac\/m for 8 vCPU, 16GB RAM and 240GB drive.\u003Csup\u003E[2]\u003C\/sup\u003E\u003C\/li\u003E\n\u003Cli\u003EThe cost can now be charged directly to the \u003Ca href=\u0022https:\/\/en.pronouns.page\/team\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E NLC\u003C\/a\u003E account,\nI won\u0027t have to manage reimbusements (well, as soon as I figure out AWS migration).\u003C\/li\u003E\n\u003Cli\u003EI could use the opportunity to migrate to a new stack,\nwhich would\u0027ve been hard to do on a running server with tens of active projects.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EThe plan\u003C\/h3\u003E\n\u003Cp\u003EI bought the server on Wednesday and started setting it up, completely independently of the old machine.\nI created a setup that from the outside was indistinguishable from the old one, except for using an older database backup.\nUntil Saturday morning they were running simultaneously \u2013 the DNS were pointing to the old IP,\nbut my local \u003Ccode\u003E\/etc\/hosts\u003C\/code\u003E to the new one.\u003C\/p\u003E\n\u003Cp\u003EI picked Saturday morning, because mornings are when our traffic is lowest,\nand that day I\u0027m free and can focus on the migration,\neven if something goes wrong and takes more time than expected.\u003C\/p\u003E\n\u003Cp\u003EAn important part of the plan was taking notes \u2013 every important command I had run, I documented for myself.\nIn case anything goes wrong and I have to start over, or in case I wanted to later migrate my other projects to Hetzner too\n(and I do), I\u0027d have a recepe basically ready.\u003C\/p\u003E\n\u003Ch3\u003ECool things\u003C\/h3\u003E\n\u003Cp\u003EThe old configs were\u2026 meh. Long, repetitive and messy.\nJust switching from \u003Ca href=\u0022https:\/\/apache.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Apache\u003C\/a\u003E to \u003Ca href=\u0022https:\/\/nginx.org\/en\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E nginx\u003C\/a\u003E simplified them massively,\nbut I went further and extracted common parts for all domains and subdomains to make them reusable.\nSetting up everything for a new language version used to be a half-an-hour-or-so long process \u2013 now it takes me a few minutes.\u003C\/p\u003E\n\u003Cp\u003EThere\u0027s two things that were really annoying for me to figure out: analytics and monitoring.\nThose things are \u003Cem\u003Eexpensive\u003C\/em\u003E when your traffic is as big as ours.\nCorporations with such traffic can afford it easily, but we\u0027re not a business,\nwe have no considerable income other than donations and an \u003Ca href=\u0022https:\/\/arc.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E arc.io\u003C\/a\u003E widget.\nWe need to self-host those things, then.\u003C\/p\u003E\n\u003Cp\u003EFor traffic analytics, I\u0027ve recently switched from \u003Ca href=\u0022https:\/\/matomo.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Matomo\u003C\/a\u003E to \u003Ca href=\u0022https:\/\/plausible.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Plausible\u003C\/a\u003E.\nAs much as Matomo is better than Google Analytics from the privicy perspective\n(and it\u0027s \u003Cem\u003Ea lot\u003C\/em\u003E better), it\u0027s still really heavy and has way more features than I\u0027ll probably ever need.\nI needed to pay 11\u20ac\/m extra for a separate database server just for Matomo to store its logs.\nPlausible, on the other hand, is \u003Cem\u003Eexactly\u003C\/em\u003E what I need. So neat!\u003C\/p\u003E\n\u003Cp\u003EFor monitoring\u2026 We used to have one, hosted on AWS Lambda, but it kept causing trouble\nthat I had no time to fix, and in the end I disabled it.\nMonitoring is quite hard, because it needs to run on a dedicated and super reliable infrastructure\n\u2013 we can\u0027t monitor ourselves after all; if the server is down, so is the monitor that\u0027s supposed to let us know.\nI found out a really cool tool that keeps blowing my mind with its ingenuity:\n\u003Ca href=\u0022https:\/\/upptime.js.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Upptime\u003C\/a\u003E. It runs entirely on GitHub pages and actions,\ntotally for free (as long as you keep it public).\u003C\/p\u003E\n\u003Ch3\u003EIssues\u003C\/h3\u003E\n\u003Cp\u003EWe have multiple node servers running for different language versions.\nEach needs to run at some port and then nginx needs to be configured as a reverse proxy to that specific port.\nBefore it was really tediuos, I\u0027d just enumerate the ports starting at 3001 and for each new version\nI\u0027d first need to sift through configs to find what the current max value was.\nI kept looking up which port was related to which domain. Annoying shit.\u003C\/p\u003E\n\u003Cp\u003EIn the new setup, I wanted to have some single source of truth for the domain-port pairs,\nbut it turned out to be near impossible (at least for my skills). Nginx is strict about\nits configs being static. I couldn\u0027t find an easy way to pass data about those ports to it.\u003C\/p\u003E\n\u003Cp\u003EUltimately, I settled for a compromise system: I unambiguously map each version to a port\nby convering each letter of its ISO code to its index in the English alphabet.\nFor example for Japanese, \u003Ccode\u003Eja\u003C\/code\u003E, the port would be \u003Ccode\u003E31001\u003C\/code\u003E because \u201cj\u201d is the 10\u003Csup\u003Eth\u003C\/sup\u003E letter of the alphabet,\nand \u201ca\u201d is the 1\u003Csup\u003Est\u003C\/sup\u003E. Not a perfect system, but it\u0027s gonna simplify my flow a lot.\u003C\/p\u003E\n\u003Cp\u003EI wanted to switch from \u003Ca href=\u0022http:\/\/supervisord.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E supervisor\u003C\/a\u003E to \u003Ca href=\u0022https:\/\/pm2.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E pm2\u003C\/a\u003E\nfor its nicer interface and cool features, but for some reason it kept dropping a significant percentage of requests at (seemingly) random.\nI couldn\u0027t figure out the root cause, so I gave up. That switch wasn\u0027t worth that much of my time, I reverted back to supervisor.\u003C\/p\u003E\n\u003Cp\u003EA huge issue was that\u2026 no emails were getting sent from the new server.\nEvery SMTP request would just time out. I tried everything I could think of,\nI figured I must\u0027ve misconfigured something. I asked the team for help, but we couldn\u0027t find a root cause.\nBut then I got this random hypothesis \u2013 what if Hetzner is blocking port 465 regardless of our firewall settings?\nA quick seach \u2013 \u003Ca href=\u0022https:\/\/docs.hetzner.com\/cloud\/servers\/faq\/#why-can-i-not-send-any-mails-from-my-server\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E turns out they do\u003C\/a\u003E!\nUgh\u2026 I get their reasoning, seems like a perfectly reasonable approach. Switching ports worked.\nI just wish they somehow gave notice more visibly, not just an unexplained timeout,\nso that I wouldn\u0027t waste so much time figuring it out.\u003C\/p\u003E\n\u003Cp\u003EI struggled with moving Plausible too\u2026 It runs in Docker containers \u2013 but my knowlege of Docker is pretty limited.\nI spent way too much time trying to \u003Ccode\u003Epg_dump\u003C\/code\u003E and \u003Ccode\u003Epg_restore\u003C\/code\u003E my way from one container to host to another host via \u003Ccode\u003Escp\u003C\/code\u003E\nto another container, only to finally succeed and then\u2026 realise that the Postgres database is just half of the story.\nThe main chunk of data resides in \u003Ca href=\u0022https:\/\/clickhouse.com\/clickhouse\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E ClickHouse\u003C\/a\u003E.\nInstead of struggling with the whole thing again, I took a different approach: backing up and restoring entire Docker volumes.\nIt worked like a charm! Here are the commands, if you\u0027re interested:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E# old host\ndocker run -v plausible_db-data:\/volume --rm loomchild\/volume-backup backup - \u0026gt; .\/db-data.tar.bz2\ndocker run -v plausible_event-data:\/volume --rm loomchild\/volume-backup backup - \u0026gt; .\/event-data.tar.bz2\n\nscp .\/db-data.tar.bz2 pp:\/home\/admin\/www\/stats.pronouns.page\nscp .\/event-data.tar.bz2 pp:\/home\/admin\/www\/stats.pronouns.page\n\n# new host\ncat .\/db-data.tar.bz2 | sudo docker run -i -v statspronounspage_db-data:\/volume --rm loomchild\/volume-backup restore -f -\ncat .\/event-data.tar.bz2 | sudo docker run -i -v statspronounspage_event-data:\/volume --rm loomchild\/volume-backup restore -f -\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch3\u003EThe switch\u003C\/h3\u003E\n\u003Cp\u003EWhen everything was ready, on Friday evening, I announced the upcoming maintanance and waited.\nI had all the commands ready in a notepad.\u003C\/p\u003E\n\u003Cp\u003EWhen the time came, I just\u2026 stopped both servers, moved the database, moved plausible volumes,\nstarted the new server, and then updated the DNS entries. Simple as that.\u003C\/p\u003E\n\u003Cp\u003EIt was tons of work over a couple of evenings, but good preparation made wonders:\nit only took a quarter to actually switch.\nConsidering how ops is not my forte at all,\nI\u0027m so proud of having accomplished such a smooth transition \ud83e\udd70\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-cpu_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-cpu_mini.png\u0022 alt=\u0022Screenshot of a CPU usage graph, dropping from ~50% to ~20%\u0022 width=\u0022240\u0022 height=\u0022134.74001507159\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-ram_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-ram_mini.png\u0022 alt=\u0022Screenshot of a RAM usage graph, dropping from almost 100% to under 40%\u0022 width=\u0022240\u0022 height=\u0022134.32835820896\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-network_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/pronouns-page-migration-old-network_mini.png\u0022 alt=\u0022Screenshot of a network activity usage graph\u0022 width=\u0022240\u0022 height=\u0022132.38884702336\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Chr \/\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Csup\u003E[1]\u003C\/sup\u003E \u003Csmall\u003EOr more precisely: 80% of the old price (based on traffic ratio),\nwas paid by \u003Ca href=\u0022https:\/\/en.pronouns.page\/team\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E NLC\u003C\/a\u003E\nand 20% by me \u2013 now that it\u0027s just my personal server again I\u0027m gonna pay 100% \ud83d\ude05\u003C\/small\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Csup\u003E[2]\u003C\/sup\u003E \u003Csmall\u003EThat\u0027s just VPS costs, AWS bill is a whole other story.\u003C\/small\u003E\u003C\/li\u003E\n\u003C\/ul\u003E","words":1432,"readTime":6,"lang":"en"}}},"blog\/technology\/ux-but-in-real-life":{"key":"blog\/technology\/ux-but-in-real-life","type":"article","published":true,"meta":{"createdAt":"2021-04-10T11:08:40+02:00","publishedAt":"2021-04-10T11:08:40+02:00","group":null,"category":"blog","subcategory":"technology","slug":"ux-but-in-real-life"},"content":{"en":{"slug":"ux-but-in-real-life","title":"UX, but in real life","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/szafa_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022853.33333333333\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAYAAACJ8xqgAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAIIElEQVRIiS2SWW+cVwGGn3O+dTbP4hnb492OG9tZ6iQNoWkVoKQqAgRCZZHKPf8j9\/wBJG64gjuEhJAqbkiFSgC1pqkTJ3Fix9t4n33m279zuEhf6b1\/nlev+N1vH2jQ\/G99nTT0ODk5pVyboN9tEoQxSdDn\/rVLNOOEx9unbL4+5azTw3UcdBJTcQX1ahbLEhjSRvqDUyJ\/iB9GWG6OkfEp\/Dil7\/mMF00srbGenzA9s8JoKYvrmEggTVJsCZWijeBNJAlmq2vRONwiZ0uqOYONFw1c1yaIErKuzfJbk7wY+rT\/\/ZBmr49tS0xDonWKRiAFCCmRQiARyF\/+\/If8+pNfkKSwtd9molSm7ChqIzaLs3Xq4+OkqUJrRbMT43s+mYzDWG0UwzRQCoQWGAiElJhx6FGrVrBMk8ZZi3KhxNWFKe7emENKzenJGZPjIzRfRgSxZLRUZrZY4sbaGgf7r+kc7aDiiIuOx1g5i\/l8cwMnkycIPOrVInnXpZh3ODptMlMfJUkTTEMyUbEYRkUqE1PYtkWpWKBfKLB29QrnzQ4P28\/AcjDnJsfp9X1+8L17SODg8JDnr\/Y4aGyRcx3uri2SKoVp2VQKCtU7IrQcNjfB7zS5+\/YS4TBEa7DdIqYwTKQBuYxLFMdM1ieoVQscHpU5OTli5+CMWq3GIIzwhgPyOYezbsSLjSdkLcHrSp7jVpfWMMZpeZjdnoehU4RIMVQPM+2iVcRMzWGiMs\/rRoeNFztolTAxPool4eu9FnEc00s0X+4f8nTvBB+b3eMWpmMAaUoaniPTCMsAIQyageCLJ69ptlrYtsGt5XnSNOHwuM1kuUCr7yGFxcbxkIgMQsdorTDD0EN7xwyGfbJuhkQbbGxfEJBhcnaRidoIJ6fnJErzavcMWzp88PZlds97zM3XCJVid++cQTvEEALTiFtoqTk8OMEuVHixd04chVy9dYepS1cIE8VyGuF1W2y8+DMfvvcOTw\/OuXlzjYOjA8LQR0URrmlwZ34C4zcf33sQK4PTTkBzmFCtjeIPugza5\/SaDfwwQkY9CLqYgc\/1hSUuXV7lx7\/6hFwmy\/pXT3EMyY9urlDJO5i58SWerW+SyAy2FeCKgOWFGhnbfPNBdUT7oMPznQb9YUw+V+HDj++Qy+b42U9\/wpXqCHsb6+wdNvjX1h5Sdw9YW5lmZnYWrSVzYzkWJgokkc\/uXoN+t83OXgMpJVP1OW59\/yOqc4sYlomQkmgwwDVtbq4sY0kDMw09ROxzZbrEaOUGwekztnYOaBy3GPgRnd4ADIPVxUWEXWBsdoah18F1skRxwj\/++xmJ57P1+oBhGmMCpEnCi82n7OwfgY7wfJ+RvMv01BjbjRbDGCq1Cr2ux8O\/\/pHS+DSV6gRpqqmPWfR6Abl+hXrGxLi5Ov0giWN6gx69XocwDBmvllHS4tN\/PmZpfpbbK3X2\/TKX3lomThIGA5+97Wc4qsv07ALCzqBSRb\/bwvjg+sSDbq9Pu9vDDyKmJ8do9SP+9tk6C1NVVudHMQyJJ0bQQmISkbXgq8cbdDp9lNZMjZVYXV3GkBozSVL6fshFp0ev77G+dUR\/4HN5fow71xdwLZOMbWF1j4lOTzBMxc5xmygO2W10OTo542Jxhhtr1zg5OsSUhkEukyEIYxwny\/WbC3QujhivFMgVRzGSAUkcMV9xSVLFwE+4aHt4fgRaszhVhLjP+ldf0\/VT5LXL80gJpp3h+tptep0eF80+23vnXLT6mJaF6zqYpoEhBRdtn1ZviB8ELE0VMWVKogzOmgMqWYl8ut3AyVX41rv3MEwLwzSoVso4jk0x7+A4byoAP4zZ3D0njBLemiqSdU2GQUicalTUZ3muhlkarbN67QZDP6B\/ts39+99hd3sfVzdxTLCkBASpgpeHbYIwpla0cSzJYOhTLuaYGR8l706ABvPW7XdJlSJOU4rFIoPDpyxdukKr6SL9M7QWeEHEaWvAy\/1zqkWHrA1xHLG8egWdxvRChWtrTAHStm0K+Tzl4gj1hWtIZwTv5CXlUpFsbY6zbsB\/np3xxbMjSoUspZxNEEbcvnWVYkZwcdFE6JhAmWhAGlICYEiDTDZPZWoFZeXxz3aRGqzyAkM\/pjKSJ+s4+EHE5HiNcj5LOZ\/j+tIMWVtiOhlCbSIREqVAIQCB67gYlknXTxie7TGWTbj33e\/g2DaVyQUGkWZpdoIkTlBJimNZVEtlvGGXza0dxNef\/kEDKEAIgRCCzvkhXhDQOX6FLSA2s5x7NseN17x9dYm8HqBTBd9AACSAH0SYtm2hNSRpitIatKJcnWQkjemc7ND3PQ5Oj2mcd1lZe58cIbZpo6UiSVMSpUBr0JpEaWSaKtJUIaTEcWwsy8R2HRzHpTp1mViDMAwuXbnNsNkAFaOUItUaISWWaSIMiZSSrGMikzRFa43gDZ1SiiSKieKY0bEpSvUV2p6kcbBPKafxfY80TYiTFENK4jhBIBASTCkw4yhGaU0u64IQ2LaDRmOkBlpr5ufn8f2ANIl5vPEEd7HC7vExU\/Ua3cGANFWUCjkAUhRSa4iiGNt1kFISJwmfPVrn0ZcbeEOPJE6o1+uUK6O8\/957PNtrs9\/0CcMhSRJSKBQwHQf1jZ3UWqNSCMMY3w\/4+8NH\/P5Pf+H5qz0wTNxMlmKxRK02RrVa4+6375KxJa8bbfwwxKktsvjORwgp0VojhQCEIkkStIbNp9vEqaIykgOtiaLoza5JAkozMjLCO7fvYGRLPNnp8Pnnj8DMMn\/zPlGc8H\/IiDMycLHKjgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/szafa_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022853.33333333333\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAmong people who create websites or apps there\u0027s an understanding that UX, user experience, is massively important.\nWe know that most users either don\u0027t have the technical knowledge to use software that isn\u0027t intuitive,\nor they simply don\u0027t have time to be bothered to get to know an app that isn\u0027t easy to use\n(and they have many alternatives to switch to).\u003C\/p\u003E\n\u003Cp\u003ESo I\u0027d think that ease of use of one\u0027s products is a common concern among companies of all industries, right?\nWell, I then moved to a new place and had to assemble a lot of furniture\u2026\nWhat an absulute UX nightmare it was!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/szafa_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022576\u0022 height=\u00221024\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAYAAACJ8xqgAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAIIElEQVRIiS2SWW+cVwGGn3O+dTbP4hnb492OG9tZ6iQNoWkVoKQqAgRCZZHKPf8j9\/wBJG64gjuEhJAqbkiFSgC1pqkTJ3Fix9t4n33m279zuEhf6b1\/nlev+N1vH2jQ\/G99nTT0ODk5pVyboN9tEoQxSdDn\/rVLNOOEx9unbL4+5azTw3UcdBJTcQX1ahbLEhjSRvqDUyJ\/iB9GWG6OkfEp\/Dil7\/mMF00srbGenzA9s8JoKYvrmEggTVJsCZWijeBNJAlmq2vRONwiZ0uqOYONFw1c1yaIErKuzfJbk7wY+rT\/\/ZBmr49tS0xDonWKRiAFCCmRQiARyF\/+\/If8+pNfkKSwtd9molSm7ChqIzaLs3Xq4+OkqUJrRbMT43s+mYzDWG0UwzRQCoQWGAiElJhx6FGrVrBMk8ZZi3KhxNWFKe7emENKzenJGZPjIzRfRgSxZLRUZrZY4sbaGgf7r+kc7aDiiIuOx1g5i\/l8cwMnkycIPOrVInnXpZh3ODptMlMfJUkTTEMyUbEYRkUqE1PYtkWpWKBfKLB29QrnzQ4P28\/AcjDnJsfp9X1+8L17SODg8JDnr\/Y4aGyRcx3uri2SKoVp2VQKCtU7IrQcNjfB7zS5+\/YS4TBEa7DdIqYwTKQBuYxLFMdM1ieoVQscHpU5OTli5+CMWq3GIIzwhgPyOYezbsSLjSdkLcHrSp7jVpfWMMZpeZjdnoehU4RIMVQPM+2iVcRMzWGiMs\/rRoeNFztolTAxPool4eu9FnEc00s0X+4f8nTvBB+b3eMWpmMAaUoaniPTCMsAIQyageCLJ69ptlrYtsGt5XnSNOHwuM1kuUCr7yGFxcbxkIgMQsdorTDD0EN7xwyGfbJuhkQbbGxfEJBhcnaRidoIJ6fnJErzavcMWzp88PZlds97zM3XCJVid++cQTvEEALTiFtoqTk8OMEuVHixd04chVy9dYepS1cIE8VyGuF1W2y8+DMfvvcOTw\/OuXlzjYOjA8LQR0URrmlwZ34C4zcf33sQK4PTTkBzmFCtjeIPugza5\/SaDfwwQkY9CLqYgc\/1hSUuXV7lx7\/6hFwmy\/pXT3EMyY9urlDJO5i58SWerW+SyAy2FeCKgOWFGhnbfPNBdUT7oMPznQb9YUw+V+HDj++Qy+b42U9\/wpXqCHsb6+wdNvjX1h5Sdw9YW5lmZnYWrSVzYzkWJgokkc\/uXoN+t83OXgMpJVP1OW59\/yOqc4sYlomQkmgwwDVtbq4sY0kDMw09ROxzZbrEaOUGwekztnYOaBy3GPgRnd4ADIPVxUWEXWBsdoah18F1skRxwj\/++xmJ57P1+oBhGmMCpEnCi82n7OwfgY7wfJ+RvMv01BjbjRbDGCq1Cr2ux8O\/\/pHS+DSV6gRpqqmPWfR6Abl+hXrGxLi5Ov0giWN6gx69XocwDBmvllHS4tN\/PmZpfpbbK3X2\/TKX3lomThIGA5+97Wc4qsv07ALCzqBSRb\/bwvjg+sSDbq9Pu9vDDyKmJ8do9SP+9tk6C1NVVudHMQyJJ0bQQmISkbXgq8cbdDp9lNZMjZVYXV3GkBozSVL6fshFp0ev77G+dUR\/4HN5fow71xdwLZOMbWF1j4lOTzBMxc5xmygO2W10OTo542Jxhhtr1zg5OsSUhkEukyEIYxwny\/WbC3QujhivFMgVRzGSAUkcMV9xSVLFwE+4aHt4fgRaszhVhLjP+ldf0\/VT5LXL80gJpp3h+tptep0eF80+23vnXLT6mJaF6zqYpoEhBRdtn1ZviB8ELE0VMWVKogzOmgMqWYl8ut3AyVX41rv3MEwLwzSoVso4jk0x7+A4byoAP4zZ3D0njBLemiqSdU2GQUicalTUZ3muhlkarbN67QZDP6B\/ts39+99hd3sfVzdxTLCkBASpgpeHbYIwpla0cSzJYOhTLuaYGR8l706ABvPW7XdJlSJOU4rFIoPDpyxdukKr6SL9M7QWeEHEaWvAy\/1zqkWHrA1xHLG8egWdxvRChWtrTAHStm0K+Tzl4gj1hWtIZwTv5CXlUpFsbY6zbsB\/np3xxbMjSoUspZxNEEbcvnWVYkZwcdFE6JhAmWhAGlICYEiDTDZPZWoFZeXxz3aRGqzyAkM\/pjKSJ+s4+EHE5HiNcj5LOZ\/j+tIMWVtiOhlCbSIREqVAIQCB67gYlknXTxie7TGWTbj33e\/g2DaVyQUGkWZpdoIkTlBJimNZVEtlvGGXza0dxNef\/kEDKEAIgRCCzvkhXhDQOX6FLSA2s5x7NseN17x9dYm8HqBTBd9AACSAH0SYtm2hNSRpitIatKJcnWQkjemc7ND3PQ5Oj2mcd1lZe58cIbZpo6UiSVMSpUBr0JpEaWSaKtJUIaTEcWwsy8R2HRzHpTp1mViDMAwuXbnNsNkAFaOUItUaISWWaSIMiZSSrGMikzRFa43gDZ1SiiSKieKY0bEpSvUV2p6kcbBPKafxfY80TYiTFENK4jhBIBASTCkw4yhGaU0u64IQ2LaDRmOkBlpr5ufn8f2ANIl5vPEEd7HC7vExU\/Ua3cGANFWUCjkAUhRSa4iiGNt1kFISJwmfPVrn0ZcbeEOPJE6o1+uUK6O8\/957PNtrs9\/0CcMhSRJSKBQwHQf1jZ3UWqNSCMMY3w\/4+8NH\/P5Pf+H5qz0wTNxMlmKxRK02RrVa4+6375KxJa8bbfwwxKktsvjORwgp0VojhQCEIkkStIbNp9vEqaIykgOtiaLoza5JAkozMjLCO7fvYGRLPNnp8Pnnj8DMMn\/zPlGc8H\/IiDMycLHKjgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/szafa_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022576\u0022 height=\u00221024\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAmong people who create websites or apps there\u0027s an understanding that UX, user experience, is massively important.\nWe know that most users either don\u0027t have the technical knowledge to use software that isn\u0027t intuitive,\nor they simply don\u0027t have time to be bothered to get to know an app that isn\u0027t easy to use\n(and they have many alternatives to switch to).\u003C\/p\u003E\n\u003Cp\u003ESo I\u0027d think that ease of use of one\u0027s products is a common concern among companies of all industries, right?\nWell, I then moved to a new place and had to assemble a lot of furniture\u2026\nWhat an absulute UX nightmare it was!\u003C\/p\u003E\n\u003Cp\u003EI\u0027ll only focus on one \u2013 most terrible \u2013 example: the wardrobe.\nCause the amount of awful compared to how easily it could\u0027ve been fixed is just astonishing there.\u003C\/p\u003E\n\u003Cp\u003EOur wardrobe came in 9 huuuge cardboard boxes. It took us just just about two evenings to \u003Cem\u003Eactually\u003C\/em\u003E assemble it \u2013\nbut like a week overall, if we count the time of being too overwhelmed to start,\nand figuring out what to do and how to even start.\u003C\/p\u003E\n\u003Cp\u003EI know, I know, check the manual, right?\u003C\/p\u003E\n\u003Cp\u003EOkay, but \u003Cem\u003Ewhere is\u003C\/em\u003E the manual, huh? Seriously, where is it? We\u0027ve received nine huge boxes,\nand before we could even start wrapping our heads around the complexity of the task,\nwe had to open and search through (so glad we had space for all that shuffling) seven of them.\nYup, the most logical thing to do as the manufacturer\nis to put the manual in the box labeled \u201c7\/9\u201d, apparently.\u003C\/p\u003E\n\u003Cp\u003EWe had already been starting to lose faith, thinking we need to contact the manufacturer now,\nwait until they send us the missing manual, worry about what else they had messed up\u2026\nNah, they just made us go searching through seven boxes of parts, just because.\u003C\/p\u003E\n\u003Cp\u003EJust put the manual in the \u201c1\/9\u201d box. That costs you nothing.\nOr even better, put it outside of box \u201c1\/9\u201d, in the plastic wrapper where you put our address label and an invoice.\nI know, crazy customer demanding impossible accommodations!\u003C\/p\u003E\n\u003Cp\u003EBut now that we have the manual, there\u0027s another challenge. We have no idea, which part is which.\nSome are easy to distinguish, but others are very similar to each other.\nThe first evening of \u201cassembly\u201d was just us going through the manual and through all the items from all the boxes,\nfiguring out which part is the correct size and has the correct holes on the correct side,\nand then putting a bit of tape on that part on which we wrote down the element number, as per manual.\u003C\/p\u003E\n\u003Cp\u003ECan you imagine the manufacturer just\u2026 doing it for us?\nOr even, I don\u0027t know, putting the info in the manual about which part is in which box?\nIt\u0027s literally a bit of ink and a few bits of tape.\u003C\/p\u003E\n\u003Cp\u003EImagine we could just take the manual from the plastic wrapping glued to one box and read things like\n\u201ctake part 5 from box 1\/9 and screw it together with part 12 from box 4\/9\u201d?\nUnreal, right?\u003C\/p\u003E\n\u003Cp\u003EThat\u0027s just the most important points I remember, among other things that could be improved.\nBut I think it already makes the point.\n\u201cMake the manual easy to find\u201d and \u201clet the consumer know which part is which\u201d\nshouldn\u0027t really be hard things to figure out, right?\u003C\/p\u003E\n\u003Cp\u003EBut apparently it\u0027s easier to just sell off a piece of furniture,\nenjoy the money you cashed in, and not give a fuck what the customer is gonna go through next.\u003C\/p\u003E\n\u003Cp\u003EAfter all, they probably won\u0027t need a new wardrobe any time soon, so why give a fuck?\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["furniture","business","ux","user experience","manual"],"hasMore":true,"image":"https:\/\/avris.it\/image\/szafa_small.jpg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/szafa_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/szafa_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022426.66666666667\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAmong people who create websites or apps there\u0027s an understanding that UX, user experience, is massively important.\nWe know that most users either don\u0027t have the technical knowledge to use software that isn\u0027t intuitive,\nor they simply don\u0027t have time to be bothered to get to know an app that isn\u0027t easy to use\n(and they have many alternatives to switch to).\u003C\/p\u003E\n\u003Cp\u003ESo I\u0027d think that ease of use of one\u0027s products is a common concern among companies of all industries, right?\nWell, I then moved to a new place and had to assemble a lot of furniture\u2026\nWhat an absulute UX nightmare it was!\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/szafa_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/szafa_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022426.66666666667\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAmong people who create websites or apps there\u0027s an understanding that UX, user experience, is massively important.\nWe know that most users either don\u0027t have the technical knowledge to use software that isn\u0027t intuitive,\nor they simply don\u0027t have time to be bothered to get to know an app that isn\u0027t easy to use\n(and they have many alternatives to switch to).\u003C\/p\u003E\n\u003Cp\u003ESo I\u0027d think that ease of use of one\u0027s products is a common concern among companies of all industries, right?\nWell, I then moved to a new place and had to assemble a lot of furniture\u2026\nWhat an absulute UX nightmare it was!\u003C\/p\u003E\n\u003Cp\u003EI\u0027ll only focus on one \u2013 most terrible \u2013 example: the wardrobe.\nCause the amount of awful compared to how easily it could\u0027ve been fixed is just astonishing there.\u003C\/p\u003E\n\u003Cp\u003EOur wardrobe came in 9 huuuge cardboard boxes. It took us just just about two evenings to \u003Cem\u003Eactually\u003C\/em\u003E assemble it \u2013\nbut like a week overall, if we count the time of being too overwhelmed to start,\nand figuring out what to do and how to even start.\u003C\/p\u003E\n\u003Cp\u003EI know, I know, check the manual, right?\u003C\/p\u003E\n\u003Cp\u003EOkay, but \u003Cem\u003Ewhere is\u003C\/em\u003E the manual, huh? Seriously, where is it? We\u0027ve received nine huge boxes,\nand before we could even start wrapping our heads around the complexity of the task,\nwe had to open and search through (so glad we had space for all that shuffling) seven of them.\nYup, the most logical thing to do as the manufacturer\nis to put the manual in the box labeled \u201c7\/9\u201d, apparently.\u003C\/p\u003E\n\u003Cp\u003EWe had already been starting to lose faith, thinking we need to contact the manufacturer now,\nwait until they send us the missing manual, worry about what else they had messed up\u2026\nNah, they just made us go searching through seven boxes of parts, just because.\u003C\/p\u003E\n\u003Cp\u003EJust put the manual in the \u201c1\/9\u201d box. That costs you nothing.\nOr even better, put it outside of box \u201c1\/9\u201d, in the plastic wrapper where you put our address label and an invoice.\nI know, crazy customer demanding impossible accommodations!\u003C\/p\u003E\n\u003Cp\u003EBut now that we have the manual, there\u0027s another challenge. We have no idea, which part is which.\nSome are easy to distinguish, but others are very similar to each other.\nThe first evening of \u201cassembly\u201d was just us going through the manual and through all the items from all the boxes,\nfiguring out which part is the correct size and has the correct holes on the correct side,\nand then putting a bit of tape on that part on which we wrote down the element number, as per manual.\u003C\/p\u003E\n\u003Cp\u003ECan you imagine the manufacturer just\u2026 doing it for us?\nOr even, I don\u0027t know, putting the info in the manual about which part is in which box?\nIt\u0027s literally a bit of ink and a few bits of tape.\u003C\/p\u003E\n\u003Cp\u003EImagine we could just take the manual from the plastic wrapping glued to one box and read things like\n\u201ctake part 5 from box 1\/9 and screw it together with part 12 from box 4\/9\u201d?\nUnreal, right?\u003C\/p\u003E\n\u003Cp\u003EThat\u0027s just the most important points I remember, among other things that could be improved.\nBut I think it already makes the point.\n\u201cMake the manual easy to find\u201d and \u201clet the consumer know which part is which\u201d\nshouldn\u0027t really be hard things to figure out, right?\u003C\/p\u003E\n\u003Cp\u003EBut apparently it\u0027s easier to just sell off a piece of furniture,\nenjoy the money you cashed in, and not give a fuck what the customer is gonna go through next.\u003C\/p\u003E\n\u003Cp\u003EAfter all, they probably won\u0027t need a new wardrobe any time soon, so why give a fuck?\u003C\/p\u003E","words":599,"readTime":3,"lang":"en"}}},"blog\/technology\/self-hosting-font-awesome-5-pro-for-yarn-npm":{"key":"blog\/technology\/self-hosting-font-awesome-5-pro-for-yarn-npm","type":"article","published":true,"meta":{"createdAt":"2020-07-27T20:05:47+02:00","publishedAt":"2020-07-27T20:05:47+02:00","group":null,"category":"blog","subcategory":"technology","slug":"self-hosting-font-awesome-5-pro-for-yarn-npm"},"content":{"en":{"slug":"self-hosting-font-awesome-5-pro-for-yarn-npm","title":"Self-hosting Font Awesome 5 Pro for yarn\/npm","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/fontawesome6_small.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022136.66666666667\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAKCAYAAADcpvzeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB\/ElEQVQ4jc2Tu46TMRCFvxnb\/5\/LLlBw03IRDQJKKCgoeAY6hCgpeAqejBdAFFQIKCmQENoQdkM2\/yW2h8LZTVIAKwQSR5rC42PP8fGMdG+fGoCZETM4AQOWEYIHsxIikDNkg+DKOq3WdRD+FjzAq\/eJ6cy4f9sxOTScA+8gxlI0+CIQAacQozGohEVnVEG4dK7wRIpAlRLLVPhOoe3Lmd3RtvjZkZHNCF4YDwTp3j2z9bZtkbHtjMjareLqOv8zHPPX537tpuSc7eM0Ukniwq4DM1S12Oc9y5jIOW8UMJxTvHMbQgWz7cfYxj2nwXK5xHtfvqyLgCQmk2+ICCllzIyrV\/bIOdP1PYKgTk9scap0fQ9myMqiEAKLpmFQD+j7nvF4dGpBbduxs+ORJ89f2O\/p\/x6fPu+zd\/k8cu3uI2u7npwzdRW4c\/MGANmMnDOz70eMR0OGw5qcMl2\/ZNG07H89+OPiTmF3uJ2LGebNaspq1\/HwXuDlm8SX\/enJ39dVIMbE9GCGzhSnStv1jIY1Z3bGqAoiJULwqCoxRlQVVSWlhHMKBk3bUVWBpulwsmBUC0etMR4IlYd5C\/PGiqBF73n9oTTraDRAEJq2o2k7RIXgHSkbIiuRKaEqGKAixFQa\/2A2P5VDZ8dw\/aKwOXFtD5NDQ249ePxf9NAxfgCKbvUuzuwSpgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/fontawesome6_small.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022136.66666666667\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFour years ago I backed Font Awesome 5 on Kickstarter,\nand in return I received a license to use it and to access the pro features.\nThe license might be perpetual, but the pro features, sadly, are not \ud83d\ude22\u003C\/p\u003E\n\u003Cblockquote class=\u0022blockquote ml-4 pl-4 border-left\u0022\u003E\n\u003Cp\u003EIf you don\u0027t subscribe to a Pro plan, you won\u0027t be able to install Font Awesome Pro using npm or yarn.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EThat\u0027s the one feature I need! And on August 1\u003Csup\u003Est\u003C\/sup\u003E it will be gone!\nMy dev setup, my deployment setup, of multiple projects,\neverything depends on fetching Font Awesome from the npm registry.\u003C\/p\u003E\n\u003Cp\u003ELuckily, there\u0027s a simple way around it \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/fontawesome6_big.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022273.33333333333\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAKCAYAAADcpvzeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB\/ElEQVQ4jc2Tu46TMRCFvxnb\/5\/LLlBw03IRDQJKKCgoeAY6hCgpeAqejBdAFFQIKCmQENoQdkM2\/yW2h8LZTVIAKwQSR5rC42PP8fGMdG+fGoCZETM4AQOWEYIHsxIikDNkg+DKOq3WdRD+FjzAq\/eJ6cy4f9sxOTScA+8gxlI0+CIQAacQozGohEVnVEG4dK7wRIpAlRLLVPhOoe3Lmd3RtvjZkZHNCF4YDwTp3j2z9bZtkbHtjMjareLqOv8zHPPX537tpuSc7eM0Ukniwq4DM1S12Oc9y5jIOW8UMJxTvHMbQgWz7cfYxj2nwXK5xHtfvqyLgCQmk2+ICCllzIyrV\/bIOdP1PYKgTk9scap0fQ9myMqiEAKLpmFQD+j7nvF4dGpBbduxs+ORJ89f2O\/p\/x6fPu+zd\/k8cu3uI2u7npwzdRW4c\/MGANmMnDOz70eMR0OGw5qcMl2\/ZNG07H89+OPiTmF3uJ2LGebNaspq1\/HwXuDlm8SX\/enJ39dVIMbE9GCGzhSnStv1jIY1Z3bGqAoiJULwqCoxRlQVVSWlhHMKBk3bUVWBpulwsmBUC0etMR4IlYd5C\/PGiqBF73n9oTTraDRAEJq2o2k7RIXgHSkbIiuRKaEqGKAixFQa\/2A2P5VDZ8dw\/aKwOXFtD5NDQ249ePxf9NAxfgCKbvUuzuwSpgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/fontawesome6_big.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022273.33333333333\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/fontawesome.com\/icons?d=gallery\u0026s=brands,light\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        fontawesome.com\/icons\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFour years ago I backed Font Awesome 5 on Kickstarter,\nand in return I received a license to use it and to access the pro features.\nThe license might be perpetual, but the pro features, sadly, are not \ud83d\ude22\u003C\/p\u003E\n\u003Cblockquote class=\u0022blockquote ml-4 pl-4 border-left\u0022\u003E\n\u003Cp\u003EIf you don\u0027t subscribe to a Pro plan, you won\u0027t be able to install Font Awesome Pro using npm or yarn.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EThat\u0027s the one feature I need! And on August 1\u003Csup\u003Est\u003C\/sup\u003E it will be gone!\nMy dev setup, my deployment setup, of multiple projects,\neverything depends on fetching Font Awesome from the npm registry.\u003C\/p\u003E\n\u003Cp\u003ELuckily, there\u0027s a simple way around it \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EI\u0027m allowed by the license to download the project and create backups,\nbut obviously not to share it with others \u2013 so it\u0027s all done in a \u003Cstrong\u003Eprivate repository\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cp\u003EFirst, I fetched the latest version of the project:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyarn add @fortawesome\/fontawesome-pro\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThen, I just went to \u003Ccode\u003Enode_modules\/@fortawesome\/fontawesome-pro\u003C\/code\u003E,\ninitialised a fresh git repository there and pushed it to gitlab.com\/Avris\/FontAwesomePro.\u003C\/p\u003E\n\u003Cp\u003ENow, whenever I want to use FontAwesome 5 in a project, I just go:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyarn add git+ssh:\/\/git@gitlab.com:Avris\/FontAwesomePro.git\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd that\u0027s it!\u003C\/p\u003E\n\u003Cp\u003EI was surprised that it\u0027s so simple.\nOf course my repository won\u0027t get automatically updated with the project,\nbut since version 5 won\u0027t be developed anymore, it doesn\u0027t matter at all.\nAnd it works like a charm!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["fontawesome","icons","web development","hosting","gitlab","git","yarn","npm"],"hasMore":true,"image":"https:\/\/avris.it\/image\/fontawesome6_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/fontawesome6_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/fontawesome6_mini.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 width=\u0022240\u0022 height=\u002268.333333333333\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFour years ago I backed Font Awesome 5 on Kickstarter,\nand in return I received a license to use it and to access the pro features.\nThe license might be perpetual, but the pro features, sadly, are not \ud83d\ude22\u003C\/p\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EIf you don\u0027t subscribe to a Pro plan, you won\u0027t be able to install Font Awesome Pro using npm or yarn.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EThat\u0027s the one feature I need! And on August 1\u003Csup\u003Est\u003C\/sup\u003E it will be gone!\nMy dev setup, my deployment setup, of multiple projects,\neverything depends on fetching Font Awesome from the npm registry.\u003C\/p\u003E\n\u003Cp\u003ELuckily, there\u0027s a simple way around it \ud83d\ude09\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/fontawesome6_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/fontawesome6_mini.png\u0022 alt=\u0022Your year of Pro services for backing FA5 expire on August 1! Subscribe to the all-new Font Awesome 6 to extend your services and get the new version. Subscribe now for half the price. Just $49\/year!\u0022 width=\u0022240\u0022 height=\u002268.333333333333\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/fontawesome.com\/icons?d=gallery\u0026s=brands,light\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Efontawesome.com\/icons\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFour years ago I backed Font Awesome 5 on Kickstarter,\nand in return I received a license to use it and to access the pro features.\nThe license might be perpetual, but the pro features, sadly, are not \ud83d\ude22\u003C\/p\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EIf you don\u0027t subscribe to a Pro plan, you won\u0027t be able to install Font Awesome Pro using npm or yarn.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EThat\u0027s the one feature I need! And on August 1\u003Csup\u003Est\u003C\/sup\u003E it will be gone!\nMy dev setup, my deployment setup, of multiple projects,\neverything depends on fetching Font Awesome from the npm registry.\u003C\/p\u003E\n\u003Cp\u003ELuckily, there\u0027s a simple way around it \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EI\u0027m allowed by the license to download the project and create backups,\nbut obviously not to share it with others \u2013 so it\u0027s all done in a \u003Cstrong\u003Eprivate repository\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cp\u003EFirst, I fetched the latest version of the project:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyarn add @fortawesome\/fontawesome-pro\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThen, I just went to \u003Ccode\u003Enode_modules\/@fortawesome\/fontawesome-pro\u003C\/code\u003E,\ninitialised a fresh git repository there and pushed it to gitlab.com\/Avris\/FontAwesomePro.\u003C\/p\u003E\n\u003Cp\u003ENow, whenever I want to use FontAwesome 5 in a project, I just go:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyarn add git+ssh:\/\/git@gitlab.com:Avris\/FontAwesomePro.git\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd that\u0027s it!\u003C\/p\u003E\n\u003Cp\u003EI was surprised that it\u0027s so simple.\nOf course my repository won\u0027t get automatically updated with the project,\nbut since version 5 won\u0027t be developed anymore, it doesn\u0027t matter at all.\nAnd it works like a charm!\u003C\/p\u003E","words":227,"readTime":null,"lang":"en"}}},"blog\/technology\/going-lite":{"key":"blog\/technology\/going-lite","type":"article","published":true,"meta":{"createdAt":"2020-06-28T13:09:18+02:00","publishedAt":"2020-06-28T13:09:18+02:00","group":null,"links":[{"icon":"paper-plane","colour":"primary","url":"https:\/\/avris.it\/lite","displayUrl":null}],"category":"blog","subcategory":"technology","slug":"going-lite"},"content":{"en":{"slug":"going-lite","title":"Going lite \ud83d\ude09","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-lite_small.png\u0022 alt=\u0022Screenshot of the lite version of this blog\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022360.24144869215\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADUElEQVRIia2X227iVhSGv33wITYk0DiJWk07TaW0j9CX6Bv3Eare9qbNaJTOKJNJBoIxYOx96EUEDQQ7DPBLFtbm996f19qHZeGc80IIvPes\/65LCAHwwrPevs+9XjRsGvzP36\/5cjumLCp+\/e1nLn7ovfBsAt9Hwq\/1+JzaGoezDgAVKKR8Cd\/0xrt6dBvtuMiZzWZUVYXWmkAH1LlCKoGpHKffdTnqhlu9+bZqBer1emgZ8PHDI53+EelZQnoRr3gOnTL5mkEIgY4EOpR8uS2Yz+qDArwKtJ7ftJvw5pdThuMO\/96dUEwUzvlG\/8GBNslaS13k2OKBv\/54YF4elGFFL1bZuoyxPNwbZlPN2bkk7TRH5RCrTHrvabucc0wnHmPg\/Tu3fHjT1fTf8\/bXPI0b40LOOrpJyejzkONIA9lXz5umqGzy6NeWbV3XTKcT0n7E+Zs+zjm89wwGA5IkIU3TraG2Am+bQ9ZanHNbDfg10lo3Rqw1Qvf39xRFwduzOe8+aZRShGFIVVU457i6utoZqmnc1ggVRQGAlBJrLUEQYK1FCIG1Fu89Simccwgh6HQ6OwMu1Boh5xx5nhNFEUIIRqPR08TTGmMMcRxTluUSdtv51ArUNvuvr6+5ubkhTVPSNCXLsr3StI2Ee34OrOl5AbZIy+JeSrmxqNv3KGk97fM85+7uDmmnVO4UY+copZhOZpxmHbyv0VpTliUnJydorcmy7HBA6xVgVVUopRmOAiZFhRCKIFBU85i040gShfeeXq9HXdfLKwiCnYFWUraxJPWe\/OMHHscxSitMbRECemcpx1myfO7J6hv72dbTCjQcDsnzp6oxjmKqukIICIIQKeVTexyv7EtSyo0fC01A655WIOcctXGMHnKmQ0OcAMy5H31LHENVwcUFnHzj0Vr\/3+k+QG0b42Aw4NOjISBnVhiSJMEzx9SgVYhUhqMwQYWK0egR7z2Xl5eE4e51tm5auovSQ9mCf94\/Ms+P6PU93eOau1tNp2v4\/q2kdhXzqUNrzfn5+XJCHyRlm2Rqw+e\/hwxMnzD0\/PjTk31xQC72pOeD7qoVIGMM1toVw3A4ZDKZMB6PiaKIsizRWhNF0dJrrSXLMvr9\/l4wQRAgpeQ\/IlqSidy6tlkAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-lite_small.png\u0022 alt=\u0022Screenshot of the lite version of this blog\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022360.24144869215\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI \u003Ca href=\u0022\/blog\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E strive to optimise\u003C\/a\u003E\nthis blog\u0027s performance as well as I can. But chasing a goal of a lightweight website while keeping it \u003Cem\u003Epretty\u003C\/em\u003E\nprevented me from realising the obvious truth that the most performant assets are\u2026 \u003Cem\u003Eno assets\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003ESo, inspired by \u003Ca href=\u0022https:\/\/sjmulder.nl\/en\/textonly.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Sijmen J. Mulder\u0027s directory of text-only websites\u003C\/a\u003E,\nI decided to create a bare version of my blog.\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s how it went:\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-lite_big.png\u0022 alt=\u0022Screenshot of the lite version of this blog\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022720.48289738431\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADUElEQVRIia2X227iVhSGv33wITYk0DiJWk07TaW0j9CX6Bv3Eare9qbNaJTOKJNJBoIxYOx96EUEDQQ7DPBLFtbm996f19qHZeGc80IIvPes\/65LCAHwwrPevs+9XjRsGvzP36\/5cjumLCp+\/e1nLn7ovfBsAt9Hwq\/1+JzaGoezDgAVKKR8Cd\/0xrt6dBvtuMiZzWZUVYXWmkAH1LlCKoGpHKffdTnqhlu9+bZqBer1emgZ8PHDI53+EelZQnoRr3gOnTL5mkEIgY4EOpR8uS2Yz+qDArwKtJ7ftJvw5pdThuMO\/96dUEwUzvlG\/8GBNslaS13k2OKBv\/54YF4elGFFL1bZuoyxPNwbZlPN2bkk7TRH5RCrTHrvabucc0wnHmPg\/Tu3fHjT1fTf8\/bXPI0b40LOOrpJyejzkONIA9lXz5umqGzy6NeWbV3XTKcT0n7E+Zs+zjm89wwGA5IkIU3TraG2Am+bQ9ZanHNbDfg10lo3Rqw1Qvf39xRFwduzOe8+aZRShGFIVVU457i6utoZqmnc1ggVRQGAlBJrLUEQYK1FCIG1Fu89Simccwgh6HQ6OwMu1Boh5xx5nhNFEUIIRqPR08TTGmMMcRxTluUSdtv51ArUNvuvr6+5ubkhTVPSNCXLsr3StI2Ee34OrOl5AbZIy+JeSrmxqNv3KGk97fM85+7uDmmnVO4UY+copZhOZpxmHbyv0VpTliUnJydorcmy7HBA6xVgVVUopRmOAiZFhRCKIFBU85i040gShfeeXq9HXdfLKwiCnYFWUraxJPWe\/OMHHscxSitMbRECemcpx1myfO7J6hv72dbTCjQcDsnzp6oxjmKqukIICIIQKeVTexyv7EtSyo0fC01A655WIOcctXGMHnKmQ0OcAMy5H31LHENVwcUFnHzj0Vr\/3+k+QG0b42Aw4NOjISBnVhiSJMEzx9SgVYhUhqMwQYWK0egR7z2Xl5eE4e51tm5auovSQ9mCf94\/Ms+P6PU93eOau1tNp2v4\/q2kdhXzqUNrzfn5+XJCHyRlm2Rqw+e\/hwxMnzD0\/PjTk31xQC72pOeD7qoVIGMM1toVw3A4ZDKZMB6PiaKIsizRWhNF0dJrrSXLMvr9\/l4wQRAgpeQ\/IlqSidy6tlkAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-lite_big.png\u0022 alt=\u0022Screenshot of the lite version of this blog\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022720.48289738431\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI \u003Ca href=\u0022\/blog\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E strive to optimise\u003C\/a\u003E\nthis blog\u0027s performance as well as I can. But chasing a goal of a lightweight website while keeping it \u003Cem\u003Epretty\u003C\/em\u003E\nprevented me from realising the obvious truth that the most performant assets are\u2026 \u003Cem\u003Eno assets\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003ESo, inspired by \u003Ca href=\u0022https:\/\/sjmulder.nl\/en\/textonly.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Sijmen J. Mulder\u0027s directory of text-only websites\u003C\/a\u003E,\nI decided to create a bare version of my blog.\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s how it went:\u003C\/p\u003E\n\u003Cp\u003EMany pages of this blog are already available in multiple formats, eg. \u003Ca href=\u0022\/posts.atom\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E  the Atom feed of all entries\u003C\/a\u003E\nor \u003Ca href=\u0022\/projects.json\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E a JSON version of the list of my projects\u003C\/a\u003E,\nso adding a new one, \u003Ccode\u003E.lite\u003C\/code\u003E, was relatively easy.\u003C\/p\u003E\n\u003Cp\u003EThe main part was copy-pasting all \u003Ccode\u003E\u0026lt;page-type\u0026gt;.html.twig\u003C\/code\u003E files to \u003Ccode\u003E\u0026lt;page-type\u0026gt;.lite.twig\u003C\/code\u003E\nand removing all the bullshit from them. All the HTML nodes that exist solely to make the page look nicer:\nwrappers, containers, columns, etc. All the icons, fonts, logos, twemoji, everything that\u0027s not essential.\u003C\/p\u003E\n\u003Cp\u003EThere\u0027s no JavaScript loaded whatsoever.\u003C\/p\u003E\n\u003Cp\u003EThere\u0027s no external stylesheets loaded, just some minimal\nstyling in \u003Ccode\u003E\u0026lt;style\u0026gt;\u003C\/code\u003E tag and few inline \u003Ccode\u003Estyle\u003C\/code\u003E attributes.\u003C\/p\u003E\n\u003Cp\u003EImages inside articles had to stay, becuase in many cases they are a very important part of the content, and not just decoration.\nBut I made them way smaller \u2013 max 240px in width \u2013 and linked to open a bigger version, if necessary.\nI also replaced the JS-based lazy loading with HTML5 native \u003Ccode\u003Eloading=\u0022lazy\u0022\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EHowever, the browser support for this feature is still not perfect \u2013 and if it doesn\u0027t work on someone\u0027s machine,\nthey\u0027ll have to download 8 MB (!) of tiny images when visiting \u003Ccode\u003E\/blog.lite\u003C\/code\u003E\u2026\nSo I implemented a simple pagination, all inside a Twig template, based on \u003Ccode\u003E?after=\u0026lt;timestamp\u0026gt;\u003C\/code\u003E parameter in the query string.\u003C\/p\u003E\n\u003Cp\u003EAnyways\u2026 It\u0027s time for the results! \ud83e\udd41\u003C\/p\u003E\n\u003Cp\u003ENormally, opening the the homepage makes 40 requests and loads 522 kB of resources.\nIn the lite version, it\u0027s 2 requests (HTML and favicon) that weight just 15.8 kB.\nJust \u003Cstrong\u003E3%\u003C\/strong\u003E of the original weight!\u003C\/p\u003E\n\u003Cp\u003EThe heaviest page, \u003Ccode\u003E\/blog\u003C\/code\u003E makes 37 requests of 3.5 MB.\nIn the lite version, it\u0027s 10 requests of 198 kB.\nJust \u003Cstrong\u003E6%\u003C\/strong\u003E of the original weight.\u003C\/p\u003E\n\u003Cp\u003EOpening a random article made 34 requests of 493 kB normally,\nand just 3 requests of 31.2 kB in the lite version.\nAlso just \u003Cstrong\u003E6%\u003C\/strong\u003E of the original weight.\u003C\/p\u003E\n\u003Cp\u003EThe differences are huuuuuuuge!\u003C\/p\u003E\n\u003Cp\u003ESumming up: if you don\u0027t mind websites looking ascetic in return for loading quicker, working smoother,\nand sparing data plan and battery,\ndefinitely check out \u003Ca href=\u0022https:\/\/sjmulder.nl\/en\/textonly.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Sijmen\u0027s directory\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EAnd on my blog you can just head to \u003Ca href=\u0022\/lite\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \/lite\u003C\/a\u003E or add \u003Ccode\u003E.lite\u003C\/code\u003E at the end of any subpage. \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["web development","development","programming","optimisation","light","text","html"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-lite_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-lite_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-lite_mini.png\u0022 alt=\u0022Screenshot of the lite version of this blog\u0022 width=\u0022240\u0022 height=\u0022180.12072434608\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI \u003Ca href=\u0022\/blog\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome.lite\u0022\u003E strive to optimise\u003C\/a\u003E\nthis blog\u0027s performance as well as I can. But chasing a goal of a lightweight website while keeping it \u003Cem\u003Epretty\u003C\/em\u003E\nprevented me from realising the obvious truth that the most performant assets are\u2026 \u003Cem\u003Eno assets\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003ESo, inspired by \u003Ca href=\u0022https:\/\/sjmulder.nl\/en\/textonly.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Sijmen J. Mulder\u0027s directory of text-only websites\u003C\/a\u003E,\nI decided to create a bare version of my blog.\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s how it went:\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-lite_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-lite_mini.png\u0022 alt=\u0022Screenshot of the lite version of this blog\u0022 width=\u0022240\u0022 height=\u0022180.12072434608\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI \u003Ca href=\u0022\/blog\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome.lite\u0022\u003E strive to optimise\u003C\/a\u003E\nthis blog\u0027s performance as well as I can. But chasing a goal of a lightweight website while keeping it \u003Cem\u003Epretty\u003C\/em\u003E\nprevented me from realising the obvious truth that the most performant assets are\u2026 \u003Cem\u003Eno assets\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003ESo, inspired by \u003Ca href=\u0022https:\/\/sjmulder.nl\/en\/textonly.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Sijmen J. Mulder\u0027s directory of text-only websites\u003C\/a\u003E,\nI decided to create a bare version of my blog.\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s how it went:\u003C\/p\u003E\n\u003Cp\u003EMany pages of this blog are already available in multiple formats, eg. \u003Ca href=\u0022\/posts.atom\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E  the Atom feed of all entries\u003C\/a\u003E\nor \u003Ca href=\u0022\/projects.json\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E a JSON version of the list of my projects\u003C\/a\u003E,\nso adding a new one, \u003Ccode\u003E.lite\u003C\/code\u003E, was relatively easy.\u003C\/p\u003E\n\u003Cp\u003EThe main part was copy-pasting all \u003Ccode\u003E\u0026lt;page-type\u0026gt;.html.twig\u003C\/code\u003E files to \u003Ccode\u003E\u0026lt;page-type\u0026gt;.lite.twig\u003C\/code\u003E\nand removing all the bullshit from them. All the HTML nodes that exist solely to make the page look nicer:\nwrappers, containers, columns, etc. All the icons, fonts, logos, twemoji, everything that\u0027s not essential.\u003C\/p\u003E\n\u003Cp\u003EThere\u0027s no JavaScript loaded whatsoever.\u003C\/p\u003E\n\u003Cp\u003EThere\u0027s no external stylesheets loaded, just some minimal\nstyling in \u003Ccode\u003E\u0026lt;style\u0026gt;\u003C\/code\u003E tag and few inline \u003Ccode\u003Estyle\u003C\/code\u003E attributes.\u003C\/p\u003E\n\u003Cp\u003EImages inside articles had to stay, becuase in many cases they are a very important part of the content, and not just decoration.\nBut I made them way smaller \u2013 max 240px in width \u2013 and linked to open a bigger version, if necessary.\nI also replaced the JS-based lazy loading with HTML5 native \u003Ccode\u003Eloading=\u0022lazy\u0022\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EHowever, the browser support for this feature is still not perfect \u2013 and if it doesn\u0027t work on someone\u0027s machine,\nthey\u0027ll have to download 8 MB (!) of tiny images when visiting \u003Ccode\u003E\/blog.lite\u003C\/code\u003E\u2026\nSo I implemented a simple pagination, all inside a Twig template, based on \u003Ccode\u003E?after=\u0026lt;timestamp\u0026gt;\u003C\/code\u003E parameter in the query string.\u003C\/p\u003E\n\u003Cp\u003EAnyways\u2026 It\u0027s time for the results! \ud83e\udd41\u003C\/p\u003E\n\u003Cp\u003ENormally, opening the the homepage makes 40 requests and loads 522 kB of resources.\nIn the lite version, it\u0027s 2 requests (HTML and favicon) that weight just 15.8 kB.\nJust \u003Cstrong\u003E3%\u003C\/strong\u003E of the original weight!\u003C\/p\u003E\n\u003Cp\u003EThe heaviest page, \u003Ccode\u003E\/blog\u003C\/code\u003E makes 37 requests of 3.5 MB.\nIn the lite version, it\u0027s 10 requests of 198 kB.\nJust \u003Cstrong\u003E6%\u003C\/strong\u003E of the original weight.\u003C\/p\u003E\n\u003Cp\u003EOpening a random article made 34 requests of 493 kB normally,\nand just 3 requests of 31.2 kB in the lite version.\nAlso just \u003Cstrong\u003E6%\u003C\/strong\u003E of the original weight.\u003C\/p\u003E\n\u003Cp\u003EThe differences are huuuuuuuge!\u003C\/p\u003E\n\u003Cp\u003ESumming up: if you don\u0027t mind websites looking ascetic in return for loading quicker, working smoother,\nand sparing data plan and battery,\ndefinitely check out \u003Ca href=\u0022https:\/\/sjmulder.nl\/en\/textonly.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Sijmen\u0027s directory\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EAnd on my blog you can just head to \u003Ca href=\u0022\/lite\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \/lite\u003C\/a\u003E or add \u003Ccode\u003E.lite\u003C\/code\u003E at the end of any subpage. \ud83d\ude09\u003C\/p\u003E","words":414,"readTime":2,"lang":"en"}}},"blog\/technology\/redesigning-a-website-naked-adventure":{"key":"blog\/technology\/redesigning-a-website-naked-adventure","type":"article","published":true,"meta":{"createdAt":"2020-05-23T22:45:46+02:00","publishedAt":"2020-05-23T22:45:46+02:00","group":"redesign","links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/naked-adventure.eu","displayUrl":null}],"category":"blog","subcategory":"technology","slug":"redesigning-a-website-naked-adventure"},"content":{"en":{"slug":"redesigning-a-website-naked-adventure","title":"Redesigning a website: Naked Adventure","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-revamp_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022323.41488807913\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHx0lEQVRIiaWWy48cVxnFf\/dRr65+THfPjD0zHj\/iJI5IFAnHJBHEioJAiCAkImUHiC0LFglISKxZwJ+AEiGxgA0SAgmxCAvEBhZBCQ85ColfsROPZzzueXV3dT3uvR+L9kxiQjbkbKpUdUvn3O+c77ulnvre7yUxiuVehtYah8EYTTuP0FqDUhSVwzshBEGUIo00mTRMVMysFuqm5trlEf1ejgTHeFzwQPdPRHrKv29qVpd63L57gFKKOI5JEnhoeAenh+RmG60bnAp02zn2hfWGTEM3DmSxJWl3aecxJ9f6LK\/1McYQghBCYFY0RGlMUQtRrHFBcVB4alfzzZ9ucTCpsKoheIfWnuVOwWihw82NEdpoEGGx3+LFL18Ev81b\/3qNPAZvLAZHXY2xiYZWZGillsgo2rail0bgS+5sbaAjTfAeazRLx1aIs4yWKKomUNZCP7aUpRBZTZxoZqVClGah1XBr3zJzFqUcwXlEhGJaMZ3cQIdAJ824vG1Z6lSs5AmJK7HPPnkGAgQfGB8UaF+jfAWNZlrOyAdtRAnGRKR5glcG8UISG6wVahfwQROphtnU0W1pGkru7jVcvgF1s4PWljhNcFXN8UGLWzc3ePv9PTA91lq7dIPgSkuoNXby3l\/oL51gcXWV9OQQBFCgECYzodaC7fbJshwdR2gJWB2Q4BEViJXHuBkqlCy0EopZgW9K9sISSbRNEkVEcYr3jrzT4sK6ZWD3OPeYZTytmLkeeewZFYrltePYevsm195\/j+23Y9bWThBFhlZnAZN1GAwHxMMhujtABPzuNlUjNEFRV55JUVFUnp29A8QVBO0wUlOWE37245fp9hZ4b3NKEOHJR\/pEBowxfBKUUtjW8mk6CJGG0sMsCAfS0DWgixLTqRBREAJeBKUEowJWO1qxYEQwHUtV7INL0MqDmwKBwSBGZQLATl0D9wxQIAJxZI\/EZMbQSyLs09\/6LlVVsbm5yfr6+rzVPwGm1fufz6uqQurf4aWiqEqapgQJJAi5r8mzjCRN+cUfb\/C3d3fwrqBtJhw\/cZrNvZpqb4Ozi56Xvv08FkBrTavVYjweA9DpdJh5zdZ+gUIxDjEdtpk0W+yFFbQfYXTFQpLwwOJZACazBt0o2mZGCCUi866K4xhjLd57lswGZ5vXWe8I7WOr\/Py1PzDZuc1J\/S7m\/JPA81ilQJmIie6jyymdyANQOMWbey1SDqiC4BtNphWTsqITrpC0YqYzODM8AyjGdy6D0qSLXaqiQEIghMBkPKGpa7rdLmsLUC136VrIO22+9NmEY9lpHlh9GpcM5xkSAQXksUbbBGsC3ntAIwLVdJM33tljtR+wMuWJczOKKiFKDJE1KKUQwNdjlNJUBYhvUAijSeDGSKNNQG7v8tDpR1hZPUOn1yXLMh5+fBejNL2FeRREZG6ZiOBcg7UxThqKsgYbgVL47AwPr7zBqeGEK9cnSK1pRwlJlDKMM6zSNAR8PUEpDT5iNp0ymYy5M9vizSt3CQEiHAfnVtmcBJSu6aYGWxZs71WU02ucOtbi4hNrWKUUu7PA9397wDDX1E4oauGFJww6i2nKESoIt\/aHdAddtkZjuoMVboc1VLjLksy7aPXzP0CZmGP9iOmkIO2uYPxfCfUrCOCA6p1naa5ewhpF1V3mN3++wgcf3CSKIr7w7HN85eJPsCJClo754jOvkpkcEGa+4NHlr7OefobgcqL4PE7FGAJN3RCbeQMrtYI1Md5V82kKFKVHmM+bB9e\/yHLvUbIkJUkTXn\/tV2SxIwRoRY5zJ4+zNIhZWBhiIosxZm5ZIi2+ln+Hfr9PnufIvV0rpRDpsLGxQZ7ndHo9iO7l5iNr5rY7CBqrYeYaQEjjnGFvlSzLUEox7C\/yfujTHyRESZ9HL5wh67SoixnLaycB5pYZY8jzHGMMInJEckio4pzSQVQ7Yq3QWn1s4gZXo3QgNAZXzxAJxHFMHMdHa85e+AanHv8q\/cEQrTWTyQSjIMvbR1xWRAgCe9OGSelYHiiiKLpPVKwcdV2zvzNDHVVOiKKI4XA4F9QUKG1pKoOSCpCjKh5iey9QNpqbox12Nt7iqc+dJ05beO9pmoYsy+aWKQV5q4XWCo8lvifmkHi\/STDeEqeBNI7QzHefpimHultqRukNo50KcRXB+\/uqLCJcvT3m+t2CNLUcXLnGr3\/5KosLbbwIKycf5KWXfzi37N5X+CD44FHq0I65fScX06M5cX\/15CjMYTYikOLrCvE1BP8x60c3\/sHW1esUtePO+29x8cFF9rc3cM5xqvvwh5YZrVnII6y19wX2kNRay0fx3+8B6mqG6BpflQRfHx0dH8Vzz5znwmOnSbMWcfQiabuLNZq83TniPWISZWkCOC9oBVqDD2DvXfX8DxQFBEADRivMvbNY3D6VA1fXiG+Q8HHL+oMhvYU+aTqvuHMOrfV9HWsvXbrEp0Vd17jpPsZGVGWBiONHr\/yT5eMjklhRlnORVVnQ1AWprimLA6rigLMnemxtbrKzcxfxDXZ3d\/dTC2qahtBMqGqFb+b5ufrBPptFG60E39SEpkLCjGKyTyQzivEOrtynHa\/z90vvMrq7jfgafViqQ\/y\/92VVIL4iuA8zFLxHiQfxKOWJjNBKFHVdg3hEPJev32Jvb8xhFv8DbBYDPiGD0eUAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/naked-revamp_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022323.41488807913\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYet another one of my projects, \u003Ca href=\u0022\/projects\/naked-adventure-de\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Naked Adventure\u003C\/a\u003E,\ngrew too outdated to support it. I had to rewrite it from scratch.\u003C\/p\u003E\n\u003Cp\u003EI took the opportunity to redesign it as well. (screenshots before \u0026amp; after at the bottom)\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-revamp_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022646.82977615825\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHx0lEQVRIiaWWy48cVxnFf\/dRr65+THfPjD0zHj\/iJI5IFAnHJBHEioJAiCAkImUHiC0LFglISKxZwJ+AEiGxgA0SAgmxCAvEBhZBCQ85ColfsROPZzzueXV3dT3uvR+L9kxiQjbkbKpUdUvn3O+c77ulnvre7yUxiuVehtYah8EYTTuP0FqDUhSVwzshBEGUIo00mTRMVMysFuqm5trlEf1ejgTHeFzwQPdPRHrKv29qVpd63L57gFKKOI5JEnhoeAenh+RmG60bnAp02zn2hfWGTEM3DmSxJWl3aecxJ9f6LK\/1McYQghBCYFY0RGlMUQtRrHFBcVB4alfzzZ9ucTCpsKoheIfWnuVOwWihw82NEdpoEGGx3+LFL18Ev81b\/3qNPAZvLAZHXY2xiYZWZGillsgo2rail0bgS+5sbaAjTfAeazRLx1aIs4yWKKomUNZCP7aUpRBZTZxoZqVClGah1XBr3zJzFqUcwXlEhGJaMZ3cQIdAJ824vG1Z6lSs5AmJK7HPPnkGAgQfGB8UaF+jfAWNZlrOyAdtRAnGRKR5glcG8UISG6wVahfwQROphtnU0W1pGkru7jVcvgF1s4PWljhNcFXN8UGLWzc3ePv9PTA91lq7dIPgSkuoNXby3l\/oL51gcXWV9OQQBFCgECYzodaC7fbJshwdR2gJWB2Q4BEViJXHuBkqlCy0EopZgW9K9sISSbRNEkVEcYr3jrzT4sK6ZWD3OPeYZTytmLkeeewZFYrltePYevsm195\/j+23Y9bWThBFhlZnAZN1GAwHxMMhujtABPzuNlUjNEFRV55JUVFUnp29A8QVBO0wUlOWE37245fp9hZ4b3NKEOHJR\/pEBowxfBKUUtjW8mk6CJGG0sMsCAfS0DWgixLTqRBREAJeBKUEowJWO1qxYEQwHUtV7INL0MqDmwKBwSBGZQLATl0D9wxQIAJxZI\/EZMbQSyLs09\/6LlVVsbm5yfr6+rzVPwGm1fufz6uqQurf4aWiqEqapgQJJAi5r8mzjCRN+cUfb\/C3d3fwrqBtJhw\/cZrNvZpqb4Ozi56Xvv08FkBrTavVYjweA9DpdJh5zdZ+gUIxDjEdtpk0W+yFFbQfYXTFQpLwwOJZACazBt0o2mZGCCUi866K4xhjLd57lswGZ5vXWe8I7WOr\/Py1PzDZuc1J\/S7m\/JPA81ilQJmIie6jyymdyANQOMWbey1SDqiC4BtNphWTsqITrpC0YqYzODM8AyjGdy6D0qSLXaqiQEIghMBkPKGpa7rdLmsLUC136VrIO22+9NmEY9lpHlh9GpcM5xkSAQXksUbbBGsC3ntAIwLVdJM33tljtR+wMuWJczOKKiFKDJE1KKUQwNdjlNJUBYhvUAijSeDGSKNNQG7v8tDpR1hZPUOn1yXLMh5+fBejNL2FeRREZG6ZiOBcg7UxThqKsgYbgVL47AwPr7zBqeGEK9cnSK1pRwlJlDKMM6zSNAR8PUEpDT5iNp0ymYy5M9vizSt3CQEiHAfnVtmcBJSu6aYGWxZs71WU02ucOtbi4hNrWKUUu7PA9397wDDX1E4oauGFJww6i2nKESoIt\/aHdAddtkZjuoMVboc1VLjLksy7aPXzP0CZmGP9iOmkIO2uYPxfCfUrCOCA6p1naa5ewhpF1V3mN3++wgcf3CSKIr7w7HN85eJPsCJClo754jOvkpkcEGa+4NHlr7OefobgcqL4PE7FGAJN3RCbeQMrtYI1Md5V82kKFKVHmM+bB9e\/yHLvUbIkJUkTXn\/tV2SxIwRoRY5zJ4+zNIhZWBhiIosxZm5ZIi2+ln+Hfr9PnufIvV0rpRDpsLGxQZ7ndHo9iO7l5iNr5rY7CBqrYeYaQEjjnGFvlSzLUEox7C\/yfujTHyRESZ9HL5wh67SoixnLaycB5pYZY8jzHGMMInJEckio4pzSQVQ7Yq3QWn1s4gZXo3QgNAZXzxAJxHFMHMdHa85e+AanHv8q\/cEQrTWTyQSjIMvbR1xWRAgCe9OGSelYHiiiKLpPVKwcdV2zvzNDHVVOiKKI4XA4F9QUKG1pKoOSCpCjKh5iey9QNpqbox12Nt7iqc+dJ05beO9pmoYsy+aWKQV5q4XWCo8lvifmkHi\/STDeEqeBNI7QzHefpimHultqRukNo50KcRXB+\/uqLCJcvT3m+t2CNLUcXLnGr3\/5KosLbbwIKycf5KWXfzi37N5X+CD44FHq0I65fScX06M5cX\/15CjMYTYikOLrCvE1BP8x60c3\/sHW1esUtePO+29x8cFF9rc3cM5xqvvwh5YZrVnII6y19wX2kNRay0fx3+8B6mqG6BpflQRfHx0dH8Vzz5znwmOnSbMWcfQiabuLNZq83TniPWISZWkCOC9oBVqDD2DvXfX8DxQFBEADRivMvbNY3D6VA1fXiG+Q8HHL+oMhvYU+aTqvuHMOrfV9HWsvXbrEp0Vd17jpPsZGVGWBiONHr\/yT5eMjklhRlnORVVnQ1AWprimLA6rigLMnemxtbrKzcxfxDXZ3d\/dTC2qahtBMqGqFb+b5ufrBPptFG60E39SEpkLCjGKyTyQzivEOrtynHa\/z90vvMrq7jfgafViqQ\/y\/92VVIL4iuA8zFLxHiQfxKOWJjNBKFHVdg3hEPJev32Jvb8xhFv8DbBYDPiGD0eUAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/naked-revamp_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022646.82977615825\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYet another one of my projects, \u003Ca href=\u0022\/projects\/naked-adventure-de\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Naked Adventure\u003C\/a\u003E,\ngrew too outdated to support it. I had to rewrite it from scratch.\u003C\/p\u003E\n\u003Cp\u003EI took the opportunity to redesign it as well. (screenshots before \u0026amp; after at the bottom)\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s an overview of what I did:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ereplaced my abandoned framework \u003Ca href=\u0022\/projects\/micrus-v4\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus v4 \u2022 Beauty of simplicity\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony 5\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Ebased the project on \u003Ca href=\u0022\/projects\/avris-booster-quick-start-of-new-projects\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Avris Booster: Quick start of new projects\u003C\/a\u003E, to take advantage of built-in features:\nuser management (including a passwordless approach to authentication \u2013 \u003Ca href=\u0022\/blog\/passwords-are-pass%C3%A9\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Passwords are pass\u00e9\u003C\/a\u003E), push notifications, etc.\u003C\/li\u003E\n\u003Cli\u003Ereplaced \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Micrus-Assetic\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E custom Assetic setup\u003C\/a\u003E\nwith \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/frontend\/encore\/installation.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Webpack Encore\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Eupdated \u003Ca href=\u0022https:\/\/getbootstrap.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Bootstrap\u003C\/a\u003E from 3.0 to 4.4,\u003C\/li\u003E\n\u003Cli\u003Eadded more contrast to the design, filled the excess of white spaces with content, making filters and maps more prominent,\u003C\/li\u003E\n\u003Cli\u003Ereplaced Google Maps with Apple Maps, because of privacy concerns (see: \u003Ca href=\u0022\/blog\/ungoogling\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Ungoogling\u003C\/a\u003E, \u003Ca href=\u0022\/blog\/log-out-for-privacy\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Log out for privacy\u003C\/a\u003E) \u2013 the website is now officially Google-free,\u003C\/li\u003E\n\u003Cli\u003Eremoved a couple of unnecessary and unused features:\n\u003Cul\u003E\n\u003Cli\u003Ethe homepage (now the user is shown the map right away \u2013 after all, the map is the whole point of the project),\u003C\/li\u003E\n\u003Cli\u003Ethe \u201dgeographic\u201d links (there\u0027s no separate map of e.g. German nude beaches anymore, it got integrated into the main map),\u003C\/li\u003E\n\u003Cli\u003Eseparate events section (now they show up together with places on the same map),\u003C\/li\u003E\n\u003Cli\u003Eforum (it wasn\u0027t used at all),\u003C\/li\u003E\n\u003Cli\u003Eadmin panel (now the buttons for admins are just integrated across the website),\u003C\/li\u003E\n\u003C\/ul\u003E\u003C\/li\u003E\n\u003Cli\u003Eimproved filters (for instance added filtering by name and location),\u003C\/li\u003E\n\u003Cli\u003Ethe process of submission of new steps isn\u0027t split into steps anymore: place info, review and description are finally just one single form,\u003C\/li\u003E\n\u003Cli\u003Eincluded some more \u003Ca href=\u0022\/blog\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E optimisations\u003C\/a\u003E.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EBefore:\u003C\/h3\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-before-home_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221147.3333333333\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAkCAYAAACe0YppAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHV0lEQVRYhc2XS48dVxWFv30e9bhV97offsUPHJLYMpFQeCTioUiIARIC8Q9QxvwAxvyijBig8AMACSkSgQFECbZjE8duu93dt\/s+quqcvRlcu7svcRIYEFjDe+4+66y99llVJaO33jGe4tr5BlQBmPcZL8L+fGBSB6aLxJlRYNZl2jKwNxvokvJZEOBbX6nYvfuYT8KEunDsz9PxevjljSMcUAoUYUFdlBQxEooCQkGMYzYnkbObNXVTYghlFXDOkfpEVmXoMvN5QoJHRMgIQzYyjhheQg2cd8w7YzFAXTpCHR1RhNIZUYTK9ZRO8SKE4CkjxKyEFDk3aambipSUsozo0+44JxxN5yQVmrbicJ4YFGJ0eC+YCcmMo4WBgHMQNCXMe0wcMQZidIAS6aljoCodo5GnKozoFeeUGAQfBDGH5Yw4aNqI4YlVpBqXmK36rQqH88x8kYnFitQ7CG0ViSLUwVEXEINDEGJwBAacCYGI08TdO\/eQwmFOQQTnhGG+wATOn7\/I+YuXwDnEOfpB6QYjqeG8Y9IKApgZ3WCEN75+FTEFNQQYktL1inYLggePYqlHkzCuW3Zne5RtBCekviMGY9SM2dyY4KOQbNVaNaGMwsgLqsaQjT4pGXBBCOOREIoWyxnvQFXoFksWc8NpxovhJCPWYcNALYnaFdSbEwgR74Sh7wltg68qyEZWoxRBBLIaiBH8ahbMwDDCw7+\/y9a5S9R1RdOOGZ1pkLMtpg3Oe8Q5ADQNdMsF3d4MrOfwcErRjjEXERfJGGaKE0PciswwnBjmDGy1bqqYGaF99Ece38087iqIFW+8dp1z117FO4\/zHmTlmQuB5kxke\/sqyUcO+wFXNEy2zhG8QE6Qe7IqlpWcVwSalKxKSpmUMzkrqkbYyRcgwAvjEi\/Cw7u7HDz4A2V0mCnjjS2qUYvFiqKuaTY38KOW7XELVYE4sOUUm89Iy4F+gCyOrELKRt9nll3PvOvpE3TLnsNlTxhXBajiyThTvBna9XQDmDjSkz047Gm3ztKIEKf7jJxCXUBKoAnSQF7MyUNGTPDicQCaUVUKG5hs1PSDktqASUM4\/43vIRgOwTtwrIZiFXqQcYgviUWBRM8QPV1dEXyDxBFQQLUFocWp4syOffSqFKrkIdMte4wBCSsrRFWPs\/rLRJCVPADefvttbt68yfXr1ynL8lN\/7jOcHPNpNAE6zBHAR49SgHZoVnz0wCoJRYTCF8d7rSm+ffs2dV0jIgzDAEDbtmxsbABw50mHLQ9XbRfHnUXF+VoZ2RP6dMTt6S325fs09meyFSABZ\/s0Qfjqxktc2b56ovi0oo0L11ADzYlJvUREGI\/Hx+sfLUp25iXMYOQWdCbcXxa0aZ+MUriGIQl\/u1dy44UnhCIjElgk5db+h2vE7jTx7kyZLpXpbMHuYccwDMxms+d6FPNDdHGfnJR7R5dx6nl0UBBD4JXxfbz1CIZ0iWBGGYq1+jWPt5vVOaweYwZeF6SUGIaBolgVikAxPODegwfcvn+EazMXNpVFPOCv7z\/mR9\/5C\/WlMft7M6oYkRK8c5TBcZprrdVPZkpSw1uHt4EmQhnXmrI6WKzZvnyDOzt\/osqf0C4esHso\/PT1CVsjZaCkn2SqGDEyRSjYCqPTO5wmNrYat3pbkBFJofCrKV4sjo4VYzBwhpQXbG5O+OaVGU29wXsfHPHBrUNeeTFjAUo8osJ43FBJyUROa5TTxMKv330EcbTWkhUcL59bQlk9u0GEWLPZjrn1jx0uTHo+uJu5erGmCRX7yxnjdsK8uMbjTrk62sMV59Y9NjvJj99+6HgwnfG1C5Gdo0xwwnIwDpbKj1+t+e7NiFPl\/Y8e8YOXdykvZX7zu4ILL77Om9\/eQXzLO+99yJs3PHv5LI9mm4Dj4HDJa9sLxpMTLrFTzL\/4\/U94tPyEcdzA4UBglg5JOvDDiz\/j5y\/+ij4r89khk1IpYmDGGMQjopSy4PHU2K4zmKx8AcQ5vBPa5uRq\/s8ic21kP\/74Y7quY7lc\/lvFBwcHHB0d0XXdf0y8do+HYWBnZ4e6rqnr+guLp9Mp3ntUlStXrjxnKJ\/hJNePiU8PV1VViAgigqp+zkYrLKyin\/d4J9zf3WVjvIUnYZoJIRDC6Su07uh6gMyNIWWcDCy7h1y+dPFziTdroQ+CqZEWC\/aW9wEQEcwMM8M5h6oyGo3Y2to6IV6pWrXi8nZDCP64uO97gOc+IgE6qVEfMWcIhi8AdQTJ5LSKWe89ZVlSVdXzFK9a2kvFfIDgQJzHJ2Gr8Z+h12gKIQ1GcI6UFdWBUVkBDovhWECM8bjmGdeaxz4dUYZAzhlLRtO2mH06q59hUFgmqMUwgxDcsULv1w98wvP0bp8OkHuPjhBxGEJwSigqthuH+4Ih+2J8eqrXAmS5XGJmx978N\/H\/kVxfJsK\/\/vBkrtRRGDKoGe7px9coCtOl4p1QxdVTy8yoC0c3GKNS2JspmyPHwUKZ1I7pQinC6n29juse\/xPzaJzjyI4XIAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/naked-before-home_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221147.3333333333\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-before-map_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022911.20234604106\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAiCAYAAAA3WXuFAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAKPElEQVRYhcWYSYwk2VnHf++9eLFkZORamZWV1bX1NnTPdGMPHgwDshjbhznYt\/FyQliIAyfEhSPiAAIhS3O1sBC++MAiGYQBGazB7WHG46Vtpj0zraarl6qacm1dWVlZWZEZ6+OQldGT08NIRkh8Uii2F+998f\/+3\/\/7IgQv\/a0Bw5ULbZw8IUoyhBDkxrB9OGJ5rsR\/7ZzQbXiEUUZuDFpJjsOElVaJQZhwdJowijLAAIKJffDxfM1hoWZj0ojSuzv8QDV5rh3xw32HLAPxlX9dN\/x\/mTEgxOM9IIwxBmA4HOL7PkKID53jw+c3xfP\/22M5PXn55Ze5ceMGN2\/enFng5zn+vzCR57nJsow3dr5HmqcfOGipvEwq19jZvMfqyipHR0cIKdgTdc7pEVprtNaQDrl753t0a13ssuZOVGKQ12hmrzEOU3K3hZQ5ILFMD0FO2Qk4FyzRrrYJ3ABr+pZ\/9tYfE+cxLbdFmIZIIUnzlH58xJcu\/g7X5lYR1QV2x4JUV5BCMBjB3dRFjMBgUFlC4Odsm0OssQVpzJjn6ZnzGFfi8TNMHqGJSI0EkzKKQx4ND2hVW5OwGWNMkiREUfQ\/wygEr\/dcHg7PzpnkjStSmnKXvaxNho00EaV8i0w6+OYeg2yRYb7Mj974N168muDWNRN8IBMuIg8RgFKSFy59Gt\/2JxwC2NjYYGdn58Pji0Fg4GwfG4Gb3scyIWmSEaWKhz2Na0mS1JDKOSr2kJeeFWhlMCafzDE2OFGMpTSOtmm6ZdRZLskpKR3HodlsEkURxhiiKCJJEvI8Lxwy082AIiPr3+L12xbf+s4PUJZgNBpRcSTZ6SP+6K92cU2fitpD2eBVHFxbo5VElxWlqoWjBLYlEdLFmIlHBUL1ep3BYEC\/38cYQ7\/f5\/j4GCEESqlZjwAr6TOvdjl\/ZYWdg33+5l\/e4Ctf+2vc01scHW\/zhV82LIv7tPM9atUyyTgnH+W4UuM5GqUknmvhWhpfKaRglkPD4ZDxeIwQAtu2CcOQRqOB53lEUcSrB5qN4XvDN8nIYX+Tk\/4jRonHx1sP2AsNJ72IjzxVxVEujZrHOIkZpGMkEqkhyzKUkATao6JrBOmIoP0Mti5NsmxK3CzLsCyrEKs8z98nlO\/RHyao7R0LWp7kWvNndNo1alHMK4cZcZhya3\/A+UYPO9DM1SqkYUoaCeo1HyuXeMrBNxkCiRLvC1mWZURRhOM4jEYj6vU6juPMsto8ua0tLXN\/O6TmCsJwzHd\/sk8y2OOffnzI85crLDWaqFzQ2xkgKVOpdRmk58hEAIBWkhE1onyCjcjz3KRpysHBwaSo5jmWZeH7\/uPwTNP+ZFahk3iE45Qop\/d45Y23+eQVh+MQYuGydeRyuXnIvKeplgV1v8Sd7CqJsTAI6vltOu6IxaCN5V1EapuqDdY0JH\/62pjVquTWXoLnOmgrA2AhUPzer5YRWY6XDEhlidSyGQ5POd78Dl98tkGcG15PEgb+b2DVJX7cZ7l2yK74GO88\/D5X5zOSxGJUrmCiI6Tlssd1dt7+ZwbthGqrwkp3ESHkY1J\/8819qrZhP8yRUpLnBstSNMouH19yGKSKcRSTIzFCEA+PMeNjmvUySkl6eY3+yKBFSmoUmghLwv5RyHxNU3ZsBichUkqyPAch0MJgpCJNM66sdbEt9ZjUr26MWQoEt3Zjrnc0n7vqUCq52LYNwPHOQ3q9XhGuKbL9Xg\/Lsrh1HPHNH+9jhCDJEvLoBOHXEHnM+NEGX\/rMr\/GNnzzC0RIJ5MZQVQlbWxscPPhP\/u7Lv8\/KuQWsqTB+YtWlahu6FYuWL3EcZ1Iw38vps7F7e3vEcczi4iJSTvKi4oxYqR5ja9i9\/X0qRw\/o2x7x0R6+yUj6Fxndf4vTLEXkCV60xfqdVxkNDoiiiDz9XYwxjxG6cX\/EUkXw5m7CRxZsfrHrPYHG1Hq9HmmaMjc3h+dNxtXSIy6YbdoqYd0N+ewXPsMIg9EOqRG8ud3j4fpbeK6DFQ+oRBt0Sy5edZGNvR7irKMsSP0rKx7zZYv5akonUBhjJgI2VemzbAO4dOkSxhi01sU1bcaINKR\/Injwztts1EvsnPSwGw1c10boJbz0Xdr4LLUdnj73NCtzDq5tEeY5jWoZIcRjhH60GbJYEdw+SLk2b3OxrKjVaoUztVrtiRBOTUpJHJTQIkIITbVkUav5NJ0rZLYiSVMuttZwP\/8p5so27WpApewjBQyjhDDKEGoyd8Gh55Y8WmWL+WpOJ1B4nij4AVAulwvE4jim3W4XwmmMIQxDglqTLMu4ePU6aZrieR7NZrO43+0u4LouxhhardYMHaZFvEDoh++OWPAN7xxkXJvXXCjbBT9gouTTRdrt9hMo5XlOkiS4rkur1SpCPH1hYwxpmhLHMfPz80VZen87XHDo2aUyLV\/SmZN0A0WjYc8sqJTC8zy01gyHQ9I0LUJqjEEpheu6SCkZDodkWUYQBAXK0+cBTk9PybIM3\/exrAIThBCPhfEP\/\/EBnZLhkCqC4quEli\/5rY\/6hGHIaDT6QA4JIdhJA27tnGKEnEws5NkmQMDHqiHrm7sYk2NMjq01JU6YC1xsrVi99AyeV3rMoafP1egEiodHCVKIIraBPalvh4eHM8I4dWT69jfHHf7+p4dIZSGUQkoLpSyEmjg2ctb5+j+8QtOOef7pJa4v19CBz96jEcKSLK09Ncuh25sH9APJ+mGKpRRpmgAwH2heWJmfQeTu3btEUcTly5cLYqe9bSr5GE8KcuEglY2yNEIKtF3iUkPx4gU4322zutql5JfZf7BFLAzKUU9y6MryHJ3AwgsSrPdoT8URuK4745DWeiYDARrhOvNv36BWdjkYhJzoKn1jc5rZ7MceL33+Os\/9wjK+X0IoTZIktJfbJKfHnIwzzBnJC4TubPc5dFK2RzaVSsCFhsVnn5p1ZGpra2tPXOu2GlxcW8SSku6CwrY1CIlSkjg1CG3x0\/sndM9liHc3uXxhif7RAbpUI8oUytKzITu\/UKMbWLj9yU+Dsp6k8hSJTqdDo9EouFN8+kqJZVmMR8ucWz5PlmWUPBel7cknjpTkxuCVSgSrV0kqFc6Pe2RpzLKtSTKDcnzss9AXpL5mbREfxzyDodPpABCGPuVyGZg4NxgM8DyvaN7yPKdUKmHbNlJKBidDyn5AEARUq9UZBE9PT+noISoe4gX1gjP+mVRIqWY59Ac323x0weLfH8RIAc8v2fzJp2e7xiRJqNfrSClJkoRGo1F0mVk2+Y0z5Ve\/36dSqRS1cCqMWmuUmizu+35RjqZCWejQ5uYmxpiz5mzSxsZxjOu6NJvNGdV+v31QR\/DzjhFnUlOE7De\/ZfFLC5pv34+QwuLXl22+\/OJc8cBXv\/rnfPc\/buBosC2P2qVPcO76JxGlOr4n6ZRavHYvha0bqEqHNFjBCA+T5QgSfvuFEre3HvDtb3ydrfV7jEchUTjGKwckccTX\/uIvac81+W9xS9XYCGf+5QAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/naked-before-map_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022911.20234604106\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-before-place_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022892.66666666667\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAhCAYAAACxzQkrAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGuklEQVRYhcWXzW8kRxnGf1XVXf1p99je9Ud2vcN6DVlyixBhySESUoT4CBJCyoED\/wo3rvwDHEGIC0TLJUIILkEkaCOtILkgJ2SD7azxLuuZnfH09EdVcZiZ9jjucRaB4D1VV1XX+9TzPu\/7dovdH7zpaLEk1axEHtY5nHMUpaWsLUoJitISh4q8MCwnPr1BSVHZtmMmZ4WKG1d8Tg6fMNY+pdOMyla3iNqY9pX\/olljGY1GVFVJUTmi0CPLsta9npKydeHjBx+xt7dHkiQURYH2NcudDkrA8198AYQABwgQwNPBAFOXaM9DCEFtDNY6lJIIAcI5JJY08oiiiInf6QHQjL35h3nbe\/8+P\/7RDxkWOVIofOWRRjFOSEqh+e7r3+eVV19j47nnCLXkT+\/eZyVboixzYl\/ymzd+SlFbfKWQwmFqg\/A0X33lVbq7L7Bz6\/Of8jkZe87NInY+cuOiREu4spxhgaUwZDQuKKucyuT8+mc\/4fd3f8Gdr32br3\/rO\/z8l3f53R\/eJohDvvnSLrc3M\/LeECUdRWVJN9cYHPe5+8aveO17ATd3dttD1joLZEshuzvXkELhjGVYOE5sQGd1iTs765wOTxn0h\/z5j78lFAXWGKhrqrLi4aM+z69nDCufK8seSegQIsQGI059i7fQ6yWAkjihsDWJtJgqZyWKSdZ3SLRio6Ppax9fB4SRJE1KcGBqi6hqnvRH5EXJSf8xV9MrBErhjU8Zjka8\/JUX2dq6vhBQu6IBgcUXCs8T5E6TO82gd4xWlqN\/jjh8eMTYWPxklRfvfAPPd1hjMWXFRwdPeOeDQ97+8CF\/fzKgso7KwGhccv+vn1CP68UMCSFaF\/KixJiCcCnmS7du44TEBhm3dm\/R6XTwg4CydtTG4emYauxwtaVyDmMK3vnLAb7WlKWll9dspQFxGPDll15meXWFRX6Fc861ZdnB3nscfvAea+tbJNkatTFo7VNVNUJIrIOyqhkXJWGc8ta773P4yUNGozEIiZAChKDTieleXSZbSgBBECXs3PoC2zc+R5vfKaCL9vjxY5xzKKXwPA9rLVEUIaWc1Jm65ujoqJl3zhHHMWma4s2p9q2jN7EYpFFcL28DsLq6urgwnn88Q5ymKXU9ifXMqVKKoiio6xrf9wnDEKUUWmuqqsL3ffI8RwhBmqYAXI22AJBOkerJnNa6lR0AYa1tZchaS7\/fxxiDlJIkSZBS8qR4RGgm4ziOUUoBcHp6inMOL0gwduJOSXAOYt2ulzZbmGXNBimx1jIYDAAYuJNmrqoqZhE3xgAQ+oIkEKSBIPLFvwUGLskyACEEQgjkfL+bMu15Ht60bwkBWbY8WWjpT89ubnFhBHDOYa3FOYcQAmstsxajtcb3\/eagBw8+JooijDHEcUyn02nAWGu5d+9ec8lut8vGxkYbBZ+tIa01URQ1bB33\/kEgQqSUaK0JggCAp8cnJOMR1fpas9c516znp0OsF5MEsrlgm13KkBACYwz9fp8syxBCEKmYsiwJgoC6rhuHhYLBwQG1qxswzjnW1tammnOIasSwosnAVkAToLPYn1EHMB6PEULgeV5Tf4IgmKbtJGyzmwa+wux0UVN2tdasrKw0WSjEJONmYCfvXdSYdzZxkcIwDBtNjEYjlFKUZdmwNwMGE70ZYxqAVVVxfHzcaG0+RGmaTp8v+vQWFGqcc5RlSV3XaK3RWiOlbKryvE4ATkePuOoC5MZW876UsmGo1ztBxxmxlk0422yhhpxz5HlOp9PBGENRFE0Lmd8ThiG+7zP2LId7H0JVN2zMhJ+mKVoHmOKUSoRz2XnRLs2yXq83Qe15TV+DibaiKCJJkmZ\/nufU9RmYWUJIKRs2hBBNC1pkCxmaAVJKUdc1Ukq63S482Ce8ce1cA53tn\/W+5rZTULPQzreahYAW1QMpJWtra01hXF1dRQjB39bHXG+pI0EQNM7m68xsPM\/wDOyCLLucoZWVFZxz9Ho94jimexxib1w8bH9\/nziOEUKQZRlhGM6d5tjfP+Dw8BDnHDdv3mRzc5O2FjP3G8Q5B1JKOp1Ow1CWZSilGoY+fbNy9JT0yg1qCxWS8NyqYHt7m+3tRd\/Sc37PJi6Gbpa61lqGwyEA3Yd6ju4zu7bd5eqSYnNZkQaLGmq7nzmPi+vQTAOzNJ\/VH5ScguUcqHS5M33v7DKXW\/v6Z34PwSR8RVE8y9b\/2BbWof+XPRND\/0u79PMjryY\/eIEnOC0tnhRIAZEvGBQWKQShLyhrh3WT+XHl0B4UNWgPajNRS+gJhoUliyTyEl3\/C8C8KrFX1sBMAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/naked-before-place_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022892.66666666667\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-before-submit_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022811.96261682243\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAeCAYAAABE4bxTAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEl0lEQVRYhcWX328bRRDHP7M\/7nx3dpxcQvqLEl6QSiMEVXkAiWfUf4A\/EvVv4AkhJFSJhyIkhITatClJXSexfbbPd7e3PASntnFcpyrqV1p5bzw7Ozvfnbk54buH3lrFnY9SfFFQOo8SOO7l7LRCXg0KtAKjFN2s4MZmg9NhwXYroKhqTrOSUeGYhwdk5hcaVmG14sF+ix9+7bDtctgwdKqYs3F9sVIe\/nzgeR+Y7irzYqnr2jvnOD4+Znd3FxFBRFBKISKUZYkxBhHB+3Mrq+YA3vsL+axsHR3x3vt+v8\/jx48JggCtNVEUMR6PMcaQZRmtVov9\/f3\/JVDTAMxFyHvP4eEhVVURRRFlWRLHMcPhkCRJGI1GaK1pt9vv3CFrLdbaeYdmw77ovfeePM8ZDAZ47\/HeX1A7qzOdwzug7E2ncG4xi9aH9x5jzFL5okMAZg1\/KMuSsixJkuTKDi1Gfxkbs8\/mMqVZ+WKWXQXT9aucmqXMzN6Fy05YFAX9fp80TZeGfxXeZH9RV+q6XusOVVV1EamrQil1qQOLUb+41KsoexuqpvDeo7VeO8su4r+KslfZhIPjE7bSlDAIAMjzHmQnNBoBYRIwqps4L4S+R1kUTJQiDmJiq0njzbUpWyvLJhLQsjW2HOKKjMlkQl8cTZkwqmvq0iOq5slZQlIXDL3leNzl\/o7DO8tWtLqgzmXZYuFa9Nh7T+WFH0fXaeZjsjrEo9B1Rlr+yUhtEelD+u4GIzZo5keEdGhEjt9f1uylH3M7vbWUstl9pjI1K1wcs8oAafUHsXRxVU3uIvrRfVS4g\/I9arPNhj0hsROsTNDiESVQzNtfBRFBTS\/tqiFAgy5no4ry4De0UVirUcUAycf0zTcYFdCoTkhcDxtqtAhaBDHLbS5SNh1qMQqLHgP4umJ7\/Igiuc3eJ5pE9zDDF7R5zlb0lNNnv\/Dh5CeuhR3Cdkg5dIRiCbShEdn5t\/mSSM3K1iqMohSv4q8wUjKaJARVlw15QkhB3in47FZCGiXYQJMVOVUaE2jDtjY0g9ZK+4t7rZVlHsXYt7FMCM0uH8gzbKwpS0vrZszZUUZnXFBUjrAdsBlH9E9yTDMkEPPGOnbld9kUzgc0VI4ucora8fywwzAbEkURn+7toYAXgxMaI02zfQMTJTiSS1uU2X2mMjVL2aosU97hvSerUhqJxaCJWze5e\/ceJv2S7qjPcDwhDZsk7TaPizsQ3qSWZM7+KqxNGa7i1vgR14Ix1gYcv3Q8j77GJY7h4JQNNaBnvsBMfmd8NuKk3MaGBd2zLhvt6\/jm+pSt1TFmwyFHR0e0Wglawbi2OAxWHKVXqDpnp91+\/eEjCiXn9pTWBDZ4tx3j4mlEhIPsKQ\/\/+h7va2rvEYHP03t8e\/vBpd3gMjtv1TEug1WWzWAT4fVda9rmym5w1SGnWIuyq8ynG7xtk79WYVzm4Ox\/6xa9dXTEOfd+PqUvgZnWB+89z3oVkRE2I30x1+o8cwItJFbRGTqUAi2wHWs6Q4f3oBXsJJq\/B46df+WRFWIrnI5rNhvna3cSTTap0UrYSfR\/KPsHj\/b+fF+Z7QQAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/naked-before-submit_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022811.96261682243\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EAfter:\u003C\/h3\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-after-home_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022784.8\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAdCAYAAADCdc79AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAJQElEQVRYha2Wy49l11XGf2vvfc499123ul7u6lbb3XI3dkIejgMTgnhaiaIQQbCiCGWUDBghZkiREEiI\/4ARAgYMQEIMkFAiGGBkWRkgO2AIsR0nbne7u+3uqlv3UfdxHvuxGNzqcrdRhBSxdAZ7n3O0z3e+9a1vLWn\/9t8pqoCCAiRQBY2QEmhk397iqa332GtX\/MedNtF7fufzn+Erv\/prfPNP\/ozxdI51GVtdYdBpc++kJgSPiFAUlk\/uTMAI9yvDblHhWi0yo6AJ5xzedti9eIX56QQnKAg8eTiiTaRuAs4K3nsW65rj2YphZ8214YJX7wzRGIi+4R9ffp2qVsbT+eYHUmIyT0xOPc7luFYLEbg8LBHTcNy0SepY+xyThH4WSOJZRk8mJfdujRERbPbMi3887GREH1hVntpHah+pmoBBiTGS6Zhr28cUboHQZr6KrMuGH9y8i6pirCVpAiDLC1JKXBx6yuhwLiOII0bhuU\/8Am3\/HmIrcmtQEYwRYowYqxiTcKDYas1xNDgDAvgQ+NSe560TR+MjzghlA9084\/KoZrLOWSwqNCWMsagqKUbEGGLwtAvDi1\/6MkV7lw\/GE0adivsnU+7813eASNFzGHUk8WTiiE5pq9JIwqDKSbQAhKj4mADh9QeWyicSgjEBZx0xKiGW9Npxw0RMRO8J3qO6Wfu6whjDm7fucbi\/x9XhKVcPD2lOvk+rSNhcyFWx0lAYQ4dEF8GqYhCMAnlmORh16HdaIBbrHPvbA3ZGfbAtILGqT5nVgbcmu7QLg8tzsrxFigmNCRFBUyKGwHy24u77U6bjN\/n+f79EUWxxYWtISpFQJaZVi7XmOIRZpRhVMpORNw7Xy5VRzxBCQ9cp\/YEwXVQ8ODo9q7RIliuFgdurAbGpuDWJ2Ayacg0iiDUgBjEGDYHnnn0G\/APqxlCap3n5tVcY9D\/G1tZ9fnRvyY+P2uz2a65fqLi72Od6f0lAqE2Ja2fCfFlR1QE9E\/HhdhvtGtDIeLpENXL7aIej44ayqkAVMQZUADDGYI0hpoSqsjUc8OvP\/wyv3Zzw7e++SbsNl\/ZGtLOczMFn9sfU6shKpVqvGc8ajE2oBmTrt\/5KU1IEQBOQGLQd3geMJDQE+rzLevwOMQRENlUuAiIGm2eIMaQQid5jncMYw8\/d6LFjS3ot5T\/vW945AWMEa2C3Ay9cKqmSUpJRWEg+sPaKG3Uc2\/0Ws2VFWXvWVaST57giI4XA8XTNaRUxMYAoqgZQVIWiPwBjaVYLNEUg8Zuff4HV9DaHzdvknRaaAi88mbh5wTGyJe+vLJmxWISOE07WijhlZ9CniAZXVRUzDRS5RSMEo7Ss4owiRsiMnmlEIJ05OputXy8JIbKJhDGGV777Er\/xNAwKyyoGrAjWWA6yipZEyBsehC4zU+DXS5rQ5v2Z5yi0ODwY4aJvsIXQySy+DmhoGE88aCSEQIqeJ7fbPPvsx\/ngeEIV5FxDm1SFDR4BYy0fP2zT7dVkuWXfghHwCYq+YjUwSMpll\/PGvMUzFxtIysky8tZyxFHdwrUzxWggeDBEMpPo5BYUFo2H5Pnln3+eb33jC3w0jBE6rY0x\/n+EiOCqssRqxla7w8lqjW8aeoMegkGiYblKzBYVv\/cXrwMw7OaEmFhVgSt7Xf7wxRs03m8oQum02z81IAWck0AKidUKRD1WA6enC1KKrNcVKQaGHcOf\/u6nN9\/8SMyTgnXn+7LxPzWgljG40FR4VUZdy3KxxIhSdLtoAlMYUjCoJm5O5\/gQEBFiilhrP5xYHkmZiJyn8OHaGIOqoijDbvcnAtrKM1xhFWcNViP9QmiaAKnBCczXK5qmQVLgswc7\/+cfNj79xGdiBGsEHxJyxvSj0hMBZwTXVGskd5RlwtclwQeMbowxxRojkRga5qenlOs11lqquuZgf588z89ZePXNI\/7gz39AAhQlycbIRQQRuHGpxwvP7\/E3r9yhyCwPlhFBsShOI5My8MVP7eJSqOh0e3RzocmFWVVzukikFCkywfuEFaVotdCUQITMGVLaNNSHkbUMB9d6iLEElPjev5MOblCvZizff4vyXqDzua8zGGbkzjEYJIyALj7gzg9fg7tvs86exNUR7i88ad6AKskHdgYtVMGIoi4jes\/p6QIfPP1+H+My2h+ppkxLLsXb7AwLbCz58d2XeKJ4hxAhf6LF\/sETnNy5yxsv\/yuSArEp2Qs3WYzfpmxKyqpmdW0H52mxNdglRsUYmN5fIxrQGDg6mZFSBI0Mh4PHAFRV9dg+J7LLKd35McuTu1w\/PODLX\/gVfnjrFq7doTPY5o0HM6bjm\/SKHCPKMsBTl6+y2\/ZUIfHU4QFOZ+8ynb3Lw0HfoJTFkBQjvbYjJcFZOROhfqjARyrJOYclUKQJmC7Tkzk6G\/PqP\/0z826HLM\/Z3a\/IucCuO+Fip8fVnYIbh1c4GOVYa2mScnD9WZzE5qw76dmltJyQdwqOxxPquiF4z3K1YjabgYLERDRQtApGoy1arRaaPC5NyFNFO4s8qNa4VkZLoaxr5qcz9i4dcGV\/RWFKyLfYGh7QarfxCW7fm3CruoXT9NDIzk0FTYGm8gy6LY7WS1IKeO9RVfb39lCEQb\/3WMouX7nGV77++8SUzntdjJFBv0+\/3yfGiKrys5\/4NHmWoygXtrdx7kNTjTHiSP6MfT0Htjidb9JnhCJ3ZNawv7fH3u7ueZk\/2r8erjudDnVdk7kMKWvsVp9Op\/NYNfZ7PVJSkhqq2Sn5oLdh+OwMRwrnQOQsZVv9NqqK957JckntA3\/9L+88xog+BKJgRfjaL11hOp1RliU7uzt0RwOKouCjMR6foKrs7Fygs7W1cfxH4hFAGzCbLyVC2Ogmc4Z11fD33ztCkE0\/eyhq3dBsUb76i5fZ29t97PBHK\/FhCzk8vHh+r2max94XEZxqfNzDgePxCTFFjAgxJpwVruzmHAwsV0cZP5p42haGLYOTRGGFO9OGv\/y3B9TKZuA\/G\/pFDCLCpYHjs9vCd177gLqJlHWkqRp81RB8QEPgc588wKH\/u\/9cGA0Q4PhkCii5hS9ezzBmM2IcHDoysxm8Fqs13\/6Hv+X603\/E9+4uMMYg1iHGYq3FiEWsIybhuUHEhzV1UlYxsPaesvb4OpBqz3xd8z8wvSjf7jlH7gAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/naked-after-home_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022784.8\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-after-place_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022647.34864300626\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHIklEQVRIibWVS6slVxXHf\/tRj3Oq6jzu+9Hv0OkkEgQHcSLJwDgWjAMRR4ofQZwKfgU\/giMdiBMRHCQoSETQxkQx706nO7dvbvc9fZ51qmrvvRzUubfP7VbBgYsqqgr247f\/\/7VWqeyNX4jWgUhrRAIKIXiPdw3BN1w6\/iXF9APyvIcKnk5\/k29994fcvPUCj47usnf5CtdvvkCUpGiliCMwRvGDH\/2YD+58xMsDTe0atjeG5HmXuiyJjebeaMpB0cFYzZ2jE3pbhxSRwoLQTVN2+gkqOIwWvPPMyiUnpw2DtEOfnNFsjNLQPGr4+c9+ShwnmChiXjvy3oDvfO\/7vPLq62zv7GANhCBEcYpkXTpNydbGJgbPZDRC5z2aZck0tgzijMP9fe4fHzM82MHEL377J10aRouayaLi8bSirhuWVUPjHN3xOwz8iGEvx3lF0Y3Z7PUIwVPXFbVrCN7x\/u0\/8dZvfsXDk4fsHVzhzbffZr6sGFVQGcP9k4ccFinLquKL0YSmqrlxuEPlBI8i0bCzv4uFwKQRggRY3U0dkOAgeHaGBVt6A\/GO\/d0dHo0mNKLwcUYUZzy\/NWD8eISRVpU\/v\/lbbv\/+dzyI+tTGkhYFC2cIIaKfdZnMpmgFl3c36eYF09MxD05G9LsWaRqsUcKXrgyoGk9sQSOUVYN3DZPpnH6Vcn2wQXCB4Dwqs3QGO3wyaVDAlY0u2y89x7JqmC8qptMpWRy4e69CaUM5m5FkGcZGPJ4tyPOctL9DXE84GU+ZLxY8OD6md+0AgmC997zz8UMEIbEKhVBXNcE3qODwiecvH91lK0vxixIksLu9xV6\/y8H2JptJjdLCu+9\/TF3XPHz4iBuXcrzvUTmwkcXNF+giZyGaUVnz4ecf8fXnD8iTgn98eJe8mxAnKSeLJZbg6FNS2i4EjyJgcMRWqCpHbBX7O5t0Y808SWmIuD+aU+mKqkj5+4Mx20WCtYqr125yeOkSr772Gp\/9+i2q08cgEIJHe89fT2rGszmxaGzc4XQ6pmlqOpHm+q1bzMZzbJEotM25HC35dCTUroEQcOJQwXE6mdJP5yTGcuv5F6nKOdN5DdmAW7dusre7Q5bnRFFK5QM+CD6Adw0iggJiG1EvK1xTowR0mrKsK7I0YjDo0ywXOOdxErBagbWG+zNLExwoizIBjSZ4jenso7eucu16H5sUPHewh0I4On3MYH+fxkZ8djxiUh6RCgwPrvDJxx\/gfEBCwDtHU5XYJEUrCwowKbenUDdLbuzt4RdT3GxKPryMHdeGIskYbPWRWcOy9mSpZauXcOd4xvZVw+begEfjd9lMFfc+f4B3jjyJee+9f\/LJ3SNevrHL7e41Xpp\/xod\/vEOnN+Tq4QFJZ9xWrxJAE6cJadYl6XSpmoqujTjVMZv729xvBLvwWHzDYlFisXQ0JIlgVMODhyU4xzdf\/ypvfOMrANR1TRRFKKX4f4VFPHGkUUoxmteICIMsIo00ywqUAmMMSik+PzqiLEu00gw3hmxubNA4x3QyJU0TtNakaYpIO+9\/CaUUIoJVk09ZTmApAhJQEhiLbysuOJCb55OybpfIRtjIopUG4HE1YTQfsRH65HkOgABNveR4dMLOxiFpbBCRCxsDlGWJ9\/58XquQW6KgHbQCkhUQ4truvQpjLGnagnS73XYBaymKgsSm1HWrcJp2cMryt7Hjy+4IozUiIAi9ogAUgqCVxlr7lGVu2b6JAE9+H4iH4NrnU9IqpZjPF8RxTBBBRNBKkff7iAgikBrN1\/Y2UbTeaa0IIawUFLqdzjMwLZBfImtAsgKS4FHiLyg0mU6IrCXtdIiidrGmrjk+\/gIzVIQgFEXeQobA6ekpaZIQgqB0iya0lT+ZTDBas729fQHMiqtWAgqIrCwLLUwIF4BaudtoGkdVVfRsxtR0sJEFBO89WhtEa\/q9Pskq2VnlzdnZtW5z6emKtfglSOtqa1ULxfq9iulsRpZlbAyH54m5XC7Z399HJGCMwRizqjJFr1esQTy7+VkKXABSrnqCfQaFrFQKK5HbKIoC1zSMRiOyLCOKIhJV4l1JMAXeX8w37wNRHKH\/Qw9wzq0U1WuW+ercW0RQhPOKewLYxmQywXtPr+ixWJTAgiTpUAlEa2OKokfpHH+4c49Xdjex1qDgPMfOVBGR80Rfs6xe+5Q1pQQhXPBeKYVC4b3DmLZk47IC50mHw\/MeIwKxUjyXWhbz+QWA2XxGka+glCLPsqeAgluzRVb7rynEkxNkWYZ3Dq01\/X4fgJGd0NSK9Ck7lFKktu3wZz1HRCjynM6q5Neb5BpQs5YlsrpWXZWLg402YCFaK1OR8MyiZ3EGISKIDmitmc8XTKdTjLVk3S7GGDqdzhrQqvGdLalk\/UsuWDadTgEhiFAul3TSlN54yXxZQm\/rfFwQwRjDwcH+vwX9b\/EvDlDrxomykUsAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/naked-after-place_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022647.34864300626\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-after-submit_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221381.6666666667\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAkCAYAAAB8DZEQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGMklEQVRIiZWXu49cSRXGf6eq7qMf0z0z3Z6xkb32yAgk2AC0EhEkCBGw\/wABCcEGkBOQEbMBfwQiQUggLQsRiIAACRAIFrRazzK2sfFjPJ5H337ce6vqENx+zcyOMSepUt17zrnnq\/N9p1s+861f6UYnIbNKCIHJZMbebsIvfvgNyqqiKAo0KoPBNiKCiKCqrNviTEQA5ntQBRFwViB6z6RWhIAzisYIgDGGfq+PtWbpfDHB4vz4+ARjhH6\/T1EUdLvdeXJwiXjKWhAUiTVWK4QmqAAxRpyzlwJfMgHvAzFGQojLqgCcSywmRkBRIHoQVpWohv+dAGi3WlhrMcaQt\/LzSYpJTTt3TGYRK2DFEeeVTEPk4en4nMNFmID5c8UYQ+qS5mE14Va3hRVwvhxzVipooI4BjTVxuwvAg8dnvPf7fW7fuMbL0wlv3k7YaJv5ZTpSB6mrELHMakdiA8YqQYXEWujcRIzDqZ80X6QBjR6NFbFu7uD54WMOPvo1b7\/1TX7w3s\/46ckRuVMePpuSZhlfuDlCsjHEFCFhO59QmJq2zem2+nzvO+\/S29jExfUkwaOhIvp8Dkfkb\/uH\/OT93\/DhwSOsdRgR8laLYbfCaMHpKGW7HXH2jDOvRKNM4xSrngZlxYRqTKzGhHJMqMaEaoL6GQCJE06KKT\/\/3R8B8L4mKux0J8xCyle\/9m3yGGhnNc4anDGk4omxZBqUoAoILpbFGlyBGGuC7wCQOc9g0\/H8cEYdakARhCSDT7ee848\/\/5hrmzNMsKSpgEYSSRipYEOFzCnlfFUAETSiMaChRn0PgHFpGY0FjQ2DEWE2meBnQm09D54KW1nk3umQuzsFRje4lo\/p+AoFrGmUwMVqBKqoxlU1dQNXXdWcHR8jxpHmGaH2ILDbU6azHg9OHZndYG9zwo4oxz4gXogTyxtv3GLR+C5W43m\/xyZRDGgoAdgdbvH1L38JbIr3FaGu6bQzvnKnJksto1IoS0+Ihp1O4OUMNnLD2Fe0sj7GOkQEF+tJw3XVBjINaKgA+Nzd2\/zo+9+l1WqtCBgj\/zq4T97KGQ4GZFkGwLNnzwDo9Xrn31fFRT9dsVcjqBKjBxpZsdadE8Woig8eYwxFMSbPm3ZvVsE5d0kh3Bc\/v9dUwUK94LN3by2TpKk5J+HGGIaDIS5xpGm6lPiiGtHL+1R1TVVVdDqdpeRIjPGydl+wJocspf7Rw306GwNarRZJkpIkjuLFEbbTJkkSRARr7fID3PrAWQ0e5fzYaM4W1tvcxVpDlmUY04jpSTmD2QxjDVma0ev1liNCVNcrOY\/lvZP7\/PLBbxvoxBA18tbwTW5OuvS2dhAxdLod8ixlNGrUOkkT0iRZQgWs4HrVWL1oDw4f0U+65K0WeZYhIhzs\/5PBzs0lTKrQ7Tb34haOV43VT7Jtn2C72bJuVWWwewuNSpZlWHt+krpVuy0CfvKAWliMkSfFIV0NdLvN3MnznNOjJ+zcuINz7pLPa3XXRTs5ekl\/e+scH46LUxIsnU7nMk8W7fl61mD9+OlTRtMJ\/X6fVp6TpgnxbER27fqy2xpkmrgGVtg36\/r+\/L0stu12m1ae4+Y\/HECYpUJZlRRFQVVVLHgF4BaOq6C8MhHAcDhARBqJ8R5rLZvkuKRp3\/WuVFXMspeX6\/p+ta7jfG\/\/Yw5fvMCYhpAiwlFxRF3VhBAu+ZqLBwt2rydd2OLs+u4u21tbhBCo6xqArcGnCDFgjLn8kf8vGa86+\/f9j9i5cYc0TS69t2iF1ybjVWfZ1jZlWVLX\/tJ7ay28arl159dlkStK0mEf69zSx8j8jl9Fxo\/\/M+b9Pzy5MnDqDJWPVz5\/5+09WplFdFnXqpIPDk55590\/kTqhkxtCCIzGJVYCiXhORwXqZyTGkxnPyckxdVnQyZTMRE5OXjKbFkRfoRobgVz9aWm6ygfl5agidXA2aeZ6DJ6qLHHimU1n1PUUG0sIU6bFGcGPub43pN+xOKn56+PHRF+CRtx5Eq6xXiOqQuoMMQhRBPWQpRYnjnJmKacRa+b3qYqzhjRx\/P3Dg1VA9KrJCGgkeBhPAmigqio0VFRljdGKuq6pqppYT5tfOBr4ywf7RD8jxsD6JP0v8DmijnnKJUoAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/naked-after-submit_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221381.6666666667\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["bootstrap","colour","design","redesign","refactoring","naked","naked adventure","naturism","webdevelopment","website","font","symfony","javascript","booster"],"hasMore":true,"image":"https:\/\/avris.it\/image\/naked-revamp_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/naked-revamp_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-revamp_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022161.70744403956\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYet another one of my projects, \u003Ca href=\u0022\/projects\/naked-adventure-de.lite\u0022\u003E Naked Adventure\u003C\/a\u003E,\ngrew too outdated to support it. I had to rewrite it from scratch.\u003C\/p\u003E\n\u003Cp\u003EI took the opportunity to redesign it as well. (screenshots before \u0026amp; after at the bottom)\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/naked-revamp_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-revamp_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022161.70744403956\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYet another one of my projects, \u003Ca href=\u0022\/projects\/naked-adventure-de.lite\u0022\u003E Naked Adventure\u003C\/a\u003E,\ngrew too outdated to support it. I had to rewrite it from scratch.\u003C\/p\u003E\n\u003Cp\u003EI took the opportunity to redesign it as well. (screenshots before \u0026amp; after at the bottom)\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s an overview of what I did:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ereplaced my abandoned framework \u003Ca href=\u0022\/projects\/micrus-v4.lite\u0022\u003E Micrus v4 \u2022 Beauty of simplicity\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony 5\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Ebased the project on \u003Ca href=\u0022\/projects\/avris-booster-quick-start-of-new-projects.lite\u0022\u003E Avris Booster: Quick start of new projects\u003C\/a\u003E, to take advantage of built-in features:\nuser management (including a passwordless approach to authentication \u2013 \u003Ca href=\u0022\/blog\/passwords-are-pass%C3%A9.lite\u0022\u003E Passwords are pass\u00e9\u003C\/a\u003E), push notifications, etc.\u003C\/li\u003E\n\u003Cli\u003Ereplaced \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Micrus-Assetic\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E custom Assetic setup\u003C\/a\u003E\nwith \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/frontend\/encore\/installation.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Webpack Encore\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Eupdated \u003Ca href=\u0022https:\/\/getbootstrap.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Bootstrap\u003C\/a\u003E from 3.0 to 4.4,\u003C\/li\u003E\n\u003Cli\u003Eadded more contrast to the design, filled the excess of white spaces with content, making filters and maps more prominent,\u003C\/li\u003E\n\u003Cli\u003Ereplaced Google Maps with Apple Maps, because of privacy concerns (see: \u003Ca href=\u0022\/blog\/ungoogling.lite\u0022\u003E Ungoogling\u003C\/a\u003E, \u003Ca href=\u0022\/blog\/log-out-for-privacy.lite\u0022\u003E Log out for privacy\u003C\/a\u003E) \u2013 the website is now officially Google-free,\u003C\/li\u003E\n\u003Cli\u003Eremoved a couple of unnecessary and unused features:\n\u003Cul\u003E\n\u003Cli\u003Ethe homepage (now the user is shown the map right away \u2013 after all, the map is the whole point of the project),\u003C\/li\u003E\n\u003Cli\u003Ethe \u201dgeographic\u201d links (there\u0027s no separate map of e.g. German nude beaches anymore, it got integrated into the main map),\u003C\/li\u003E\n\u003Cli\u003Eseparate events section (now they show up together with places on the same map),\u003C\/li\u003E\n\u003Cli\u003Eforum (it wasn\u0027t used at all),\u003C\/li\u003E\n\u003Cli\u003Eadmin panel (now the buttons for admins are just integrated across the website),\u003C\/li\u003E\n\u003C\/ul\u003E\u003C\/li\u003E\n\u003Cli\u003Eimproved filters (for instance added filtering by name and location),\u003C\/li\u003E\n\u003Cli\u003Ethe process of submission of new steps isn\u0027t split into steps anymore: place info, review and description are finally just one single form,\u003C\/li\u003E\n\u003Cli\u003Eincluded some more \u003Ca href=\u0022\/blog\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome.lite\u0022\u003E optimisations\u003C\/a\u003E.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EBefore:\u003C\/h3\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/naked-before-home_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-before-home_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022286.83333333333\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/naked-before-map_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-before-map_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022227.80058651026\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/naked-before-place_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-before-place_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022223.16666666667\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/naked-before-submit_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-before-submit_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022202.99065420561\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EAfter:\u003C\/h3\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/naked-after-home_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-after-home_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022196.2\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/naked-after-place_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-after-place_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022161.83716075157\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/naked-after-submit_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/naked-after-submit_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022345.41666666667\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E","words":262,"readTime":2,"lang":"en"}}},"blog\/technology\/mysn-de-schenker-there-s-a-part-three-after-all":{"key":"blog\/technology\/mysn-de-schenker-there-s-a-part-three-after-all","type":"article","published":true,"meta":{"createdAt":"2020-05-03T12:32:08+02:00","publishedAt":"2020-05-03T12:32:08+02:00","group":"customer-rants","category":"blog","subcategory":"technology","slug":"mysn-de-schenker-there-s-a-part-three-after-all"},"content":{"en":{"slug":"mysn-de-schenker-there-s-a-part-three-after-all","title":"mySN.de \/ Schenker \u2013 there\u0027s a part three after all \ud83d\ude44","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGVUlEQVRIiXWWzW4cxxWFv1tV3TM9v\/zRiMMhKUqWJUWwjQBO7G1WQZBXMPJOAbLIQxjIM9hGNpEDW14IdgxDsiOJpCSKIjn\/0911bxbdpKggKaDRjUZX1ek6955zZDhYs7wsmc2WFDHiEBADBFUwM5xzOOcQES6GiIAAIgj1vb6gmocJIIgzRARTAzMQCImjkSY0mw1azYxOu02SOMJ8uWI2X6FaTVIMUwC73NzMLjeKqjhxGIb3vgbhcCKIc2DVTBHBe0+\/3+fa5jXW19dYW1uj1WrR7\/bodlpkzZTx+JzpfMZ8PmM8HiNOxC4WqPY0VHlnhBBQ1eqvEZwPmBlZltHv9xlcGzAajRgOtxluDxltj9jZGTEYXCPPc+bzBYdHRxy\/PubVq2OOXrzg8OiI1yevmc\/nlEXJqliiURERsUsKMJwTwF3SkiQpvV6fzc1Nrl\/fYnd3j\/39G9x+7zY3b92k027TamWUsWQ8nvD65ISDwxc8ffaMg4NDjo9fc\/LmDdPZDDNlsViwWq4oY47GSFkWODGcOLwDcc4ZQLvdotvtsrmxwWBzwHA4Yms4Yn1jHec9UY2yLCljpIyR8\/Mx4\/GEPM85PTtnNpuhaqgpZVmQr5bEGAnB452QhEC322F9rU+\/36PbbpEkAbPIdDJmNp9TrFYVoMFgg1\/dvYdLGkQ1ohrT6Zw3Z+fkeYGZXRZ38AERRwierNmk02nRabfYHm6xd2OPne1ttra26PW6qCrT6YTJZEqel4wnY05P33B6dsp0cs5kMub4+ARDEYGiqAGJ87iQ4rxHpKLLiSNJAmmSkDWbXL9+nRt7N3j\/9m1u3drn2uYmahFVI01TDDg\/O+Pw4DnLxZytrQGmJY9\/ecrZ+TnD7R2SRsZiuSQNwmKxZDw+49tvvyFrpCxqGsU5Z1mrRRkjgrB\/Y4+7799lNBqxtTVkNNplZ3eXjY0NHj95zMOHDzFTyrJkd3eXm\/t7rK+tAfDgwT8YDK5x\/\/49xuMJq6IEcWTtFj\/+8D0vXr1hMV8wm004Oz3h+PUJz589Iy9yiiJntcoJAPlqRdbKuH\/3Dp9+8inD7R1++PFffP3Pr2l3vuezz\/7Ew+++4eHD79jZ3WEynXH+5pijBz+TJr\/DVAne0+l22Lt5i3Z3jSgBt5iTBMfPTx7z+ed\/4+nzI\/LlAtVIjBEzRa2iS8xQjFB1kue9vR3u3b2LCSSNFLOCaCVHRwd88eUXPHr0iG63w6vjY\/prfX79wR0+\/OA+Pz35N3\/+y195dnBIcJ7R9oCPPrzPy5cvOT0bc3p2xmQyYTqdIWK1pinOWdXmKBrryxTx3puI0Ov3yLIWWdZCVVmt8loUoSwjZVlWOiTw209+wx\/\/8HtmkzE\/Pf6FVrvNV1\/9nYPDQ5wITgQzJWqJqaKqqEY0VicTo14R3ivKXkmNmPeekAQajWal7OIuO+viY9W3z0masLe3R75cMZ1OSRsphwcHNQ1vFR7RSrWvvAIQJ4QQaDRSWlmTdjtjfa1Lt9O6AFQBCGmK9x7TypNifMv1W4C1H1VGxv8bzjuazbTSt06H9fU+\/X6fXq9Dp5WRZU2Cd6hFRAzvBNUS8d6ZiNTWAM45zMDqja\/62NXn\/w3IaGYZH3\/8EaPRkH6vV\/kbELyj0WiQpgGzqnaS4NEYq72JlEVOuGLgmBkxxndc\/SoQEbnC9X9hESHLmuzv73Dnzm289zQaTdJGQvCeJDgQKMuS4F1lFd5RFgXOC8tlgXdStb2I4J0DFFV7pw6ugoDKaEPwhHAhoobUiydpYK3fw4nQSFIajYSLLk4SR1mUZM0GGiMhOJyDJGmhGvHOUI2Ei7pwUh1rFL10e1cXn\/dyqeDe+0ugaRowrWKP91XeSRspIQScBxEjSQKNRsA7R\/CeNE0wVWIsq84zxQmoRqbT6cUJcRm0vPckQXA1CBGH84JGw3t3WTcXgStJAtGq1hYR0iQlCZ40TXGuOsGLhvBOKIvKG4uiQJwRiwKzWJuzVsJY1QggDlTBOcRV+cjM0FgVu6rW6VEwoKw7MEkS1CBGxVQRR0VH8LX7l6gIyxirIFevW+YFsSyIsaAsSoqyqCi7yEJmVndFHT\/rwIYYevFdnV2iKVABU1WCdxREFssFsSwxS+ucI6CKVSgwrJaUoqasoirPc1SV\/wDhNHm2gKzJHQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-0_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u0027ve already complained about my mySN laptop\n\u003Ca href=\u0022\/blog\/mysn-schenker-kurwa-ma%C4%87-de\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E here\u003C\/a\u003E and\n\u003Ca href=\u0022\/blog\/mysn-de-schenker-a-bittersweet-ending-of-a-horrible-customer-service\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E here\u003C\/a\u003E,\nbut now it turns out, there\u0027s a part three to be written...\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGVUlEQVRIiXWWzW4cxxWFv1tV3TM9v\/zRiMMhKUqWJUWwjQBO7G1WQZBXMPJOAbLIQxjIM9hGNpEDW14IdgxDsiOJpCSKIjn\/0911bxbdpKggKaDRjUZX1ek6955zZDhYs7wsmc2WFDHiEBADBFUwM5xzOOcQES6GiIAAIgj1vb6gmocJIIgzRARTAzMQCImjkSY0mw1azYxOu02SOMJ8uWI2X6FaTVIMUwC73NzMLjeKqjhxGIb3vgbhcCKIc2DVTBHBe0+\/3+fa5jXW19dYW1uj1WrR7\/bodlpkzZTx+JzpfMZ8PmM8HiNOxC4WqPY0VHlnhBBQ1eqvEZwPmBlZltHv9xlcGzAajRgOtxluDxltj9jZGTEYXCPPc+bzBYdHRxy\/PubVq2OOXrzg8OiI1yevmc\/nlEXJqliiURERsUsKMJwTwF3SkiQpvV6fzc1Nrl\/fYnd3j\/39G9x+7zY3b92k027TamWUsWQ8nvD65ISDwxc8ffaMg4NDjo9fc\/LmDdPZDDNlsViwWq4oY47GSFkWODGcOLwDcc4ZQLvdotvtsrmxwWBzwHA4Yms4Yn1jHec9UY2yLCljpIyR8\/Mx4\/GEPM85PTtnNpuhaqgpZVmQr5bEGAnB452QhEC322F9rU+\/36PbbpEkAbPIdDJmNp9TrFYVoMFgg1\/dvYdLGkQ1ohrT6Zw3Z+fkeYGZXRZ38AERRwierNmk02nRabfYHm6xd2OPne1ttra26PW6qCrT6YTJZEqel4wnY05P33B6dsp0cs5kMub4+ARDEYGiqAGJ87iQ4rxHpKLLiSNJAmmSkDWbXL9+nRt7N3j\/9m1u3drn2uYmahFVI01TDDg\/O+Pw4DnLxZytrQGmJY9\/ecrZ+TnD7R2SRsZiuSQNwmKxZDw+49tvvyFrpCxqGsU5Z1mrRRkjgrB\/Y4+7799lNBqxtTVkNNplZ3eXjY0NHj95zMOHDzFTyrJkd3eXm\/t7rK+tAfDgwT8YDK5x\/\/49xuMJq6IEcWTtFj\/+8D0vXr1hMV8wm004Oz3h+PUJz589Iy9yiiJntcoJAPlqRdbKuH\/3Dp9+8inD7R1++PFffP3Pr2l3vuezz\/7Ew+++4eHD79jZ3WEynXH+5pijBz+TJr\/DVAne0+l22Lt5i3Z3jSgBt5iTBMfPTx7z+ed\/4+nzI\/LlAtVIjBEzRa2iS8xQjFB1kue9vR3u3b2LCSSNFLOCaCVHRwd88eUXPHr0iG63w6vjY\/prfX79wR0+\/OA+Pz35N3\/+y195dnBIcJ7R9oCPPrzPy5cvOT0bc3p2xmQyYTqdIWK1pinOWdXmKBrryxTx3puI0Ov3yLIWWdZCVVmt8loUoSwjZVlWOiTw209+wx\/\/8HtmkzE\/Pf6FVrvNV1\/9nYPDQ5wITgQzJWqJqaKqqEY0VicTo14R3ivKXkmNmPeekAQajWal7OIuO+viY9W3z0masLe3R75cMZ1OSRsphwcHNQ1vFR7RSrWvvAIQJ4QQaDRSWlmTdjtjfa1Lt9O6AFQBCGmK9x7TypNifMv1W4C1H1VGxv8bzjuazbTSt06H9fU+\/X6fXq9Dp5WRZU2Cd6hFRAzvBNUS8d6ZiNTWAM45zMDqja\/62NXn\/w3IaGYZH3\/8EaPRkH6vV\/kbELyj0WiQpgGzqnaS4NEYq72JlEVOuGLgmBkxxndc\/SoQEbnC9X9hESHLmuzv73Dnzm289zQaTdJGQvCeJDgQKMuS4F1lFd5RFgXOC8tlgXdStb2I4J0DFFV7pw6ugoDKaEPwhHAhoobUiydpYK3fw4nQSFIajYSLLk4SR1mUZM0GGiMhOJyDJGmhGvHOUI2Ei7pwUh1rFL10e1cXn\/dyqeDe+0ugaRowrWKP91XeSRspIQScBxEjSQKNRsA7R\/CeNE0wVWIsq84zxQmoRqbT6cUJcRm0vPckQXA1CBGH84JGw3t3WTcXgStJAtGq1hYR0iQlCZ40TXGuOsGLhvBOKIvKG4uiQJwRiwKzWJuzVsJY1QggDlTBOcRV+cjM0FgVu6rW6VEwoKw7MEkS1CBGxVQRR0VH8LX7l6gIyxirIFevW+YFsSyIsaAsSoqyqCi7yEJmVndFHT\/rwIYYevFdnV2iKVABU1WCdxREFssFsSwxS+ucI6CKVSgwrJaUoqasoirPc1SV\/wDhNHm2gKzJHQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u0027ve already complained about my mySN laptop\n\u003Ca href=\u0022\/blog\/mysn-schenker-kurwa-ma%C4%87-de\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E here\u003C\/a\u003E and\n\u003Ca href=\u0022\/blog\/mysn-de-schenker-a-bittersweet-ending-of-a-horrible-customer-service\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E here\u003C\/a\u003E,\nbut now it turns out, there\u0027s a part three to be written...\u003C\/p\u003E\n\u003Cp\u003ELong story short, my main complaint (among many others) was this:\u003C\/p\u003E\n\u003Cblockquote class=\u0022blockquote ml-4 pl-4 border-left\u0022\u003E\n\u003Cp\u003EThe \u003Cstrong\u003Echarger would just disconnect randomly\u003C\/strong\u003E. Then connect back after a couple of minutes. Then disconnect again. One day it was better, the other it was worse. I almost didn\u2019t use it on battery anymore, for fear I would drain it and then not be able to charge it back.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003ESo basically: now it started happening again \ud83d\ude44\u003C\/p\u003E\n\u003Cp\u003EI\u0027m planning to get a new laptop anyway, a decent one this time,\nbut it\u0027s super annoying that it had to happen now, when I still have to wait a few weeks until Apple releases their new MacBooks Pro.\u003C\/p\u003E\n\u003Cp\u003EI do need to vent, though... So here we go:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ethis laptop didn\u0027t even serve me for three years yet, and it\u0027s already trash again,\u003C\/li\u003E\n\u003Cli\u003Enow I\u0027m even more sure that the original problem was absolutely their fault \u2013 it happened again, exactly the same, it\u0027s an obvious design flaw,\u003C\/li\u003E\n\u003Cli\u003Etheir website (mysn.de) is now down and it looks like they\u0027re out of business \u2013 exactly what they deserve.\u003C\/li\u003E\n\u003C\/ul\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["computer","crap","customer service","charger","laptop","mysn","opinion","quality","review","schenker","schenker technologies","service","unprofessional","warranty"],"hasMore":true,"image":"https:\/\/avris.it\/image\/mysn-0_small.jpeg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u0027ve already complained about my mySN laptop\n\u003Ca href=\u0022\/blog\/mysn-schenker-kurwa-ma%C4%87-de.lite\u0022\u003E here\u003C\/a\u003E and\n\u003Ca href=\u0022\/blog\/mysn-de-schenker-a-bittersweet-ending-of-a-horrible-customer-service.lite\u0022\u003E here\u003C\/a\u003E,\nbut now it turns out, there\u0027s a part three to be written...\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u0027ve already complained about my mySN laptop\n\u003Ca href=\u0022\/blog\/mysn-schenker-kurwa-ma%C4%87-de.lite\u0022\u003E here\u003C\/a\u003E and\n\u003Ca href=\u0022\/blog\/mysn-de-schenker-a-bittersweet-ending-of-a-horrible-customer-service.lite\u0022\u003E here\u003C\/a\u003E,\nbut now it turns out, there\u0027s a part three to be written...\u003C\/p\u003E\n\u003Cp\u003ELong story short, my main complaint (among many others) was this:\u003C\/p\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EThe \u003Cstrong\u003Echarger would just disconnect randomly\u003C\/strong\u003E. Then connect back after a couple of minutes. Then disconnect again. One day it was better, the other it was worse. I almost didn\u2019t use it on battery anymore, for fear I would drain it and then not be able to charge it back.\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003ESo basically: now it started happening again \ud83d\ude44\u003C\/p\u003E\n\u003Cp\u003EI\u0027m planning to get a new laptop anyway, a decent one this time,\nbut it\u0027s super annoying that it had to happen now, when I still have to wait a few weeks until Apple releases their new MacBooks Pro.\u003C\/p\u003E\n\u003Cp\u003EI do need to vent, though... So here we go:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ethis laptop didn\u0027t even serve me for three years yet, and it\u0027s already trash again,\u003C\/li\u003E\n\u003Cli\u003Enow I\u0027m even more sure that the original problem was absolutely their fault \u2013 it happened again, exactly the same, it\u0027s an obvious design flaw,\u003C\/li\u003E\n\u003Cli\u003Etheir website (mysn.de) is now down and it looks like they\u0027re out of business \u2013 exactly what they deserve.\u003C\/li\u003E\n\u003C\/ul\u003E","words":198,"readTime":null,"lang":"en"}}},"blog\/technology\/passwords-are-pass\u00e9":{"key":"blog\/technology\/passwords-are-pass\u00e9","type":"article","published":true,"meta":{"createdAt":"2020-04-18T11:09:31+02:00","publishedAt":"2020-04-18T11:09:31+02:00","group":null,"category":"blog","subcategory":"technology","slug":"passwords-are-pass\u00e9"},"content":{"en":{"slug":"passwords-are-pass\u00e9","title":"Passwords are pass\u00e9","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/password_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022267.47720364742\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEfUlEQVRIiWWWW48bRRCFv+rpsb0X7zVxQBCCEq3ywAsSvPA\/eOcv8jcQDyACPLBaIBIJIdlbkvXaY8\/04aF6Lt6sZO+4unvq1KmqU22z4z0BWP4yDMywbOvtwswA4Sbf44tqd+bV\/O3\/\/Jf69WxG3VO\/N3Zg2pdjmMBMBMsW61fpgAxOqt\/g2AwNzgn5goyEMiL3pQE8ZESkfHIIRIQBC6aWuQ9ZG0bnoAwJhiYN2AsZv6TNczmauMGNQWF+POS0hcFzH5fbO4cdE5kPu5sa\/0oZXCJl\/zZMGghilyaDkGMpMApEYeaA8PQNowwZWOe8Y8XusJM\/5oAaeb0lhJnugIJo1kbsTgtgZL4QEdG80MIg6gIoMpoENEDKDvtdPasig8FY5UDq3Ad30xv9oDBEgTE2mJiYGIyASbAOIIi1YGRGzN7WgkpuTwMoLYtgBIMacStnBCDlgjYTlnpQkQzG\/AfbBscBjkJgHGAaAscxMC0CK4nLJjENgdK8thZJvKkbKnmKk0QSjIMRMGrEYQjEYJxWNS+VPNUYarsud6fAA20\/0WAHcVKWPB6X7MXAozLyxb1DSjMu5zdcKDErCiSYbk24Xlb8eP2ehPHZZMxKiavVmkeTMaNQsAzGbH\/K3vER3\/\/0Oz\/cVvxVNzSCBnWsNub5i5lVryM5qINgfPv4E47GI+rLtxx88xXvX\/zHyT8vOPl4RrFYwv4+abrLvUVF+cszFnXi6ddfcrOzTfj5GdMHM4oHM1gu4fwKHj3ku9UKfjvl6mbJrcRKUOPdbXJFil3VGSTECpinhsvr91STMbGq2H83Z1oUrJOw0YiUoDzcJ518TvPqnI\/+2OK1FYxm9zi6mbMWWFFADLBak6oloWkod3aYFgXlICvuX0gBEFHKLZnRVoKrRlRbY84vrrAmoVdveFivuF4uOSxLqGt09px4\/5jm9E\/ezOdMDg64PXvOi7O\/OZ\/PeQocGLw9v+D5y1dsXVwxOdjj19uKd8mboMFVfDhubHY4VWHe1iViJxgPAjwpA7tZUT8dldwvC8zEk+0Ju7HgZlWzHSMvlyvOFhW7RWArGOd14m1K3I8FR7Hgdd3w76omBFgn43Rd83cNc4ylRC1olLtOYLOjPbkGiYAxzqDGiG0TEzO2gzEJxsRgKxhbwQ83wDyJRfJRE81YyQs1AGbu9Da54zWwELyTUWXJaARNJ44iokTKU6utISVRAUuD0kRMojQv+IBrkGVBbCRSP\/c3xkUrmnXWqBqjFlT0upWUB6w8fbFJIgTXj2CiydSl3JJreToLWZ5z6goyZecJZV0eTibbAOUzzANY5+du3qm\/irgAu2aSBMEcSJ2Rt4ob8JSGQQHK2pdZdm8DQGw4TdllyvrTAv5gdLR0tX+po14ZoM8uv4a04zPv0fDB9US5jXsw1nWSsPbaQ9LwRiCU3xF9Q2v2O1GwNkbrDlrW9w396MnqgLT4lC9Nygy2s8EDtcFdqIcrZ2iQyBx+yi8282SYNj3bBqJsbo93I77luQcu1AHstUddMAD\/A+DnkhKGvnqaAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/password_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022267.47720364742\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHackers know your password. I\u0027m like 99% sure they do.\nJust go to \u003Ca href=\u0022https:\/\/haveibeenpwned.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u0027;--have i been pwned?\u003C\/a\u003E and enter your email(s).\nSee? Your password is as good as public.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/password_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022534.95440729483\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEfUlEQVRIiWWWW48bRRCFv+rpsb0X7zVxQBCCEq3ywAsSvPA\/eOcv8jcQDyACPLBaIBIJIdlbkvXaY8\/04aF6Lt6sZO+4unvq1KmqU22z4z0BWP4yDMywbOvtwswA4Sbf44tqd+bV\/O3\/\/Jf69WxG3VO\/N3Zg2pdjmMBMBMsW61fpgAxOqt\/g2AwNzgn5goyEMiL3pQE8ZESkfHIIRIQBC6aWuQ9ZG0bnoAwJhiYN2AsZv6TNczmauMGNQWF+POS0hcFzH5fbO4cdE5kPu5sa\/0oZXCJl\/zZMGghilyaDkGMpMApEYeaA8PQNowwZWOe8Y8XusJM\/5oAaeb0lhJnugIJo1kbsTgtgZL4QEdG80MIg6gIoMpoENEDKDvtdPasig8FY5UDq3Ad30xv9oDBEgTE2mJiYGIyASbAOIIi1YGRGzN7WgkpuTwMoLYtgBIMacStnBCDlgjYTlnpQkQzG\/AfbBscBjkJgHGAaAscxMC0CK4nLJjENgdK8thZJvKkbKnmKk0QSjIMRMGrEYQjEYJxWNS+VPNUYarsud6fAA20\/0WAHcVKWPB6X7MXAozLyxb1DSjMu5zdcKDErCiSYbk24Xlb8eP2ehPHZZMxKiavVmkeTMaNQsAzGbH\/K3vER3\/\/0Oz\/cVvxVNzSCBnWsNub5i5lVryM5qINgfPv4E47GI+rLtxx88xXvX\/zHyT8vOPl4RrFYwv4+abrLvUVF+cszFnXi6ddfcrOzTfj5GdMHM4oHM1gu4fwKHj3ku9UKfjvl6mbJrcRKUOPdbXJFil3VGSTECpinhsvr91STMbGq2H83Z1oUrJOw0YiUoDzcJ518TvPqnI\/+2OK1FYxm9zi6mbMWWFFADLBak6oloWkod3aYFgXlICvuX0gBEFHKLZnRVoKrRlRbY84vrrAmoVdveFivuF4uOSxLqGt09px4\/5jm9E\/ezOdMDg64PXvOi7O\/OZ\/PeQocGLw9v+D5y1dsXVwxOdjj19uKd8mboMFVfDhubHY4VWHe1iViJxgPAjwpA7tZUT8dldwvC8zEk+0Ju7HgZlWzHSMvlyvOFhW7RWArGOd14m1K3I8FR7Hgdd3w76omBFgn43Rd83cNc4ylRC1olLtOYLOjPbkGiYAxzqDGiG0TEzO2gzEJxsRgKxhbwQ83wDyJRfJRE81YyQs1AGbu9Da54zWwELyTUWXJaARNJ44iokTKU6utISVRAUuD0kRMojQv+IBrkGVBbCRSP\/c3xkUrmnXWqBqjFlT0upWUB6w8fbFJIgTXj2CiydSl3JJreToLWZ5z6goyZecJZV0eTibbAOUzzANY5+du3qm\/irgAu2aSBMEcSJ2Rt4ob8JSGQQHK2pdZdm8DQGw4TdllyvrTAv5gdLR0tX+po14ZoM8uv4a04zPv0fDB9US5jXsw1nWSsPbaQ9LwRiCU3xF9Q2v2O1GwNkbrDlrW9w396MnqgLT4lC9Nygy2s8EDtcFdqIcrZ2iQyBx+yi8282SYNj3bBqJsbo93I77luQcu1AHstUddMAD\/A+DnkhKGvnqaAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/password_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022534.95440729483\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/unsplash.com\/photos\/zEFyM4sulJ8\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        unsplash.com\/photos\/zEFyM4sulJ8\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHackers know your password. I\u0027m like 99% sure they do.\nJust go to \u003Ca href=\u0022https:\/\/haveibeenpwned.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u0027;--have i been pwned?\u003C\/a\u003E and enter your email(s).\nSee? Your password is as good as public.\u003C\/p\u003E\n\u003Cp\u003EWe all hate passwords, don\u0027t we? Trying to keep them easy to remember, but also hard to break,\nwhile also complying with stupid \u003Ca href=\u0022https:\/\/twitter.com\/PWTooStrong\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E arbitrary rules\u003C\/a\u003E,\nwhile having corporate forcing you to change it regularly... They\u0027re a pain in the ass.\u003C\/p\u003E\n\u003Cp\u003EThey aren\u0027t even that safe.\nHow can you be sure that the administrator of a website that you trusted with your password even hashes it?\nHow do you know they salt it? How do you know they don\u0027t use an outdated hashing algorithm?\nHow can you be sure they won\u0027t have a data breach, their database leaked, and your password recovered with supercomputers?\u003C\/p\u003E\n\u003Cp\u003EDamn, I\u0027m an administrator myself, and I still can\u0027t be sure I do everything right.\nI got a panic attack last week when a user reported that his password was stolen and used for blackmail\n(\u003Ca href=\u0022\/blog\/recognising-red-flags-in-blackmail-emails\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Recognising red flags in blackmail emails\u003C\/a\u003E)\n\u2013 in this case it was a reused password that leaked somewhere else, but still...\nEven though I\u0027m storing people\u0027s passwords in the best way I can,\nI would feel so much better, if I just \u003Cem\u003Edidn\u0027t have to store them\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EHow about we just \u003Cem\u003Estop using passwords\u003C\/em\u003E?\u003C\/p\u003E\n\u003Ch3\u003E1. Social login\u003C\/h3\u003E\n\u003Cp\u003EIf you log in with Facebook, Twitter, Google, Apple or whatever, you make me a happier developer.\nYes, your social media account is still protected by a password, but at least \u003Cem\u003EI don\u0027t know it\u003C\/em\u003E.\nIf anything happens to your social media account, it\u0027s gonna be a problem of a huge corporation with\nwell-funded infosec department \u2013 not a random developer who makes websites for fun and does their best keeping them safe.\u003C\/p\u003E\n\u003Ch3\u003E2. Magic links\u003C\/h3\u003E\n\u003Cp\u003EIn my first job I saw in the logs that many users use the \u201cremind password\u201d feature not as a recovery option,\nbut as their main login method. Today, their quirk is becoming an increasingly popular security trend, actually.\nIf you go, for example, to \u003Ca href=\u0022https:\/\/whereby.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Whereby\u003C\/a\u003E, they\u0027ll only ask you for your email, not a password.\nEvery time you try to log in, they\u0027ll just send you and email with a one-time code.\u003C\/p\u003E\n\u003Cp\u003EI implemented a similar approach in my new project, \u003Ca href=\u0022\/projects\/avris-booster-quick-start-of-new-projects\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Avris Booster: Quick start of new projects\u003C\/a\u003E (under active development).\nNow I don\u0027t need a separate \u201cregister\u201d, \u201clog in\u201d and \u201cremind password\u201d forms \u2013 I just have one.\nNow I don\u0027t keep any passwords \u2013 just some temporary codes that can\u0027t be reused on other websites.\u003C\/p\u003E\n\u003Cp\u003EAnd users don\u0027t have to worry about remembering, storing or losing their passwords.\u003C\/p\u003E\n\u003Ch3\u003E3. Multi-factor authentication\u003C\/h3\u003E\n\u003Cp\u003EWhatever authentication method you use (or are forced to use), it\u0027s always better to have a second one.\nIf a website offers MFA, it\u0027s smart set it up (I can strongly recommend the \u003Ca href=\u0022https:\/\/authy.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Authy\u003C\/a\u003E app for it).\u003C\/p\u003E\n\u003Cp\u003EThis way, even if your password gets stolen, the hackers will still need more (your phone) to access your account.\u003C\/p\u003E\n\u003Ch3\u003E4. Other options\u003C\/h3\u003E\n\u003Cp\u003EThere\u0027s also such a thing as \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Hardware_security_module\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Hardware Security Modules\u003C\/a\u003E.\nSome websites offer login with \u003Ca href=\u0022https:\/\/www.openpgp.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PGP keys\u003C\/a\u003E.\nAnd there\u0027s probably a lot more options, but no time to dive into them right now.\u003C\/p\u003E\n\u003Ch3\u003E5. Password managers\u003C\/h3\u003E\n\u003Cp\u003ELet\u0027s face it, passwords are still inevitable. Until webmasters stop being so password-centric,\nwe have to keep using passwords, if we want to keep using their products.\u003C\/p\u003E\n\u003Cp\u003EThe best we can do in this situation, is to make sure that all of our passwords are strong and unique\n(so that a hacker who found out our Spotify password can\u0027t use it to log in to our bank or email).\nOf course, nobody can remember tens or hundreds of strong, unique password. That\u0027s why we have password managers.\nI can strongly recommend \u003Ca href=\u0022https:\/\/keepass.info\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E KeePass\u003C\/a\u003E. Or even saving the passwords in the browser.\u003C\/p\u003E\n\u003Cp\u003ESeriously, anything is better than using the same password for some shady forum as you use for your online banking.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["password","security","magic link","development","programming","hackers","hacking"],"hasMore":true,"image":"https:\/\/avris.it\/image\/password_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/password_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/password_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022133.73860182371\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHackers know your password. I\u0027m like 99% sure they do.\nJust go to \u003Ca href=\u0022https:\/\/haveibeenpwned.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u0027;--have i been pwned?\u003C\/a\u003E and enter your email(s).\nSee? Your password is as good as public.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/password_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/password_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022133.73860182371\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/unsplash.com\/photos\/zEFyM4sulJ8\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Eunsplash.com\/photos\/zEFyM4sulJ8\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHackers know your password. I\u0027m like 99% sure they do.\nJust go to \u003Ca href=\u0022https:\/\/haveibeenpwned.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u0027;--have i been pwned?\u003C\/a\u003E and enter your email(s).\nSee? Your password is as good as public.\u003C\/p\u003E\n\u003Cp\u003EWe all hate passwords, don\u0027t we? Trying to keep them easy to remember, but also hard to break,\nwhile also complying with stupid \u003Ca href=\u0022https:\/\/twitter.com\/PWTooStrong\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E arbitrary rules\u003C\/a\u003E,\nwhile having corporate forcing you to change it regularly... They\u0027re a pain in the ass.\u003C\/p\u003E\n\u003Cp\u003EThey aren\u0027t even that safe.\nHow can you be sure that the administrator of a website that you trusted with your password even hashes it?\nHow do you know they salt it? How do you know they don\u0027t use an outdated hashing algorithm?\nHow can you be sure they won\u0027t have a data breach, their database leaked, and your password recovered with supercomputers?\u003C\/p\u003E\n\u003Cp\u003EDamn, I\u0027m an administrator myself, and I still can\u0027t be sure I do everything right.\nI got a panic attack last week when a user reported that his password was stolen and used for blackmail\n(\u003Ca href=\u0022\/blog\/recognising-red-flags-in-blackmail-emails.lite\u0022\u003E Recognising red flags in blackmail emails\u003C\/a\u003E)\n\u2013 in this case it was a reused password that leaked somewhere else, but still...\nEven though I\u0027m storing people\u0027s passwords in the best way I can,\nI would feel so much better, if I just \u003Cem\u003Edidn\u0027t have to store them\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EHow about we just \u003Cem\u003Estop using passwords\u003C\/em\u003E?\u003C\/p\u003E\n\u003Ch3\u003E1. Social login\u003C\/h3\u003E\n\u003Cp\u003EIf you log in with Facebook, Twitter, Google, Apple or whatever, you make me a happier developer.\nYes, your social media account is still protected by a password, but at least \u003Cem\u003EI don\u0027t know it\u003C\/em\u003E.\nIf anything happens to your social media account, it\u0027s gonna be a problem of a huge corporation with\nwell-funded infosec department \u2013 not a random developer who makes websites for fun and does their best keeping them safe.\u003C\/p\u003E\n\u003Ch3\u003E2. Magic links\u003C\/h3\u003E\n\u003Cp\u003EIn my first job I saw in the logs that many users use the \u201cremind password\u201d feature not as a recovery option,\nbut as their main login method. Today, their quirk is becoming an increasingly popular security trend, actually.\nIf you go, for example, to \u003Ca href=\u0022https:\/\/whereby.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Whereby\u003C\/a\u003E, they\u0027ll only ask you for your email, not a password.\nEvery time you try to log in, they\u0027ll just send you and email with a one-time code.\u003C\/p\u003E\n\u003Cp\u003EI implemented a similar approach in my new project, \u003Ca href=\u0022\/projects\/avris-booster-quick-start-of-new-projects.lite\u0022\u003E Avris Booster: Quick start of new projects\u003C\/a\u003E (under active development).\nNow I don\u0027t need a separate \u201cregister\u201d, \u201clog in\u201d and \u201cremind password\u201d forms \u2013 I just have one.\nNow I don\u0027t keep any passwords \u2013 just some temporary codes that can\u0027t be reused on other websites.\u003C\/p\u003E\n\u003Cp\u003EAnd users don\u0027t have to worry about remembering, storing or losing their passwords.\u003C\/p\u003E\n\u003Ch3\u003E3. Multi-factor authentication\u003C\/h3\u003E\n\u003Cp\u003EWhatever authentication method you use (or are forced to use), it\u0027s always better to have a second one.\nIf a website offers MFA, it\u0027s smart set it up (I can strongly recommend the \u003Ca href=\u0022https:\/\/authy.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Authy\u003C\/a\u003E app for it).\u003C\/p\u003E\n\u003Cp\u003EThis way, even if your password gets stolen, the hackers will still need more (your phone) to access your account.\u003C\/p\u003E\n\u003Ch3\u003E4. Other options\u003C\/h3\u003E\n\u003Cp\u003EThere\u0027s also such a thing as \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Hardware_security_module\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Hardware Security Modules\u003C\/a\u003E.\nSome websites offer login with \u003Ca href=\u0022https:\/\/www.openpgp.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PGP keys\u003C\/a\u003E.\nAnd there\u0027s probably a lot more options, but no time to dive into them right now.\u003C\/p\u003E\n\u003Ch3\u003E5. Password managers\u003C\/h3\u003E\n\u003Cp\u003ELet\u0027s face it, passwords are still inevitable. Until webmasters stop being so password-centric,\nwe have to keep using passwords, if we want to keep using their products.\u003C\/p\u003E\n\u003Cp\u003EThe best we can do in this situation, is to make sure that all of our passwords are strong and unique\n(so that a hacker who found out our Spotify password can\u0027t use it to log in to our bank or email).\nOf course, nobody can remember tens or hundreds of strong, unique password. That\u0027s why we have password managers.\nI can strongly recommend \u003Ca href=\u0022https:\/\/keepass.info\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E KeePass\u003C\/a\u003E. Or even saving the passwords in the browser.\u003C\/p\u003E\n\u003Cp\u003ESeriously, anything is better than using the same password for some shady forum as you use for your online banking.\u003C\/p\u003E","words":656,"readTime":3,"lang":"en"}}},"blog\/technology\/redesigning-a-website-avi":{"key":"blog\/technology\/redesigning-a-website-avi","type":"article","published":true,"meta":{"createdAt":"2020-04-10T19:33:59+02:00","publishedAt":"2020-04-10T19:33:59+02:00","group":"redesign","links":[{"icon":"globe-europe","colour":"primary","url":"https:\/\/avi.avris.it","displayUrl":null},{"icon":"brands gitlab","colour":"secondary","url":"https:\/\/gitlab.com\/Avris\/Avi","displayUrl":null}],"category":"blog","subcategory":"technology","slug":"redesigning-a-website-avi"},"content":{"en":{"slug":"redesigning-a-website-avi","title":"Redesigning a website: Avi","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avi-comparison_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022403.61904761905\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAeCAYAAABE4bxTAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAF+ElEQVRYhbWXy48cVxXGf\/dVVd093Z6ezKPHYw\/jJNhjj+PEsRWwMxEKCFYIBSWLwIIFiCURfwQrlrCBDQKiyAobXlFYBITA4BBDHE8snPBMzMSKHz3TM+6Z7urqqntZVPdtT+ZhGw+f1OqS6tx7T33nO9+pEkmSOOccUkruFc45AJ59\/is0m2sYY2i1WzgHQgicc6Rpis2yu95TO+cQQnD+\/HmMMTz22HG0Vj4gSRJWV1awzoFzaKNJuylSKarVqk+qHcdYa1FKAQLnLEJIlJI460AIwIGDzFqSpLt1Qv2Lw4cPo7XGZimJTQFQSqO1Yqhc9guiKPLXWe\/JR0aqABitEVIA+eHW5sz3kxYCnANrLUmSbJmQSJLEAbTX1nHOMjRUpsf54L8HafSGxWmaehaNMcRxjDEBYRhsU5A7w5esEIbgQChJmmXE7VZPB6CUxBiD6MXCQD\/5+lx\/aZaRZXHvXn5fKYUxpsdQvnbx2lVe\/cNrzD00y\/zxTw7YEQLdD8I6XJpBIUQIEAiscxip0Nr0tt8McRuDpVKJoHf4TrGLt5a5uHqdlUXFU4+f2vCAg5K1214T9JiwvSCtNcYYrwchhP8BdLspQWBwzvVEvTWszfdbaq9x4dr7TO8Z5dBILU9ESpQUiE6n44QQxHFMlmVIIUAKPCXO4chlSq+VlVIEQXBba2dEUchO9pFllub6em\/PPmUgpcRogzYBRjFIKE3TPKk0RWntD+vDOYfW2h8oZa4r5xytuEM3SUjTlCiKKBaL27J0J\/iSOedyhqTcoIsdF\/fi1lsxURjgkmyD33g2BL5rRaB7dG+546DLlFI71n8rWGsHLFqHW+sgymF+KNBsNr0uwzDM9+8mBMF2tuAGXVav1ymVSpRKpY0hzuVGlib8+Nff44HKGF88\/aVNLCEFohgg1EBDQRAgLCBAK7XJxz4KIcTAqSuVMlJIkqRD\/6GDIMA5h3OOThrzD3eZ6+1hnnHP+24DUEoglUQMheSGkUP\/D1ryJUuShHK5sjlroNvtotB8\/uRzVMwwQggW6x+yf3Qy7zqpsFlGo9HAWkutVrvn8vvz+qJOkoRCobBlkLUWYIPgrzVuMlrOZ1i3m6KUJI5jnAgQLvFdqZTybEop83lpLVLKLZP2JTt7+S\/caq+hZS7uTjcffk8cfJSPTUxtWlirjvlZBnhLSJIWUiqkFGRZ5jXYF7eUkiiKkFKSpqlP3DPU96G1uEWapZsOHiqUCPTW46DfZb87e27g8vcJPbiQCJQ3xEqlckc\/6pfypTM\/YWm5gTEayIetdQ5Bzoi1lrjTAbfdRBzAa+i7535BfX2VRnuNzwYzvPjyGZIk4Wtf\/jrf+fZZqtUiT3\/mGG\/86QxxHBNFET986UdArqFicWv93Stk39iWKxFTDx\/i6kiBbpYx\/+STnDhxgrjt+GDBMP3AIRofKFauLPPCN16g8f4SwIbxsisJ9csyceAhupNjHDx2klqtRitNMcUi46MTfGLuNHK1Rq26n6MzR3jxWz\/g6MwRgLseM3cLr6HH\/3aTG\/UbzABjD5d4cGIBKRXDI3Oog79hWQiCqScwS2X2DGuCbSzifuFLViwVeWTuGFNTU2T2KtPTYwyVl2g2b1Aw+wnlFH+92ODKuUXmT85z5Y\/\/ATa+Oe7GzzO0d2qSTrfDRHEcI95Dhx8yNrGH1nKZhddXCSPD6U\/tZbY8y60LTWYrh\/8vDPnh+stfvcK7\/3wXgK8+\/QX+\/PPchR99rsqnv\/kmAKeO7mVhr+Wt+luMfm4U2H0N+ZK9dulnzD91ipff+D4rly5TaXbovHmJG\/\/6O8P7asweeYS3l\/7Nqwuvs2\/u47xy8Ryw+13mGaocEPz+2k+ZOB4xqjS3Llxk\/OZNhgtF3tEN6iJget9+wpkav118h8KBSWDA0G4x5Y1xuX2duNsCYFKN011aBkCNj1KX+VdmSYesr7dJbYaWionyMLC7xuhnWX\/y9r8qpZRw27s+gBSCzFqiIATwwzNNs11LSPdnV38uATu8YpK\/+9wW+9EPx\/vFfwEsBAWgUvaJSgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avi-comparison_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022403.61904761905\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYet another one of my projects, \u003Ca href=\u0022\/projects\/avi-simple-placeholder-avatars\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Avi \u2022 Simple placeholder avatars\u003C\/a\u003E,\ngrew too outdated to support it. I had to rewrite it from scratch.\u003C\/p\u003E\n\u003Cp\u003EI took the opportunity to redesign it as well.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avi-comparison_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022807.2380952381\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAeCAYAAABE4bxTAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAF+ElEQVRYhbWXy48cVxXGf\/dVVd093Z6ezKPHYw\/jJNhjj+PEsRWwMxEKCFYIBSWLwIIFiCURfwQrlrCBDQKiyAobXlFYBITA4BBDHE8snPBMzMSKHz3TM+6Z7urqqntZVPdtT+ZhGw+f1OqS6tx7T33nO9+pEkmSOOccUkruFc45AJ59\/is0m2sYY2i1WzgHQgicc6Rpis2yu95TO+cQQnD+\/HmMMTz22HG0Vj4gSRJWV1awzoFzaKNJuylSKarVqk+qHcdYa1FKAQLnLEJIlJI460AIwIGDzFqSpLt1Qv2Lw4cPo7XGZimJTQFQSqO1Yqhc9guiKPLXWe\/JR0aqABitEVIA+eHW5sz3kxYCnANrLUmSbJmQSJLEAbTX1nHOMjRUpsf54L8HafSGxWmaehaNMcRxjDEBYRhsU5A7w5esEIbgQChJmmXE7VZPB6CUxBiD6MXCQD\/5+lx\/aZaRZXHvXn5fKYUxpsdQvnbx2lVe\/cNrzD00y\/zxTw7YEQLdD8I6XJpBIUQIEAiscxip0Nr0tt8McRuDpVKJoHf4TrGLt5a5uHqdlUXFU4+f2vCAg5K1214T9JiwvSCtNcYYrwchhP8BdLspQWBwzvVEvTWszfdbaq9x4dr7TO8Z5dBILU9ESpQUiE6n44QQxHFMlmVIIUAKPCXO4chlSq+VlVIEQXBba2dEUchO9pFllub6em\/PPmUgpcRogzYBRjFIKE3TPKk0RWntD+vDOYfW2h8oZa4r5xytuEM3SUjTlCiKKBaL27J0J\/iSOedyhqTcoIsdF\/fi1lsxURjgkmyD33g2BL5rRaB7dG+546DLlFI71n8rWGsHLFqHW+sgymF+KNBsNr0uwzDM9+8mBMF2tuAGXVav1ymVSpRKpY0hzuVGlib8+Nff44HKGF88\/aVNLCEFohgg1EBDQRAgLCBAK7XJxz4KIcTAqSuVMlJIkqRD\/6GDIMA5h3OOThrzD3eZ6+1hnnHP+24DUEoglUQMheSGkUP\/D1ryJUuShHK5sjlroNvtotB8\/uRzVMwwQggW6x+yf3Qy7zqpsFlGo9HAWkutVrvn8vvz+qJOkoRCobBlkLUWYIPgrzVuMlrOZ1i3m6KUJI5jnAgQLvFdqZTybEop83lpLVLKLZP2JTt7+S\/caq+hZS7uTjcffk8cfJSPTUxtWlirjvlZBnhLSJIWUiqkFGRZ5jXYF7eUkiiKkFKSpqlP3DPU96G1uEWapZsOHiqUCPTW46DfZb87e27g8vcJPbiQCJQ3xEqlckc\/6pfypTM\/YWm5gTEayIetdQ5Bzoi1lrjTAbfdRBzAa+i7535BfX2VRnuNzwYzvPjyGZIk4Wtf\/jrf+fZZqtUiT3\/mGG\/86QxxHBNFET986UdArqFicWv93Stk39iWKxFTDx\/i6kiBbpYx\/+STnDhxgrjt+GDBMP3AIRofKFauLPPCN16g8f4SwIbxsisJ9csyceAhupNjHDx2klqtRitNMcUi46MTfGLuNHK1Rq26n6MzR3jxWz\/g6MwRgLseM3cLr6HH\/3aTG\/UbzABjD5d4cGIBKRXDI3Oog79hWQiCqScwS2X2DGuCbSzifuFLViwVeWTuGFNTU2T2KtPTYwyVl2g2b1Aw+wnlFH+92ODKuUXmT85z5Y\/\/ATa+Oe7GzzO0d2qSTrfDRHEcI95Dhx8yNrGH1nKZhddXCSPD6U\/tZbY8y60LTWYrh\/8vDPnh+stfvcK7\/3wXgK8+\/QX+\/PPchR99rsqnv\/kmAKeO7mVhr+Wt+luMfm4U2H0N+ZK9dulnzD91ipff+D4rly5TaXbovHmJG\/\/6O8P7asweeYS3l\/7Nqwuvs2\/u47xy8Ryw+13mGaocEPz+2k+ZOB4xqjS3Llxk\/OZNhgtF3tEN6iJget9+wpkav118h8KBSWDA0G4x5Y1xuX2duNsCYFKN011aBkCNj1KX+VdmSYesr7dJbYaWionyMLC7xuhnWX\/y9r8qpZRw27s+gBSCzFqiIATwwzNNs11LSPdnV38uATu8YpK\/+9wW+9EPx\/vFfwEsBAWgUvaJSgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avi-comparison_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022807.2380952381\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYet another one of my projects, \u003Ca href=\u0022\/projects\/avi-simple-placeholder-avatars\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Avi \u2022 Simple placeholder avatars\u003C\/a\u003E,\ngrew too outdated to support it. I had to rewrite it from scratch.\u003C\/p\u003E\n\u003Cp\u003EI took the opportunity to redesign it as well.\u003C\/p\u003E\n\u003Cp\u003EIt\u0027s quite a simple project, so it only took me a couple of hours. Here\u0027s what I did:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ereplaced my abandoned framework \u003Ca href=\u0022\/projects\/micrus-v4\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus v4 \u2022 Beauty of simplicity\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony 5\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Ereplaced \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Micrus-Assetic\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E custom Assetic setup\u003C\/a\u003E\nwith \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/frontend\/encore\/installation.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Webpack Encore\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Eupdated \u003Ca href=\u0022https:\/\/getbootstrap.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Bootstrap\u003C\/a\u003E from 3.0 to 4.4,\u003C\/li\u003E\n\u003Cli\u003Eadded more contrast to the design, while keeping it simple,\u003C\/li\u003E\n\u003Cli\u003Eremoved the ugly logo,\u003C\/li\u003E\n\u003Cli\u003Ereplaced the font that I used to overuse, \u003Ca href=\u0022https:\/\/design.ubuntu.com\/font\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Ubuntu\u003C\/a\u003E,\nwith the beautiful \u003Ca href=\u0022https:\/\/fonts.google.com\/specimen\/Baloo+Thambi+2\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Baloo Thambi 2\u003C\/a\u003E\nand \u003Ca href=\u0022https:\/\/www.jetbrains.com\/lp\/mono\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E JetBrains Mono\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Emoved the generation of links from backend to frontend \u2013\u00a0now it gives you an immediate feedback\nto changes in the form, without having to reload the website,\u003C\/li\u003E\n\u003Cli\u003Eremoved the \u201cLatest generated avatars\u201d section \u2013 I never liked it, but I needed some showcase\nof what this project does\u2026 with the immediate feedback in the \u201cTry it!\u201d section, it\u0027s not needed anymore,\u003C\/li\u003E\n\u003Cli\u003Eincluded some more \u003Ca href=\u0022\/blog\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E optimisations\u003C\/a\u003E.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EBefore:\u003C\/h3\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avi-old_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221695.2\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAYAAACJ8xqgAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFCklEQVRIia2W229UVRjFf3vvc84MnTkzhU5LOy3QYQqUQAKUIAoGFNFETEgw+mTiizFi4pN\/hNEXH4gxMSaGmKiJBpWgCeqDYPVBEeQqlGulF2m1tMN0hjlzLtuH6TntOAVF\/B73\/vaab+219pojHMfRAEII7qe01gAY4YIQgv7+fjb29WGnUg0HyqUSgQ7QGnzfxzAMgiBAAFYshpSyHnB4eJhSqYTnezhOBbRGCIkQAtOyKJfLuJ4HaKRUEWAIFA0WUgYIggDDMFBK3TNdz\/NqE4Z353sebrmCNk2wTNAahIBg5vekBB2AEKiY1QAY4kSUDakQUmHEYwhD4bou5XIZKSU6CBBSYlkWSkqk1typZi9Aa3TVJXDdOZuCwPeRCAwhUTPgd6toQl+A22ThaZ9gehoAZRqIGSUDoRFSoaSILHJXwMD3qVartQmEACUQ7qy\/tNZUKg5SCISU0XoymaxT2gg3pFKYpokQoR7zG11rjZQSKWuWCoKgrjdSOWysVqu1DcNAiBq9+SgGQYDWGqVUdBZAVKvVqFtrPa9Z\/6nqJowoz9C4V1PPHQTmUHYch9u3b2PbNrFYrOFQeOC2U+b6+DUMZZLPrmyYsi4cEokEpmlGh+eW7\/sAnB0+yb7Dr1EoT\/HZq0cb+iLKge\/jem5Dg2ma0TVorbFsi+Z1C8nQGokVigd\/EwW4oyDVanUmADRNTYloffTmOLdKRVZ25uoBPc9DCIFlWfMC3smXnu\/jBz5KyHrK47ducmnkGkopDGXMNNciKd1ks6FnzbyAhlIoKRvjS0mFZVoRbcHsvfwbK4U4UcCGT+m\/VJ0Pw8VCqcjQ+O8IKTGEJKYlgQYlJYlEArRJaboCwMJFSaanp6Jn2tbWRjwer6d8YnyQN3\/4nA3tOa4Vxukbs9j\/0Qek7BRrenupjq3i4IFjrF6bZfeeBzh44HXsdIqTx3\/hnf3vsnvP7voJLdvmqS1P8M2NAdoXLWeRX2HvCy9iJ5NcGRxkaiJLe3wVjz+8gaRKkom38NIrL\/P1wcPE1ezLkmGamLbNmWaDnX3bSOVytGQy3Jia5PLIEO2dWZrNTrZv3sqFfknCyJC12\/nwjfcpDhZYIGNRKkWUcxXBM0MeMMbG+AIy+TSWrKne3pbhtwUOA+evA7DywQ6M5h3c\/PMmANkVSxrf8nRhElku4zgV\/vBc\/PQlpqZ+QkqNUznNJx8vJWnHOH9uCNcPOP7Fl2zYup5vDx2lt3c1+VX5GmDoNdtOkevupimeYGJqAskw6XQfvu9R9SYwRZYdj6zn+qUjGKKFXCJHT1sParPCNuzZT5FwVNu2EWbtHhYvbgM\/y2TxEKaRxjLyLOtawf63LyJlF4tbu8j2rsO56GAXU2QWtjRSPnX2FG+9tw+Azo5Onl79ED9+6gDj9GzO0bn9Css6TgDQui7NkZEzjIyOQitsiveRZ3m9yjcKQ3T0tNC2PM33l79iemCAFs9nxZKlFI79zPnJIbZt3smWTY8yWBznuwuneWzXk1wpTjA6OdGosmkLvHSBZDyFXRRklMnkrwOIWyWyHe20LO2mlLAoOiVSiRbsXCcnRq8yZrpYqUQj5XzXCs5NtgLw7LLnWOJsIlGs\/eEn167B6VnF1eIYC+LNrMvkCXYJJooF9nY\/T35Jd2TsunC4n2oIh7lp43kerusihEAatejyfA\/LsHB9FykkgQ6ImTHkTPyHgOL\/\/iT+C3VfUNvDPRWOAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avi-old_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221695.2\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EAfter:\u003C\/h3\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avi-new_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022632\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAXCAYAAABj7u2bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACzElEQVRIib2Wu3IjVRCGvz6XmfHu4hvrMhkpkSNT1FJFsC9BxhtQvAAxAQHPCMHmrHGNR3NuTXBGkrXWSLLA+1epdGZa6v77fuT23XtlBt1JizGWh\/4BUEAmydz5v8OpzPLBWsvZ6SnOWUTM6r2qIsCwWJBzRkSQidqSYEzxOEJoVSUioKAoTAZiTAzDgDEGQRAjaCnVpBjevH6FKogIqmX6rrQ+3v1DKfPOzhJ6993tUZ68FKTscCPGyGKxIKXMxcX5ZyHkVswehXuJUgoPDwPGGj7e3eG9B11XSts0eO+3lvWfH\/4ipMjl6QVXl283ZCL116r65Lw3QilnTrru2Z7+8MuPfPnFOd9+c8OvP\/188P\/cLqG1FrZEbhuWni5xdXPD12+\/4s3F1cFkYE8NpZQopdA0zV5FOZfaoRM+3P9NLIWztuOye700hzEGa45MmaqScsa7nYGkqNL3A2MYgToCVMGYddS67gTF0rUeb+d1SQhxllCIAWtsTd1ngsulzAr7fmAYBkC5vr7+\/6zu2ECyGMN8ynJBhwhG6gdAp0rJkyPWAIqoVIWd389n2QBbCLmZ92vjY0S8Q175yTiEcaQf+2m\/Kd55mrahlAJjoWvbvaQAJh82zg42h9qnA06cnSK0Xq5ihNbXzrMIiOD2FP6hqCmbCdEh8+cooztStrPth8WCMI7kXDDGcH5+9iIEH8N9OmE3hNYQRTBGsNY8mcYvQmiXsKZMMNaDCPf396s0LmeTqmKMoZSC9w3WmjpQU6Lrumc7YdaGH5OoWN4DVetqiDFSSiGl9GRYigjjuCCEelPspoWsqrP6t51F91RuSom+7+sOshYRUBVEapRyzqtrbL09VnLee8zUmSEE2rZdPe+C++33P2aF63vy+vnQ7X8s5Pb797pt6wI452iaBkHJueC8I6WMMUIpSts0hBgJIZBz3kz3I+LPOf8L0k9\/atxDHsEAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avi-new_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022632\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["bootstrap","colour","design","redesign","refactoring","avi","avatar","webdevelopment","website","font","symfony","javascript"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avi-comparison_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avi-comparison_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avi-comparison_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022201.80952380952\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYet another one of my projects, \u003Ca href=\u0022\/projects\/avi-simple-placeholder-avatars.lite\u0022\u003E Avi \u2022 Simple placeholder avatars\u003C\/a\u003E,\ngrew too outdated to support it. I had to rewrite it from scratch.\u003C\/p\u003E\n\u003Cp\u003EI took the opportunity to redesign it as well.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avi-comparison_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avi-comparison_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022201.80952380952\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYet another one of my projects, \u003Ca href=\u0022\/projects\/avi-simple-placeholder-avatars.lite\u0022\u003E Avi \u2022 Simple placeholder avatars\u003C\/a\u003E,\ngrew too outdated to support it. I had to rewrite it from scratch.\u003C\/p\u003E\n\u003Cp\u003EI took the opportunity to redesign it as well.\u003C\/p\u003E\n\u003Cp\u003EIt\u0027s quite a simple project, so it only took me a couple of hours. Here\u0027s what I did:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ereplaced my abandoned framework \u003Ca href=\u0022\/projects\/micrus-v4.lite\u0022\u003E Micrus v4 \u2022 Beauty of simplicity\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony 5\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Ereplaced \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Micrus-Assetic\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E custom Assetic setup\u003C\/a\u003E\nwith \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/frontend\/encore\/installation.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Webpack Encore\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Eupdated \u003Ca href=\u0022https:\/\/getbootstrap.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Bootstrap\u003C\/a\u003E from 3.0 to 4.4,\u003C\/li\u003E\n\u003Cli\u003Eadded more contrast to the design, while keeping it simple,\u003C\/li\u003E\n\u003Cli\u003Eremoved the ugly logo,\u003C\/li\u003E\n\u003Cli\u003Ereplaced the font that I used to overuse, \u003Ca href=\u0022https:\/\/design.ubuntu.com\/font\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Ubuntu\u003C\/a\u003E,\nwith the beautiful \u003Ca href=\u0022https:\/\/fonts.google.com\/specimen\/Baloo+Thambi+2\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Baloo Thambi 2\u003C\/a\u003E\nand \u003Ca href=\u0022https:\/\/www.jetbrains.com\/lp\/mono\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E JetBrains Mono\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Emoved the generation of links from backend to frontend \u2013\u00a0now it gives you an immediate feedback\nto changes in the form, without having to reload the website,\u003C\/li\u003E\n\u003Cli\u003Eremoved the \u201cLatest generated avatars\u201d section \u2013 I never liked it, but I needed some showcase\nof what this project does\u2026 with the immediate feedback in the \u201cTry it!\u201d section, it\u0027s not needed anymore,\u003C\/li\u003E\n\u003Cli\u003Eincluded some more \u003Ca href=\u0022\/blog\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome.lite\u0022\u003E optimisations\u003C\/a\u003E.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EBefore:\u003C\/h3\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avi-old_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avi-old_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022423.8\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EAfter:\u003C\/h3\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avi-new_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avi-new_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022158\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E","words":169,"readTime":null,"lang":"en"}}},"blog\/technology\/my-biggest-maths-lesson":{"key":"blog\/technology\/my-biggest-maths-lesson","type":"article","published":true,"meta":{"createdAt":"2020-02-02T11:09:15+01:00","publishedAt":"2020-02-02T11:09:15+01:00","group":null,"category":"blog","subcategory":"technology","slug":"my-biggest-maths-lesson"},"content":{"en":{"slug":"my-biggest-maths-lesson","title":"My biggest maths lesson","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/coffee-milk_small.jpeg\u0022 alt=\u0022Coffee with milk\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022720\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAkCAYAAACTz\/ouAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHrUlEQVRIiVWXy48cVxXGf\/dRXV3d0zPtGY+t2EnAeUh2rOA4D0QSYEOCIvZRNgiRDfBnRAKxISsWSCxZBCERGQggIbHAggUIoiCxCQrYEMeezKNn+jFd73vvYXGr26al26oq1b3n9Z3vO6UGO0NBBAVordcLQEQQkfUzYwzGGESBQiEiuLbFeY\/3Du88PnhEBN\/ttVprlAAKtFIYY9BaoxSI0F0rFAqlFdZaUBCCsH4JkBDwKqCVJiDEf7DWGIjnr7201tKFAEqhOsMA1lqU1njv1\/sAQghxxRsUGlGCRWtUlyKl1H2PVdyqu2daGwSJBjqDzrloYPW+ikGt9gJYYwwSAqrzzlpL0uuRWPv\/6VEK7z3Gxjo0TYu1Nj7znmAM2mlEAwRCiPFZgmC0QWuF0oY07TMYDOj1eugHUmGM6TwTjLFYW1PXNcF7gvdoEYwxhKC6xIUYcSyIYLQlSRKGwyFJkmCtpdfrrVFkjEErjdbxgI2NDcqioCgKlnqJFDneaECImFEgCmuUjjdAmqZrSK5yPRwOMcaQ2ASbWBKboJQieE89GHJyckwIAde0NE2D0godcRxRFKGpSZIEAOdcRJIxDDc22Nzc5LFLj5H1LFoJ6WCLo8mE09MFRdWue0MBITjKusSJIBIQAlYpRZr2SdN0XeQVHHe2d3jh2hU+\/uefOZkfIRLQJuHxp77ApSdf5r2\/\/Jfl4h4Xzp3vchBwE0fwQtCC8iqiKB7ceaI0iU0YDjd48bnr\/P3mO+zt7bN\/NMP5wNZoQL6Y8+IrGce33+fh7RHnz5\/HaIVCaOqaSXuMRiGisCtK0DoaMFrT7\/d56KGLzA8+4l8f3eaTacl4c8DzV55gfGaH8nRG6pd85+uvc3BwFHOvFE1dUZYFy+WSZVWgVGcghID3jiRJ6PV6bJ85w+658xTTDzlcVLz6xWf59utfoZf0KOlh+xuc27nA+3tQ1566rtb1q+uG+WJBWVcIHot0POIDVhs2RyPO7e6SJpb+ucd56olH+ObrXyMb9PAorAChpT86y+To3wyHI5Kkh\/eetm0o8pzJ8REnsyk+BDQKfAixgaxhMMjIBgPG4zH\/uLXPm29+C4Nn6QxlKyhlGG+f53d\/vcVpUWJMhG6a9smyIaPNLUajLZIkQaEwG+ONt5QCrQ3DwZDt7W0GgwFnxtukvR4\/eucG\/e1LjLd3semQu3P48bt\/4Mavf8vDFx+mLAp6aR+jDcF7mqZmMZ8xn80pq+J+kb33VFUZOd45yirn6atXadqGn974DT9xLXfu3sEHDyGQWsUPb33IoD9g5+wu1z73HC+9+DJZlpFlGf00RaHQdI0tEqjqmqZtUdrgnKesap5\/9gVQwt7+Hq5t8W2LeEcIgvjA5ctP8f3vvs3maMQf\/3STfr\/PxsaoYwWFBoXqBKSua+azKXm+pCgKptMTyrLk3O4uZb4k+BYlIZKeCEGEDz74G+\/e+BlXrz7NzZu\/p2naSJRdT+kVeYkIrXOcnJwwm0YjQQJNW3PlycskVmO0wnQUHiOPEP\/lr97lB29\/D+cdQQLee9K0FyUAFEInOCjyImc+n7NcLinLnH6\/z2ce\/SxW68gvEkVoVTulFBIC2WDIG298gzPjMYvZlDTtR+IEAYkUG0KgdZ7pbMpkMmE2n9M0DVtbW+zunouareLBK1r2IgSBw8MDrDF477GJ7ahdo4Os+DtKn0ggz3Pm8xlHh4fk+RLvPM9cew7dSWMcOlSU7M5UXVf84r2fU9U13vlOOjVauqkgCmpX7LZhOptxNJlwfHxM41o+\/8JLpP0M9YB+RM6P44kAd+58zO3btyirKjqtNGawOXxLiLnUKo4mWilc28ZJwxjSXo8z422KouDOJ\/9h7dP6tyq6cOHCRRCYzmacnEzQQoAQG611DgmBEITWO2azGQf7n3L37idMpxO+9PKXGW1sxaR0dYgrdDEpsmxIVVVr01oE\/KrQIeCco3UtzjmWec7p6Sl7e\/fY3\/8UrRWvvvIatpPNVSDRBFy69AT9tMfp6YK2bREBk20O3lq9tEZ3l1MfPN45FIqmqen1ely8eJELFx5lf3+PumlAKayxXL\/2LF995TVm0xMWiwWnp6cs8yVWHkho6GChut7Q2lDVNafLJSJCv58BcOXyZa4\/c53Dw0PqumR39zzDwYDJ8WTNZc47gvfYIIISENUNwGhCl65Vh+dFjjWGg4N9+lnGaHOLM2PFo488sm6+vMgpypymaQjBUxQ5zvsYgSDxYAQlYT0KhhAwWkeOYk4Int6nKWm\/j3OeIAFr4whZVRXz2YyqqvDB0zYtrWujgdUcppCu4JHMlFI0ro24r+uYx8MDsiwDUZRlztZ4jHcuqlmRs1gsaFuHEPBesHF+idWNvaARwGiF8wGRgFIaH4S6afDzGebePbQxLPNTirIgsQlBAmVZ0bYtVVkiEinFhiBr0tJa4SWgFLReVvwRBSl4RAKudRxNjuLcdHaXosgZjUaIwGw+o3EtVV0TOm6zD\/bjmsRk9WERuUl1c6BXEXFlVXJ8ckya9UlswnK5JMsyqqqmbVta53CtixEkSULTNPeh6sN9apLYGaEzrFFIR0PzxZw0yzi7s0Nd1bSrzyjvCSKxdkrxP6LTigWq4eeDAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/coffee-milk_small.jpeg\u0022 alt=\u0022Coffee with milk\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022720\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe most important maths lesson in my life wasn\u0027t actually that hard. It wasn\u0027t even really about maths.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/coffee-milk_big.jpeg\u0022 alt=\u0022Coffee with milk\u0022 class=\u0022border\u0022 width=\u0022634\u0022 height=\u0022951\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAkCAYAAACTz\/ouAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHrUlEQVRIiVWXy48cVxXGf\/dRXV3d0zPtGY+t2EnAeUh2rOA4D0QSYEOCIvZRNgiRDfBnRAKxISsWSCxZBCERGQggIbHAggUIoiCxCQrYEMeezKNn+jFd73vvYXGr26al26oq1b3n9Z3vO6UGO0NBBAVordcLQEQQkfUzYwzGGESBQiEiuLbFeY\/3Du88PnhEBN\/ttVprlAAKtFIYY9BaoxSI0F0rFAqlFdZaUBCCsH4JkBDwKqCVJiDEf7DWGIjnr7201tKFAEqhOsMA1lqU1njv1\/sAQghxxRsUGlGCRWtUlyKl1H2PVdyqu2daGwSJBjqDzrloYPW+ikGt9gJYYwwSAqrzzlpL0uuRWPv\/6VEK7z3Gxjo0TYu1Nj7znmAM2mlEAwRCiPFZgmC0QWuF0oY07TMYDOj1eugHUmGM6TwTjLFYW1PXNcF7gvdoEYwxhKC6xIUYcSyIYLQlSRKGwyFJkmCtpdfrrVFkjEErjdbxgI2NDcqioCgKlnqJFDneaECImFEgCmuUjjdAmqZrSK5yPRwOMcaQ2ASbWBKboJQieE89GHJyckwIAde0NE2D0godcRxRFKGpSZIEAOdcRJIxDDc22Nzc5LFLj5H1LFoJ6WCLo8mE09MFRdWue0MBITjKusSJIBIQAlYpRZr2SdN0XeQVHHe2d3jh2hU+\/uefOZkfIRLQJuHxp77ApSdf5r2\/\/Jfl4h4Xzp3vchBwE0fwQtCC8iqiKB7ceaI0iU0YDjd48bnr\/P3mO+zt7bN\/NMP5wNZoQL6Y8+IrGce33+fh7RHnz5\/HaIVCaOqaSXuMRiGisCtK0DoaMFrT7\/d56KGLzA8+4l8f3eaTacl4c8DzV55gfGaH8nRG6pd85+uvc3BwFHOvFE1dUZYFy+WSZVWgVGcghID3jiRJ6PV6bJ85w+658xTTDzlcVLz6xWf59utfoZf0KOlh+xuc27nA+3tQ1566rtb1q+uG+WJBWVcIHot0POIDVhs2RyPO7e6SJpb+ucd56olH+ObrXyMb9PAorAChpT86y+To3wyHI5Kkh\/eetm0o8pzJ8REnsyk+BDQKfAixgaxhMMjIBgPG4zH\/uLXPm29+C4Nn6QxlKyhlGG+f53d\/vcVpUWJMhG6a9smyIaPNLUajLZIkQaEwG+ONt5QCrQ3DwZDt7W0GgwFnxtukvR4\/eucG\/e1LjLd3semQu3P48bt\/4Mavf8vDFx+mLAp6aR+jDcF7mqZmMZ8xn80pq+J+kb33VFUZOd45yirn6atXadqGn974DT9xLXfu3sEHDyGQWsUPb33IoD9g5+wu1z73HC+9+DJZlpFlGf00RaHQdI0tEqjqmqZtUdrgnKesap5\/9gVQwt7+Hq5t8W2LeEcIgvjA5ctP8f3vvs3maMQf\/3STfr\/PxsaoYwWFBoXqBKSua+azKXm+pCgKptMTyrLk3O4uZb4k+BYlIZKeCEGEDz74G+\/e+BlXrz7NzZu\/p2naSJRdT+kVeYkIrXOcnJwwm0YjQQJNW3PlycskVmO0wnQUHiOPEP\/lr97lB29\/D+cdQQLee9K0FyUAFEInOCjyImc+n7NcLinLnH6\/z2ce\/SxW68gvEkVoVTulFBIC2WDIG298gzPjMYvZlDTtR+IEAYkUG0KgdZ7pbMpkMmE2n9M0DVtbW+zunouareLBK1r2IgSBw8MDrDF477GJ7ahdo4Os+DtKn0ggz3Pm8xlHh4fk+RLvPM9cew7dSWMcOlSU7M5UXVf84r2fU9U13vlOOjVauqkgCmpX7LZhOptxNJlwfHxM41o+\/8JLpP0M9YB+RM6P44kAd+58zO3btyirKjqtNGawOXxLiLnUKo4mWilc28ZJwxjSXo8z422KouDOJ\/9h7dP6tyq6cOHCRRCYzmacnEzQQoAQG611DgmBEITWO2azGQf7n3L37idMpxO+9PKXGW1sxaR0dYgrdDEpsmxIVVVr01oE\/KrQIeCco3UtzjmWec7p6Sl7e\/fY3\/8UrRWvvvIatpPNVSDRBFy69AT9tMfp6YK2bREBk20O3lq9tEZ3l1MfPN45FIqmqen1ely8eJELFx5lf3+PumlAKayxXL\/2LF995TVm0xMWiwWnp6cs8yVWHkho6GChut7Q2lDVNafLJSJCv58BcOXyZa4\/c53Dw0PqumR39zzDwYDJ8WTNZc47gvfYIIISENUNwGhCl65Vh+dFjjWGg4N9+lnGaHOLM2PFo488sm6+vMgpypymaQjBUxQ5zvsYgSDxYAQlYT0KhhAwWkeOYk4Int6nKWm\/j3OeIAFr4whZVRXz2YyqqvDB0zYtrWujgdUcppCu4JHMlFI0ro24r+uYx8MDsiwDUZRlztZ4jHcuqlmRs1gsaFuHEPBesHF+idWNvaARwGiF8wGRgFIaH4S6afDzGebePbQxLPNTirIgsQlBAmVZ0bYtVVkiEinFhiBr0tJa4SWgFLReVvwRBSl4RAKudRxNjuLcdHaXosgZjUaIwGw+o3EtVV0TOm6zD\/bjmsRk9WERuUl1c6BXEXFlVXJ8ckya9UlswnK5JMsyqqqmbVta53CtixEkSULTNPeh6sN9apLYGaEzrFFIR0PzxZw0yzi7s0Nd1bSrzyjvCSKxdkrxP6LTigWq4eeDAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/coffee-milk_big.jpeg\u0022 alt=\u0022Coffee with milk\u0022 class=\u0022border\u0022 width=\u0022634\u0022 height=\u0022951\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/unsplash.com\/photos\/wkh1WvOygac\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        unsplash.com\/photos\/wkh1WvOygac\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe most important maths lesson in my life wasn\u0027t actually that hard. It wasn\u0027t even really about maths.\u003C\/p\u003E\n\u003Cp\u003EBack in the primary school we had the following problem to solve:\u003C\/p\u003E\n\u003Cblockquote class=\u0022blockquote ml-4 pl-4 border-left\u0022\u003E\n\u003Cp\u003EThere\u0027s a guy who likes his coffee... strange. He gets a cup of black coffee, drinks half of it,\nthen fills the empty half of the cup with milk. Drinks half of it and fills back up with milk.\nHis coffee gets whiter and whiter that way, until after the eighth time he just drinks it whole.\nHow much coffee and how much milk did he drink overall?\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EWe\u0027ve spent the entire lesson calculating this shit. An entire class of primary school kids\ntrying not to make a mistake in their fractions. And not just regular kids \u2013 it was an extracurricular\nfor pupils gifted at maths.\u003C\/p\u003E\n\u003Cp\u003EAt first he drank \u00bd a cup of coffee. Then he drank a half of this half-coffee half-milk mixture.\nSo now it\u0027s \u00bd + \u00bd\u22c5\u00bd = \u00be cup of coffee, and \u00bd\u22c5\u00bd = \u00bc cup of milk.\nThen he drank a half of the \u00bc-coffee \u00bc-milk mixture, or something... Then five more times...\u003C\/p\u003E\n\u003Cp\u003EOur young brains, that had just learned about fractions in the first place, were now melting,\nbasically trying to calculate the 8\u003Csup\u003Eth\u003C\/sup\u003E power of some messy fractions.\nEveryone got a different result. We were tired, disappointed and ready to give up.\u003C\/p\u003E\n\u003Cp\u003ESo then the teacher gave us the answer. It\u0027s one cup of coffee and 4 cups of milk. Simple as that.\nNot \u003Csup\u003E507\u003C\/sup\u003E\/\u003Csub\u003E512\u003C\/sub\u003E cups of coffee and \u003Csup\u003E1034\u003C\/sup\u003E\/\u003Csub\u003E256\u003C\/sub\u003E cups of milk,\nor whatever we came up with.\u003C\/p\u003E\n\u003Cp\u003EWhy were we so wrong and tired, while she managed to calculate the correct result in her head in a second?\u003C\/p\u003E\n\u003Cp\u003EBecause we were calculating how much he drank (exactly what the question was),\nwhile she calculated... how much he poured into the cup. He drank everything he had poured, so why not?\u003C\/p\u003E\n\u003Cp\u003EHe poured in a full cup of coffee and 8\u00d7 half of cup of milk, and then drank it in an overcomplicated way.\nThat\u0027s it.\u003C\/p\u003E\n\u003Cp\u003ESo here\u0027s my math lesson: if you\u0027re stuck solving a problem (any problem, not just primary school maths problems),\nbut it gets increasingly harder and harder to solve \u2013 don\u0027t keep plowing like an idiot,\nand stop being so sure you\u0027re gonna solve it if only you just work hard enough.\nInstead, take a step back, take a deep breath and try to find a totally different way around it.\u003C\/p\u003E\n\u003Cp\u003ESometimes it\u0027s way better to work smart than hard.\u003C\/p\u003E\n\u003Cp\u003EThe whole class (including the teacher who kept pretending to help us all along)\nhas spent an entire hour calculating boring and complex stuff,\nwhile we could have just spent a minute to think about it first.\u003C\/p\u003E\n\u003Cp\u003EWe didn\u0027t \u003Cem\u003Ewaste\u003C\/em\u003E that hour. It might have been one of the most valuable hours of my early life.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["maths","logic","problem","problem solving"],"hasMore":true,"image":"https:\/\/avris.it\/image\/coffee-milk_small.jpeg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/coffee-milk_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/coffee-milk_mini.jpeg\u0022 alt=\u0022Coffee with milk\u0022 width=\u0022240\u0022 height=\u0022360\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe most important maths lesson in my life wasn\u0027t actually that hard. It wasn\u0027t even really about maths.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/coffee-milk_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/coffee-milk_mini.jpeg\u0022 alt=\u0022Coffee with milk\u0022 width=\u0022240\u0022 height=\u0022360\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/unsplash.com\/photos\/wkh1WvOygac\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Eunsplash.com\/photos\/wkh1WvOygac\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe most important maths lesson in my life wasn\u0027t actually that hard. It wasn\u0027t even really about maths.\u003C\/p\u003E\n\u003Cp\u003EBack in the primary school we had the following problem to solve:\u003C\/p\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003EThere\u0027s a guy who likes his coffee... strange. He gets a cup of black coffee, drinks half of it,\nthen fills the empty half of the cup with milk. Drinks half of it and fills back up with milk.\nHis coffee gets whiter and whiter that way, until after the eighth time he just drinks it whole.\nHow much coffee and how much milk did he drink overall?\u003C\/p\u003E\n\u003C\/blockquote\u003E\n\u003Cp\u003EWe\u0027ve spent the entire lesson calculating this shit. An entire class of primary school kids\ntrying not to make a mistake in their fractions. And not just regular kids \u2013 it was an extracurricular\nfor pupils gifted at maths.\u003C\/p\u003E\n\u003Cp\u003EAt first he drank \u00bd a cup of coffee. Then he drank a half of this half-coffee half-milk mixture.\nSo now it\u0027s \u00bd + \u00bd\u22c5\u00bd = \u00be cup of coffee, and \u00bd\u22c5\u00bd = \u00bc cup of milk.\nThen he drank a half of the \u00bc-coffee \u00bc-milk mixture, or something... Then five more times...\u003C\/p\u003E\n\u003Cp\u003EOur young brains, that had just learned about fractions in the first place, were now melting,\nbasically trying to calculate the 8\u003Csup\u003Eth\u003C\/sup\u003E power of some messy fractions.\nEveryone got a different result. We were tired, disappointed and ready to give up.\u003C\/p\u003E\n\u003Cp\u003ESo then the teacher gave us the answer. It\u0027s one cup of coffee and 4 cups of milk. Simple as that.\nNot \u003Csup\u003E507\u003C\/sup\u003E\/\u003Csub\u003E512\u003C\/sub\u003E cups of coffee and \u003Csup\u003E1034\u003C\/sup\u003E\/\u003Csub\u003E256\u003C\/sub\u003E cups of milk,\nor whatever we came up with.\u003C\/p\u003E\n\u003Cp\u003EWhy were we so wrong and tired, while she managed to calculate the correct result in her head in a second?\u003C\/p\u003E\n\u003Cp\u003EBecause we were calculating how much he drank (exactly what the question was),\nwhile she calculated... how much he poured into the cup. He drank everything he had poured, so why not?\u003C\/p\u003E\n\u003Cp\u003EHe poured in a full cup of coffee and 8\u00d7 half of cup of milk, and then drank it in an overcomplicated way.\nThat\u0027s it.\u003C\/p\u003E\n\u003Cp\u003ESo here\u0027s my math lesson: if you\u0027re stuck solving a problem (any problem, not just primary school maths problems),\nbut it gets increasingly harder and harder to solve \u2013 don\u0027t keep plowing like an idiot,\nand stop being so sure you\u0027re gonna solve it if only you just work hard enough.\nInstead, take a step back, take a deep breath and try to find a totally different way around it.\u003C\/p\u003E\n\u003Cp\u003ESometimes it\u0027s way better to work smart than hard.\u003C\/p\u003E\n\u003Cp\u003EThe whole class (including the teacher who kept pretending to help us all along)\nhas spent an entire hour calculating boring and complex stuff,\nwhile we could have just spent a minute to think about it first.\u003C\/p\u003E\n\u003Cp\u003EWe didn\u0027t \u003Cem\u003Ewaste\u003C\/em\u003E that hour. It might have been one of the most valuable hours of my early life.\u003C\/p\u003E","words":471,"readTime":2,"lang":"en"}}},"blog\/technology\/why-even-use-constants":{"key":"blog\/technology\/why-even-use-constants","type":"article","published":true,"meta":{"createdAt":"2020-01-29T19:19:32+01:00","publishedAt":"2020-01-29T19:19:32+01:00","group":null,"category":"blog","subcategory":"technology","slug":"why-even-use-constants"},"content":{"en":{"slug":"why-even-use-constants","title":"Why even use constants?","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/constants_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022246.66666666667\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADGUlEQVRIib2Wz44cRQzGf65ydfcMu4PCBnEiAoSE4BCQEkCIEyeegjfhDXgiHiAcEsQNJC5ISJwQkCXazG53V9kcqnp6pAhpDptYKvU\/u\/zZbbs+kQffjAjggFu9MQehLYEgIAE4eicCIVT95RsO7pAzmEEp7d2RjQNWoFjVXUQChICCd5hDaEZuEBs4kQoAwMsK5oAWiAuoRTFAVKQYjlanx6uUBkCqrpUKkhqA0vdghc8+eoevv7jf\/CxRrYHXLPoKcgEgskZ6iLgZSAO4ZG7Jjtm6uQjfP\/mFx7\/+DqIoXYICX378Pt9+\/h7+1jU\/xsinu094VXI1Tjz+7Q8IijJ0kIEY8A8+BOAh4Mf\/92WLtJJJEWWaoIyQZy5vMmfPLtE37oBGrNW3hvWvyaFWbhNQBUOnaO0qAzc2V5kpb5n+HNFN5G86hiS4Q4wQyJxv9fYBmcE0gUS0tmAGd+JGIRbSWSI\/z1z0zogc6hFR9iO8Ntx2lrx2cSnoYV64kSWTtgkRIQ4R0eo4G8SjsfNSROow1AqmOuo3PRQYn46EFAjTP2jXEW5Gyt27ZBu5mq7ocofjZMvkkjnvz9jP12TLbLstucycpx1d6k4DYzU7REeZcpsNTggBK7aCVsXmGRl69PISSUo4u+D5dEm2zEY3aFCu8w27YUf0SEoJqF16cgMs0z3MKG6QZ3B7sdVDoJzvYH5GGQZs\/xdqW9L+X3avv43qiwV+vMfJo+NwzAiKhNrbzVhUGN4cmmZHBEh36uNwr14u3j3N0alSDMYJfN\/mkBmYY2aICKUUQgjEGG\/X8f\/J0sZjJiypQoScK5CU0qsDA2COTBmRgHL1FER49OgJ30VwLxBiZRRma5sf6AaVCZR2SMYAoYG3sh6wIiBxtTumNwe+U2nNDz\/9jFCZgMi9r5zpGmwGz1DaFYfNOaSOSilS3Wdxelgtw6qV03gDao1mxARR6x5ebcUbmKVuBYg9SECZx4modUMvLfq8ZmMuSEowT40jhRqbpgOpIs\/1Pibo+5q1pTbz1LKkIKlxogwu9TxKPY4g7rgo\/wFfX5oLEV+cMgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/constants_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022246.66666666667\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u0027ve seen some begginer programmers asking themselves: why do I even need constants?\nVariables I get, they\u0027re super important, but why have an extra thing that\u0027s \u003Cem\u003Elike\u003C\/em\u003E a variable, \u003Cem\u003Ebut worse\u003C\/em\u003E?\nIt can\u0027t even change! And if I know that \u003Ccode\u003Econst NUMBER_OF_COLUMNS = 3\u003C\/code\u003E, why can\u0027t I just write \u003Ccode\u003E3\u003C\/code\u003E?\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/constants_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022493.33333333333\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADGUlEQVRIib2Wz44cRQzGf65ydfcMu4PCBnEiAoSE4BCQEkCIEyeegjfhDXgiHiAcEsQNJC5ISJwQkCXazG53V9kcqnp6pAhpDptYKvU\/u\/zZbbs+kQffjAjggFu9MQehLYEgIAE4eicCIVT95RsO7pAzmEEp7d2RjQNWoFjVXUQChICCd5hDaEZuEBs4kQoAwMsK5oAWiAuoRTFAVKQYjlanx6uUBkCqrpUKkhqA0vdghc8+eoevv7jf\/CxRrYHXLPoKcgEgskZ6iLgZSAO4ZG7Jjtm6uQjfP\/mFx7\/+DqIoXYICX378Pt9+\/h7+1jU\/xsinu094VXI1Tjz+7Q8IijJ0kIEY8A8+BOAh4Mf\/92WLtJJJEWWaoIyQZy5vMmfPLtE37oBGrNW3hvWvyaFWbhNQBUOnaO0qAzc2V5kpb5n+HNFN5G86hiS4Q4wQyJxv9fYBmcE0gUS0tmAGd+JGIRbSWSI\/z1z0zogc6hFR9iO8Ntx2lrx2cSnoYV64kSWTtgkRIQ4R0eo4G8SjsfNSROow1AqmOuo3PRQYn46EFAjTP2jXEW5Gyt27ZBu5mq7ocofjZMvkkjnvz9jP12TLbLstucycpx1d6k4DYzU7REeZcpsNTggBK7aCVsXmGRl69PISSUo4u+D5dEm2zEY3aFCu8w27YUf0SEoJqF16cgMs0z3MKG6QZ3B7sdVDoJzvYH5GGQZs\/xdqW9L+X3avv43qiwV+vMfJo+NwzAiKhNrbzVhUGN4cmmZHBEh36uNwr14u3j3N0alSDMYJfN\/mkBmYY2aICKUUQgjEGG\/X8f\/J0sZjJiypQoScK5CU0qsDA2COTBmRgHL1FER49OgJ30VwLxBiZRRma5sf6AaVCZR2SMYAoYG3sh6wIiBxtTumNwe+U2nNDz\/9jFCZgMi9r5zpGmwGz1DaFYfNOaSOSilS3Wdxelgtw6qV03gDao1mxARR6x5ebcUbmKVuBYg9SECZx4modUMvLfq8ZmMuSEowT40jhRqbpgOpIs\/1Pibo+5q1pTbz1LKkIKlxogwu9TxKPY4g7rgo\/wFfX5oLEV+cMgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/constants_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022493.33333333333\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u0027ve seen some begginer programmers asking themselves: why do I even need constants?\nVariables I get, they\u0027re super important, but why have an extra thing that\u0027s \u003Cem\u003Elike\u003C\/em\u003E a variable, \u003Cem\u003Ebut worse\u003C\/em\u003E?\nIt can\u0027t even change! And if I know that \u003Ccode\u003Econst NUMBER_OF_COLUMNS = 3\u003C\/code\u003E, why can\u0027t I just write \u003Ccode\u003E3\u003C\/code\u003E?\u003C\/p\u003E\n\u003Cp\u003EWell, first of all, it\u0027s not always just a simple \u003Ccode\u003E3\u003C\/code\u003E. Sometimes, for example, a constant is \u003Ccode\u003E3.141592653589793...\u003C\/code\u003E.\nIn this case writing \u003Ccode\u003EMath::PI\u003C\/code\u003E is not only \u003Cstrong\u003Eshorter\u003C\/strong\u003E, \u003Cstrong\u003Eprettier\u003C\/strong\u003E, and more \u003Cstrong\u003Emeaningful\u003C\/strong\u003E,\nbut usually more \u003Cstrong\u003Eaccurate\u003C\/strong\u003E (how many digits of \u03c0 can you write down? your standard library knows \u003Cem\u003Ea lot\u003C\/em\u003E of them)\nand \u003Cstrong\u003Enot prone to typos\u003C\/strong\u003E (misspelled constant name just won\u0027t compile...).\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Elet\u003C\/span\u003E circ1 = \u003Cspan class=\u0022hljs-number\u0022\u003E2\u003C\/span\u003E * \u003Cspan class=\u0022hljs-built_in\u0022\u003EMath\u003C\/span\u003E.PI * radius;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Elet\u003C\/span\u003E circ2 = \u003Cspan class=\u0022hljs-number\u0022\u003E2\u003C\/span\u003E * \u003Cspan class=\u0022hljs-number\u0022\u003E3.141582653589793\u003C\/span\u003E * radius;\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe first line better resembles the well-known mathematical formula,\nand it doesn\u0027t require googling (or remembering) the actual value.\nThe second one? Apart from being ugly, it\u0027s also wrong. Look closely.\u003C\/p\u003E\n\u003Cp\u003ECreating a constant with some value gives this value a \u003Cstrong\u003Elabel\u003C\/strong\u003E. Gives it an extra meaning.\nIt\u0027s not just a three anymore. Now it\u0027s the \u003Ccode\u003ENUMBER_OF_COLUMNS\u003C\/code\u003E (that just happens to be three).\u003C\/p\u003E\n\u003Cp\u003ENow it\u0027s a three that\u0027s different from other threes.\u003C\/p\u003E\n\u003Cp\u003ELet\u0027s say you have \u003Ccode\u003E3\u003C\/code\u003E columns of data updated every \u003Ccode\u003E3\u003C\/code\u003E minutes. Your code is full of threes.\nAfter coming back to your code after a break, you don\u0027t know anymore what those threes mean, they\u0027re just some numbers.\nIf one day you have to change the layout to two columns, how do you know which threes to replace with twos,\nand which ones to keep?\u003C\/p\u003E\n\u003Cp\u003EDo you have to look through your entire codebase, read it and understand it?\u003C\/p\u003E\n\u003Cp\u003EOr maybe instead you have \u003Ccode\u003ENUMBER_OF_COLUMNS\u003C\/code\u003E columns of date updated every \u003Ccode\u003EUPDATE_INTERVAL\u003C\/code\u003E minutes?\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E NUMBER_OF_COLUMNS = \u003Cspan class=\u0022hljs-number\u0022\u003E3\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Econst\u003C\/span\u003E UPDATE_INTERVAL = \u003Cspan class=\u0022hljs-number\u0022\u003E3\u003C\/span\u003E;\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EEasy to understand wherever they are used, and super easy to change in just a single place.\u003C\/p\u003E\n\u003Cp\u003EConstants are only constant during the execution.\nDuring development \u2013 the actually make changes \u003Cem\u003Eeasier\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EAnd yes, you can do \u201cless\u201d with them, but that property actually \u003Cem\u003Eadds\u003C\/em\u003E value.\nIt lets the programmers (and the compiler) know that it\u0027s \u003Cem\u003Enot supposed\u003C\/em\u003E to change.\nIt prevents your app from being inconsistent because someone accidentally overwrote a variable.\u003C\/p\u003E\n\u003Cp\u003ESo there you go: constants, although less flexible, are just as useful as variables.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["programming","constant","variable"],"hasMore":true,"image":"https:\/\/avris.it\/image\/constants_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/constants_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/constants_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022123.33333333333\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u0027ve seen some begginer programmers asking themselves: why do I even need constants?\nVariables I get, they\u0027re super important, but why have an extra thing that\u0027s \u003Cem\u003Elike\u003C\/em\u003E a variable, \u003Cem\u003Ebut worse\u003C\/em\u003E?\nIt can\u0027t even change! And if I know that \u003Ccode\u003Econst NUMBER_OF_COLUMNS = 3\u003C\/code\u003E, why can\u0027t I just write \u003Ccode\u003E3\u003C\/code\u003E?\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/constants_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/constants_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022123.33333333333\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u0027ve seen some begginer programmers asking themselves: why do I even need constants?\nVariables I get, they\u0027re super important, but why have an extra thing that\u0027s \u003Cem\u003Elike\u003C\/em\u003E a variable, \u003Cem\u003Ebut worse\u003C\/em\u003E?\nIt can\u0027t even change! And if I know that \u003Ccode\u003Econst NUMBER_OF_COLUMNS = 3\u003C\/code\u003E, why can\u0027t I just write \u003Ccode\u003E3\u003C\/code\u003E?\u003C\/p\u003E\n\u003Cp\u003EWell, first of all, it\u0027s not always just a simple \u003Ccode\u003E3\u003C\/code\u003E. Sometimes, for example, a constant is \u003Ccode\u003E3.141592653589793...\u003C\/code\u003E.\nIn this case writing \u003Ccode\u003EMath::PI\u003C\/code\u003E is not only \u003Cstrong\u003Eshorter\u003C\/strong\u003E, \u003Cstrong\u003Eprettier\u003C\/strong\u003E, and more \u003Cstrong\u003Emeaningful\u003C\/strong\u003E,\nbut usually more \u003Cstrong\u003Eaccurate\u003C\/strong\u003E (how many digits of \u03c0 can you write down? your standard library knows \u003Cem\u003Ea lot\u003C\/em\u003E of them)\nand \u003Cstrong\u003Enot prone to typos\u003C\/strong\u003E (misspelled constant name just won\u0027t compile...).\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003Elet circ1 = 2 * Math.PI * radius;\nlet circ2 = 2 * 3.141582653589793 * radius;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe first line better resembles the well-known mathematical formula,\nand it doesn\u0027t require googling (or remembering) the actual value.\nThe second one? Apart from being ugly, it\u0027s also wrong. Look closely.\u003C\/p\u003E\n\u003Cp\u003ECreating a constant with some value gives this value a \u003Cstrong\u003Elabel\u003C\/strong\u003E. Gives it an extra meaning.\nIt\u0027s not just a three anymore. Now it\u0027s the \u003Ccode\u003ENUMBER_OF_COLUMNS\u003C\/code\u003E (that just happens to be three).\u003C\/p\u003E\n\u003Cp\u003ENow it\u0027s a three that\u0027s different from other threes.\u003C\/p\u003E\n\u003Cp\u003ELet\u0027s say you have \u003Ccode\u003E3\u003C\/code\u003E columns of data updated every \u003Ccode\u003E3\u003C\/code\u003E minutes. Your code is full of threes.\nAfter coming back to your code after a break, you don\u0027t know anymore what those threes mean, they\u0027re just some numbers.\nIf one day you have to change the layout to two columns, how do you know which threes to replace with twos,\nand which ones to keep?\u003C\/p\u003E\n\u003Cp\u003EDo you have to look through your entire codebase, read it and understand it?\u003C\/p\u003E\n\u003Cp\u003EOr maybe instead you have \u003Ccode\u003ENUMBER_OF_COLUMNS\u003C\/code\u003E columns of date updated every \u003Ccode\u003EUPDATE_INTERVAL\u003C\/code\u003E minutes?\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003Econst NUMBER_OF_COLUMNS = 3;\nconst UPDATE_INTERVAL = 3;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EEasy to understand wherever they are used, and super easy to change in just a single place.\u003C\/p\u003E\n\u003Cp\u003EConstants are only constant during the execution.\nDuring development \u2013 the actually make changes \u003Cem\u003Eeasier\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EAnd yes, you can do \u201cless\u201d with them, but that property actually \u003Cem\u003Eadds\u003C\/em\u003E value.\nIt lets the programmers (and the compiler) know that it\u0027s \u003Cem\u003Enot supposed\u003C\/em\u003E to change.\nIt prevents your app from being inconsistent because someone accidentally overwrote a variable.\u003C\/p\u003E\n\u003Cp\u003ESo there you go: constants, although less flexible, are just as useful as variables.\u003C\/p\u003E","words":379,"readTime":2,"lang":"en"}}},"blog\/technology\/what-i-use":{"key":"blog\/technology\/what-i-use","type":"article","published":true,"meta":{"createdAt":"2020-01-14T11:26:18+01:00","publishedAt":"2020-01-14T11:26:18+01:00","group":null,"category":"blog","subcategory":"technology","slug":"what-i-use"},"content":{"en":{"slug":"what-i-use","title":"What I use?","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/workspace_small.png\u0022 alt=\u0022My workspace\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022360\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAKcklEQVRIiV2X24+kx1mHn6r6jn2eU8\/sbM\/M7uzu7M6udzfrGCvEmAQ5KImjKCYiXEQgDuIOxA0SF1z5jj8ACcQFCgJhARdIKEIEhyhOiOygrJ1ge7Pe03h3Z3pOPd1fH77u\/k5VxUWPNxIllVSluvm99b76vc8r\/uRP\/8IeH7cp8gm+K9mfbHCQXcaxMZ6NsCjmsu+hSHnppS\/y2heu8cmy1s4OAoQQCCGQAoQUCCGRUiKVmm0BeV7wt\/\/2N9SDJaL4hFsXbnBpc4tcF3z7B9+mFpRxHh1YfFmlteoz6E9oVie04xrahGTWxyIo1BaBvkc2forr38LamRhjzDNRQgiElAgpkFIgTwUJKXAcNQugKJirLXF\/5yFPdvdQqQs4TIopjz7+mFqlgvM7r90kSydUgoTBKCGOcxbGJaKRYDp2mKQFpFfx+k8ZjROUcjDWUhSarNAUhcZai1IKx1G4roOSCiEVQgqsNTzt7EAWcPuj27QPj+j0u7ilgLv7O3y8\/5R+3qWxUGJz4zyi\/fC2Pf1zBGAMmNOo0zSnF\/WJ4wnj8YTOSY80SRDaIIxB5wXSQn8UkynNuY011tZaLDWXcJQDwvJw\/32OTg7R05APHn3Aoyc7DMcjpKvQ+ZRatcpSs4lTMvSOT3B8f5YWEKepgO\/+xw+pTBWulDTKFZbKZTbDZSoX1vE9BVZjrUEbDQjeu\/+If37nTeq1CnPz85SThLu7tzno7tKPBnhOyGRYIK1AeJqK8JDKRShF8+wCvuciUNQrdZzBZML3v\/c2X3\/tVawAYwWLy4t8prZJGHhgDcYIpBKAnt1tgTY5UimMMbiuIs8KpklCmuWcDE4otOV4uM9wPCbu55hckmtLqVSlVPEwSUEjlOROCddx6ex1sF6KfPdnH\/KXf\/0t\/u4f\/oXxZIqQitbmGrudI7I8QwqFQSKERCgHpMAKBUJhkSAVruuRZinJZEKSpJTcOlIo1ua3cD1JrbrMOMmp1RbxXZ8kKXh++9OYksskHVOixNRMsMKi9vYOX\/c8xePHT0niIWdbZ1lePsPDOw9oLSwilTr9FYMQAm0MFrDWYNAYa4lGMT+++z6VapVKrU4Qlgn8Mtc2n+cwanN57TqHvROUI\/iNV75Eo7rIC1deYL\/zhF957tdZXlriweEdrq5fxdndO2CuXidLDR\/+9A57Rz3OtNapFQ63zm0iHQcpBIXWaE7rRoCxhqzIKYzFIpFSkRea406H\/ijGUZJBd8jN1ssszC+wdmaDc611wqDE1ijB9wQvX\/k85y5c459+9Fd87XPf4MWtz+EsNBrUqxUalRJz5QpRp8fRSY+y8vnGS79GYTVoi7ZgCkOuc5I8oTvo0un3OI4iBtMEGYY8enKMakeUSgHl0CPq9lhrLWDyhKvPfYpSWCbNMtLcMO0f4SifvDB8+dbvoqTPMM5whvGIQue4CpIixXM8MmMZpFPeffiANE9pHx9SblQIamXuPnyA6ytcz6XQBaPhEGthmmZ0h33a7Q5CumTplEajzh\/\/wddOXVthrOAkGhPHMY\/efRunVCUeJ1TnFilVHCwCp1qr0u8PKLTGdx0mScbq+Qv4QcDfv\/XvHOwf8cuf\/SVeOHeJw8MD+u4BxcmUcrBCEJYotCZwFQ5wfHDIME74oz\/\/RxabLaLjnxH1f4QWEse\/RxCW6Q8n7Dza4Ydv\/oDhaML2tWv85tdfI\/eraAtqdfXM60WhyYsCA3S6Ea21DZTjsrK8xKtf+SJpmvHw\/n2S6YjGSgACam4V8oySK7Em57079xkNHabTIaNBm1e++ocE7giZtqnWGuR5ShwPKXTGk719jocZQW2etdYyrlLs7h8Rj8Y4S80mSik6nS7jaUJWFEileP75m6y1VsmSKSVlqSzPY3RB9LhDZ2ef8LxCa00QBrz\/wV2e7OySFYZatcIk2udfv\/VnPHf5DM1aicPDY+7t7BO4kuvXL9Pr9RmPY1zHYWF+HuW5\/Pit77O+voGq1xuvn11r0T3pUvZdrLV885u\/xbXty4giJx928aXBFRqpU+6+91PiKOLSlU0C12EwHHHSG7Ew16BWq+A4kulkxMHTe1y\/sk6t0UTYnO3tLZrNebCw2NxgfX2TpcV55hsVpICDow5h4ON4GKLjDuVKmao\/w4SPfn6XlaUFevu7FJMB0mgss75y48VPIaUEa1BKsXJmheW1DbRwyY2gFw3onHQxOmNufh7PD4AqyWSMtRZtQ4T08H2BHzYIa2U8R7B69oBRv4\/49M3nbL1axpUCIQWHnR6Fsbzw2V+l8\/QB2xc3+MyLt8gmE6bjGGthZo2g3ADpegjlIZSLlerZu9YaYwxCgJQzNClMiMYDBEI6MyIwOa5MydIBt2+\/h7h2+ZJtzteplAN6gxHGQica0B+OUcpBCIHvumxfvcjVKxe5sH6WsytNfD9kOk1JsxyhZu3FWjBm5uraGIwxz1gJJQnL8xgRkKaabDrFYlEYfHeCwPL2Oz9BXLl8yZ6Zr1MUBZ7vMUlTuv0x0XBEPBrheR6O45AkU6QQ1EsBqlThTHOR7es3OHf+Ihvra5xdXSVPJ8TDiDxLT4VZjLVYAeIZZwpcL8AJGmQ5FOMOghyL4c6du4hXv\/KqffzwHvP1GsYaxkmG47g8fLyLxOJ4HlmWYY1B6AKrFCsrZzBG0+tFJGmK74U0m0tcuLTFb\/\/e75OmKbVqmXK5xHgYMYkHGDMDOWvNJ\/w7Y187E26tpXvSxXn5C6\/Qj04YDAYIIAx9ev0YVwlWl+bRwqFz0qPIErTjAIK9dhshBLVqGd\/3sEB7v81oFGPyKR\/+\/CMEgi+\/uMHahasES+dpbZxjeWWFLJsy6kdM4uEMgU\/Z3FpLo1HHWVk9y7UbN\/jud\/6TUhjSjUZ4nkOe5wz6I4zjUQoDBnkB1lAKA3zPJctyov7wFzWCYDgacLz7iMtNlyTXHHf7HHf+m\/H0v9DakGjJpUtbbF2\/Sev8FvW5BgsLcwwHEf1el3Eco2r1+utpMqHf69Ht9RFSoAvNKB5zebNFUmiGvT7KlZRLIVmeMxjGJGn6bNL4xbKk2rK5OsdcLSRwZ\/ytpEVYS6EtURTxk3f\/l++8+RZvvPEGh4ddzl+6QnR4xMJKC1WvVl7vHHcweUq3G2EtZFlBnufYPCcslaAo6I8njKcJ2phnQv7\/htmoUymXqYcOrqMIfQcJCKnwHIdCG8apIRrGM2uw0Dnq8uSd\/2Fn\/wSnXhxxv5ujs4RKKSDJNUoqkiwjLzT9YUwOZHmOkgorLVLOUvSJiObyCivLTawumE7GxFmONRZpLRKB6zrkRiMkeBoaZWgfZyAE0vGI+gm9saDSfoqzXNKMKtAeuPhIkBKtLXP1Gvu9Pq7rnk4kArBgwXNdtrevEAYhIIh6XfaePAYxc2qAslpku1WjyAvSXGOtwFqB1gVpnjNNMubKLnP1CsP+MVpMyYsQx\/M9NhdzJtZlMNHM+R6u69GL+iipGIxGFEWBkpKLFzZYmKvjuz7tgw57k+mz2cvYWe15rkOapsSjIVJU8XwXIWA4TtAGSp5kPJ2ZZsl3KAb7eF4dbWaM\/n\/EiYnnPJLE5AAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/workspace_small.png\u0022 alt=\u0022My workspace\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022360\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s a list of tools that I use for work and can fully recommend:\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/workspace_big.png\u0022 alt=\u0022My workspace\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022720\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAKcklEQVRIiV2X24+kx1mHn6r6jn2eU8\/sbM\/M7uzu7M6udzfrGCvEmAQ5KImjKCYiXEQgDuIOxA0SF1z5jj8ACcQFCgJhARdIKEIEhyhOiOygrJ1ge7Pe03h3Z3pOPd1fH77u\/k5VxUWPNxIllVSluvm99b76vc8r\/uRP\/8IeH7cp8gm+K9mfbHCQXcaxMZ6NsCjmsu+hSHnppS\/y2heu8cmy1s4OAoQQCCGQAoQUCCGRUiKVmm0BeV7wt\/\/2N9SDJaL4hFsXbnBpc4tcF3z7B9+mFpRxHh1YfFmlteoz6E9oVie04xrahGTWxyIo1BaBvkc2forr38LamRhjzDNRQgiElAgpkFIgTwUJKXAcNQugKJirLXF\/5yFPdvdQqQs4TIopjz7+mFqlgvM7r90kSydUgoTBKCGOcxbGJaKRYDp2mKQFpFfx+k8ZjROUcjDWUhSarNAUhcZai1IKx1G4roOSCiEVQgqsNTzt7EAWcPuj27QPj+j0u7ilgLv7O3y8\/5R+3qWxUGJz4zyi\/fC2Pf1zBGAMmNOo0zSnF\/WJ4wnj8YTOSY80SRDaIIxB5wXSQn8UkynNuY011tZaLDWXcJQDwvJw\/32OTg7R05APHn3Aoyc7DMcjpKvQ+ZRatcpSs4lTMvSOT3B8f5YWEKepgO\/+xw+pTBWulDTKFZbKZTbDZSoX1vE9BVZjrUEbDQjeu\/+If37nTeq1CnPz85SThLu7tzno7tKPBnhOyGRYIK1AeJqK8JDKRShF8+wCvuciUNQrdZzBZML3v\/c2X3\/tVawAYwWLy4t8prZJGHhgDcYIpBKAnt1tgTY5UimMMbiuIs8KpklCmuWcDE4otOV4uM9wPCbu55hckmtLqVSlVPEwSUEjlOROCddx6ex1sF6KfPdnH\/KXf\/0t\/u4f\/oXxZIqQitbmGrudI7I8QwqFQSKERCgHpMAKBUJhkSAVruuRZinJZEKSpJTcOlIo1ua3cD1JrbrMOMmp1RbxXZ8kKXh++9OYksskHVOixNRMsMKi9vYOX\/c8xePHT0niIWdbZ1lePsPDOw9oLSwilTr9FYMQAm0MFrDWYNAYa4lGMT+++z6VapVKrU4Qlgn8Mtc2n+cwanN57TqHvROUI\/iNV75Eo7rIC1deYL\/zhF957tdZXlriweEdrq5fxdndO2CuXidLDR\/+9A57Rz3OtNapFQ63zm0iHQcpBIXWaE7rRoCxhqzIKYzFIpFSkRea406H\/ijGUZJBd8jN1ssszC+wdmaDc611wqDE1ijB9wQvX\/k85y5c459+9Fd87XPf4MWtz+EsNBrUqxUalRJz5QpRp8fRSY+y8vnGS79GYTVoi7ZgCkOuc5I8oTvo0un3OI4iBtMEGYY8enKMakeUSgHl0CPq9lhrLWDyhKvPfYpSWCbNMtLcMO0f4SifvDB8+dbvoqTPMM5whvGIQue4CpIixXM8MmMZpFPeffiANE9pHx9SblQIamXuPnyA6ytcz6XQBaPhEGthmmZ0h33a7Q5CumTplEajzh\/\/wddOXVthrOAkGhPHMY\/efRunVCUeJ1TnFilVHCwCp1qr0u8PKLTGdx0mScbq+Qv4QcDfv\/XvHOwf8cuf\/SVeOHeJw8MD+u4BxcmUcrBCEJYotCZwFQ5wfHDIME74oz\/\/RxabLaLjnxH1f4QWEse\/RxCW6Q8n7Dza4Ydv\/oDhaML2tWv85tdfI\/eraAtqdfXM60WhyYsCA3S6Ea21DZTjsrK8xKtf+SJpmvHw\/n2S6YjGSgACam4V8oySK7Em57079xkNHabTIaNBm1e++ocE7giZtqnWGuR5ShwPKXTGk719jocZQW2etdYyrlLs7h8Rj8Y4S80mSik6nS7jaUJWFEileP75m6y1VsmSKSVlqSzPY3RB9LhDZ2ef8LxCa00QBrz\/wV2e7OySFYZatcIk2udfv\/VnPHf5DM1aicPDY+7t7BO4kuvXL9Pr9RmPY1zHYWF+HuW5\/Pit77O+voGq1xuvn11r0T3pUvZdrLV885u\/xbXty4giJx928aXBFRqpU+6+91PiKOLSlU0C12EwHHHSG7Ew16BWq+A4kulkxMHTe1y\/sk6t0UTYnO3tLZrNebCw2NxgfX2TpcV55hsVpICDow5h4ON4GKLjDuVKmao\/w4SPfn6XlaUFevu7FJMB0mgss75y48VPIaUEa1BKsXJmheW1DbRwyY2gFw3onHQxOmNufh7PD4AqyWSMtRZtQ4T08H2BHzYIa2U8R7B69oBRv4\/49M3nbL1axpUCIQWHnR6Fsbzw2V+l8\/QB2xc3+MyLt8gmE6bjGGthZo2g3ADpegjlIZSLlerZu9YaYwxCgJQzNClMiMYDBEI6MyIwOa5MydIBt2+\/h7h2+ZJtzteplAN6gxHGQica0B+OUcpBCIHvumxfvcjVKxe5sH6WsytNfD9kOk1JsxyhZu3FWjBm5uraGIwxz1gJJQnL8xgRkKaabDrFYlEYfHeCwPL2Oz9BXLl8yZ6Zr1MUBZ7vMUlTuv0x0XBEPBrheR6O45AkU6QQ1EsBqlThTHOR7es3OHf+Ihvra5xdXSVPJ8TDiDxLT4VZjLVYAeIZZwpcL8AJGmQ5FOMOghyL4c6du4hXv\/KqffzwHvP1GsYaxkmG47g8fLyLxOJ4HlmWYY1B6AKrFCsrZzBG0+tFJGmK74U0m0tcuLTFb\/\/e75OmKbVqmXK5xHgYMYkHGDMDOWvNJ\/w7Y187E26tpXvSxXn5C6\/Qj04YDAYIIAx9ev0YVwlWl+bRwqFz0qPIErTjAIK9dhshBLVqGd\/3sEB7v81oFGPyKR\/+\/CMEgi+\/uMHahasES+dpbZxjeWWFLJsy6kdM4uEMgU\/Z3FpLo1HHWVk9y7UbN\/jud\/6TUhjSjUZ4nkOe5wz6I4zjUQoDBnkB1lAKA3zPJctyov7wFzWCYDgacLz7iMtNlyTXHHf7HHf+m\/H0v9DakGjJpUtbbF2\/Sev8FvW5BgsLcwwHEf1el3Eco2r1+utpMqHf69Ht9RFSoAvNKB5zebNFUmiGvT7KlZRLIVmeMxjGJGn6bNL4xbKk2rK5OsdcLSRwZ\/ytpEVYS6EtURTxk3f\/l++8+RZvvPEGh4ddzl+6QnR4xMJKC1WvVl7vHHcweUq3G2EtZFlBnufYPCcslaAo6I8njKcJ2phnQv7\/htmoUymXqYcOrqMIfQcJCKnwHIdCG8apIRrGM2uw0Dnq8uSd\/2Fn\/wSnXhxxv5ujs4RKKSDJNUoqkiwjLzT9YUwOZHmOkgorLVLOUvSJiObyCivLTawumE7GxFmONRZpLRKB6zrkRiMkeBoaZWgfZyAE0vGI+gm9saDSfoqzXNKMKtAeuPhIkBKtLXP1Gvu9Pq7rnk4kArBgwXNdtrevEAYhIIh6XfaePAYxc2qAslpku1WjyAvSXGOtwFqB1gVpnjNNMubKLnP1CsP+MVpMyYsQx\/M9NhdzJtZlMNHM+R6u69GL+iipGIxGFEWBkpKLFzZYmKvjuz7tgw57k+mz2cvYWe15rkOapsSjIVJU8XwXIWA4TtAGSp5kPJ2ZZsl3KAb7eF4dbWaM\/n\/EiYnnPJLE5AAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/workspace_big.png\u0022 alt=\u0022My workspace\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022720\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s a list of tools that I use for work and can fully recommend:\u003C\/p\u003E\n\u003Ch3\u003EWorkspace\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/diablochairs.com\/diablo-x-one-2-0\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Diablo X-One 2.0\u003C\/a\u003E chair\u003C\/li\u003E\n\u003Cli\u003EAn electric standing desk\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EHardware\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/macbook-pro-13\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E MacBook Pro\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/iphone\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E iPhone Xs\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/airpods\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Apple AirPods\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EOperating System\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/macos\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E MacOS\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/ios\/ios-13\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E iOS\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EEditors\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.jetbrains.com\/phpstorm\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PhpStorm\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.jetbrains.com\/pycharm\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PyCharm\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.jetbrains.com\/lp\/mono\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E JetBrains Mono\u003C\/a\u003E \u2013 a beautiful monospaced font with code ligatures\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EApps\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/brave.com\/avr418\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Brave Browser\u003C\/a\u003E (\u0026amp; Chrome as a \u003Ca href=\u0022\/blog\/log-out-for-privacy\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E sandbox\u003C\/a\u003E for anti-privacy services: Google \u0026amp; Facebook)\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.icloud.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E iCloud\u003C\/a\u003E \u2013 Contacts, Calendar\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/keepassxc.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E KeePassXC\u003C\/a\u003E \/ \u003Ca href=\u0022https:\/\/apps.apple.com\/us\/app\/keepass-touch\/id966759076\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E KeePass Touch\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/authy.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Authy\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003Esee also: \u003Ca href=\u0022\/blog\/ungoogling\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Ungoogling\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EWebdev\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/plauisble.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Plausible\u003C\/a\u003E (self-hosted)\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/regexr.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Regexr\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["uses","technology","hardware","software"],"hasMore":true,"image":"https:\/\/avris.it\/image\/workspace_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/workspace_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/workspace_mini.png\u0022 alt=\u0022My workspace\u0022 width=\u0022240\u0022 height=\u0022180\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s a list of tools that I use for work and can fully recommend:\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/workspace_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/workspace_mini.png\u0022 alt=\u0022My workspace\u0022 width=\u0022240\u0022 height=\u0022180\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHere\u0027s a list of tools that I use for work and can fully recommend:\u003C\/p\u003E\n\u003Ch3\u003EWorkspace\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/diablochairs.com\/diablo-x-one-2-0\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Diablo X-One 2.0\u003C\/a\u003E chair\u003C\/li\u003E\n\u003Cli\u003EAn electric standing desk\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EHardware\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/macbook-pro-13\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E MacBook Pro\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/iphone\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E iPhone Xs\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/airpods\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Apple AirPods\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EOperating System\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/macos\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E MacOS\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.apple.com\/ios\/ios-13\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E iOS\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EEditors\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.jetbrains.com\/phpstorm\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PhpStorm\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.jetbrains.com\/pycharm\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PyCharm\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.jetbrains.com\/lp\/mono\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E JetBrains Mono\u003C\/a\u003E \u2013 a beautiful monospaced font with code ligatures\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EApps\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/brave.com\/avr418\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Brave Browser\u003C\/a\u003E (\u0026amp; Chrome as a \u003Ca href=\u0022\/blog\/log-out-for-privacy.lite\u0022\u003E sandbox\u003C\/a\u003E for anti-privacy services: Google \u0026amp; Facebook)\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/www.icloud.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E iCloud\u003C\/a\u003E \u2013 Contacts, Calendar\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/keepassxc.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E KeePassXC\u003C\/a\u003E \/ \u003Ca href=\u0022https:\/\/apps.apple.com\/us\/app\/keepass-touch\/id966759076\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E KeePass Touch\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/authy.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Authy\u003C\/a\u003E\u003C\/li\u003E\n\u003Cli\u003Esee also: \u003Ca href=\u0022\/blog\/ungoogling.lite\u0022\u003E Ungoogling\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Ch3\u003EWebdev\u003C\/h3\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/plauisble.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Plausible\u003C\/a\u003E (self-hosted)\u003C\/li\u003E\n\u003Cli\u003E\u003Ca href=\u0022https:\/\/regexr.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Regexr\u003C\/a\u003E\u003C\/li\u003E\n\u003C\/ul\u003E","words":73,"readTime":null,"lang":"en"}}},"blog\/technology\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome":{"key":"blog\/technology\/reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome","type":"article","published":true,"meta":{"createdAt":"2020-01-10T11:53:15+01:00","publishedAt":"2020-01-10T11:53:15+01:00","group":null,"links":[{"icon":"box-alt","colour":"primary","url":"https:\/\/packagist.org\/packages\/avris\/fontawesome-optimiser","displayUrl":"avris\/fontawesome-optimiser"}],"category":"blog","subcategory":"technology","slug":"reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome"},"content":{"en":{"slug":"reducing-website-size-by-a-half-by-optimising-bootstrap-and-fontawesome","title":"Reducing website size by a half by optimising Bootstrap and FontAwesome","intro":"\u003Cp\u003EMy new blog, despite being simple and freshly rewritten, loads way too much crap...\nSo I took a few moments to optimise it a bit \u2013 and I ended up with almost 50% reduction in resources size\nin just two steps!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cp\u003EMy new blog, despite being simple and freshly rewritten, loads way too much crap...\nSo I took a few moments to optimise it a bit \u2013 and I ended up with almost 50% reduction in resources size\nin just two steps!\u003C\/p\u003E\n\u003Ch3\u003EBootstrap\u003C\/h3\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/getbootstrap.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Bootstrap\u003C\/a\u003E is awesome. But it\u2019s also a lot.\nModals? Popovers? Tooltips? Badges? Toasts? I don\u2019t use any of that!\u003C\/p\u003E\n\u003Cp\u003EI already don\u2019t include any of Bootstrap\u2019s JavaScripts, but I should definitely clean up its CSS.\u003C\/p\u003E\n\u003Cp\u003ESo instead of including\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs scss border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\u0022\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EI went to its source and copy-pasted the modules that it was loading over there,\ncommenting out the ones I don\u2019t need:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs scss border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/functions\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/variables\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/mixins\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/root\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/reboot\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/type\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/images\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/code\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/grid\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/tables\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/forms\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/buttons\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/transitions\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/dropdown\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/button-group\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/input-group\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/custom-forms\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/nav\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/navbar\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/card\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/breadcrumb\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/pagination\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/badge\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/jumbotron\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/alert\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/progress\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/media\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/list-group\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/close\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/toasts\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/modal\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/tooltip\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/popover\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/carousel\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/@import \u0022~bootstrap\/scss\/spinners\u0022;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/utilities\u0022\u003C\/span\u003E;\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E@import\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022~bootstrap\/scss\/print\u0022\u003C\/span\u003E;\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe only issue is that I do use \u003Ccode\u003Eforms.scss\u003C\/code\u003E \u003Cem\u003Ea bit\u003C\/em\u003E.\nThere is a search form in the header that has its \u003Ccode\u003E\u0026lt;input\u0026gt;\u003C\/code\u003E field styled.\u003C\/p\u003E\n\u003Cp\u003ESo I just inspected that element in Opera and pretty much just copy-pasted the three relevant selectors.\u003C\/p\u003E\n\u003Cp\u003EBum! Starting off with a minified CSS file of \u003Cstrong\u003E244 KB\u003C\/strong\u003E, now it\u2019s down to \u003Cstrong\u003E184 KB\u003C\/strong\u003E.\nA third of its weight is now gone.\u003C\/p\u003E\n\u003Cp\u003EBut that\u2019s just the first step.\u003C\/p\u003E\n\u003Ch3\u003EFontAwesome\u003C\/h3\u003E\n\u003Cp\u003EThe real big deal in terms of the website weight were the \u003Ca href=\u0022https:\/\/fontawesome.com\/icons\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E FontAwesome icons\u003C\/a\u003E.\nThere\u2019s thousands of icons included, but I only use a dozen \u2013 so why do I make visitors download them all?\u003C\/p\u003E\n\u003Cp\u003EYou can load FontAwesome in a number of different ways. One of them are \u003Ca href=\u0022https:\/\/fontawesome.com\/how-to-use\/on-the-web\/advanced\/svg-sprites\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E SVG sprites\u003C\/a\u003E.\nYou can include the definitions of the icons in a form of SVG \u003Ccode\u003E\u0026lt;symbols\u0026gt;\u003C\/code\u003Es, and whenever they\u2019re used,\njust use a \u003Ccode\u003E\u0026lt;use\u0026gt;\u003C\/code\u003E tag to reference it.\u003C\/p\u003E\n\u003Cp\u003ESo a wrote a simple service (plus a Twig extension) that would do exactly that:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Eput \u003Ccode\u003E\u0026lt;use\u0026gt;\u003C\/code\u003E tags wherever an icon should be displayed,\u003C\/li\u003E\n\u003Cli\u003Ekeep track of the icons used,\u003C\/li\u003E\n\u003Cli\u003Edump the definions of the used icons at the bottom of the page.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EI just had to add some CSS to display the SVG icons the same way as webfonts\nin terms of size, position and using the color of the surrounding text:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs css border\u0022\u003E\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.icon\u003C\/span\u003E {\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E1.1em\u003C\/span\u003E;\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Eheight\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E1.1em\u003C\/span\u003E;\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Evertical-align\u003C\/span\u003E: -.\u003Cspan class=\u0022hljs-number\u0022\u003E125em\u003C\/span\u003E;\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Efill\u003C\/span\u003E: currentColor;\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EEt voil\u00e0!\nThe homepage of my blog went down from \u003Cstrong\u003E765 KB\u003C\/strong\u003E at the beginning,\nto \u003Cstrong\u003E704 KB\u003C\/strong\u003E after the first step, to \u003Cstrong\u003E393 KB\u003C\/strong\u003E now!\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-optimised_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022800\u0022 height=\u0022200\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAJCAYAAABaMo5wAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB3UlEQVQ4ja2U227bMBBEz\/IiUqLapu7\/f2HdGEV0gcXL9kG24rQIkKKdF2KXFDU7M6CoqnKDqiIix3rvAeTrFR\/Cm\/3HFXh372\/OiKrq+XzGe0+tFRFBRGitATAMAwClFEophBDYtg2AruvIOWOMwTkHQG1KLYXWKiEGtuuGAjEEDqiCCKUqzgqX9SfBRr5++rwTmueZeZ4ppWCtJcbIuq6oKqqKMYZxTMzzjDZFb5OmYWBeFgRwzuG7jvPSMCI0bYgItTaitwA8BWG7PCPOA0o8nQ6OtTbGcURaa3qfvpQCgDHmUCWldFh3vV6JMZJzptZKjJFSCiKCtfbh8sq2bfR9T86Z1hrhQaHSFGfkqHPemKl8i+Ou0OVyYV3Xg1BKuxp368QYhr5nXVceMY4jLy8vdF1HrZUuDvyYC8YoqoIR0JtDQ2dJZMpN5fD0BdN1h4XWOVJKrwrdQ\/yvEHYSH+0fuJFyANM04b0\/rLqjtfZHb\/\/2NVsfoagoclQ7NQWaghHINeN9R+8cTkTw3jNPE7XtgYx9z7IsiEBrijWGISWmaXqjZEqJZVn2H4nQ9z3f54rIqyKlNoKziMApGrbnZzAGjDlC7a2n5oJE2TP0OPl779D\/eGMezxz6\/Vb\/AmBJWhxIiYZ2AAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-optimised_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022800\u0022 height=\u0022200\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EBtw, I\u2019ve put my little helper into \u003Ca href=\u0022https:\/\/packagist.org\/packages\/avris\/fontawesome-optimiser\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E a library\u003C\/a\u003E,\nif you want to check it out.\u003C\/p\u003E\n\u003Cp\u003EThere\u2019s caveats though...\nSVG is heavy. The two \u003Ccode\u003E.woff2\u003C\/code\u003E files I was using are \u003Cstrong\u003E261 KB\u003C\/strong\u003E overall,\nwhile the corresponding two sprites are \u003Cstrong\u003E2.1 MB\u003C\/strong\u003E.\nBut if I filter their content to just the icons I actually use (which is way simpler to do in SVG than in webfonts),\nit goes down to just \u003Cstrong\u003E44 KB\u003C\/strong\u003E!\nSo if your website is using a looot of fonts, you\u2019ll probably be better of generating a custom webfont.\u003C\/p\u003E\n\u003Cp\u003EThere can also be issues related to warm caches possibly circumventing the Optimiser,\nwith data that includes new icons being loaded dynamically in JS (which I don\u2019t do),\nwith the increased execution time (which doesn\u2019t bother me since I use an HTTP cache),\netc. Still, in many cases this trick can be very useful. Like mine.\u003C\/p\u003E\n\u003Cp\u003ESwitching from webfonts to dynamically filtered SVG sprites\nnot only removed the need for two requests \u003Ccode\u003E.woff2\u003C\/code\u003E files,\nbut also the need for the CSS that maps class names to font glyphs.\nMy CSS file went down again, from \u003Cstrong\u003E184 KB\u003C\/strong\u003E to just \u003Cstrong\u003E96 KB\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Ch3\u003ESumming up\u003C\/h3\u003E\n\u003Cp\u003ESo here I am: having spent not even a full evening on it, doing optimisations as simple as they can get,\nand ending up with the website trimmed of \u003Cstrong\u003Ehalf\u003C\/strong\u003E of its fat.\u003C\/p\u003E\n\u003Cp\u003ENice \ud83d\ude0e\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["website","web development","javascript","scss","css","bootstrap","fontawesome","svg","optimisation"],"hasMore":true,"image":null,"introLite":"\u003Cp\u003EMy new blog, despite being simple and freshly rewritten, loads way too much crap...\nSo I took a few moments to optimise it a bit \u2013 and I ended up with almost 50% reduction in resources size\nin just two steps!\u003C\/p\u003E","contentLite":"\u003Cp\u003EMy new blog, despite being simple and freshly rewritten, loads way too much crap...\nSo I took a few moments to optimise it a bit \u2013 and I ended up with almost 50% reduction in resources size\nin just two steps!\u003C\/p\u003E\n\u003Ch3\u003EBootstrap\u003C\/h3\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/getbootstrap.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Bootstrap\u003C\/a\u003E is awesome. But it\u2019s also a lot.\nModals? Popovers? Tooltips? Badges? Toasts? I don\u2019t use any of that!\u003C\/p\u003E\n\u003Cp\u003EI already don\u2019t include any of Bootstrap\u2019s JavaScripts, but I should definitely clean up its CSS.\u003C\/p\u003E\n\u003Cp\u003ESo instead of including\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-scss\u0022\u003E@import \u0022~bootstrap\u0022\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EI went to its source and copy-pasted the modules that it was loading over there,\ncommenting out the ones I don\u2019t need:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-scss\u0022\u003E@import \u0022~bootstrap\/scss\/functions\u0022;\n@import \u0022~bootstrap\/scss\/variables\u0022;\n@import \u0022~bootstrap\/scss\/mixins\u0022;\n@import \u0022~bootstrap\/scss\/root\u0022;\n@import \u0022~bootstrap\/scss\/reboot\u0022;\n@import \u0022~bootstrap\/scss\/type\u0022;\n\/\/@import \u0022~bootstrap\/scss\/images\u0022;\n@import \u0022~bootstrap\/scss\/code\u0022;\n@import \u0022~bootstrap\/scss\/grid\u0022;\n@import \u0022~bootstrap\/scss\/tables\u0022;\n\/\/@import \u0022~bootstrap\/scss\/forms\u0022;\n@import \u0022~bootstrap\/scss\/buttons\u0022;\n\/\/@import \u0022~bootstrap\/scss\/transitions\u0022;\n\/\/@import \u0022~bootstrap\/scss\/dropdown\u0022;\n@import \u0022~bootstrap\/scss\/button-group\u0022;\n@import \u0022~bootstrap\/scss\/input-group\u0022;\n\/\/@import \u0022~bootstrap\/scss\/custom-forms\u0022;\n\/\/@import \u0022~bootstrap\/scss\/nav\u0022;\n\/\/@import \u0022~bootstrap\/scss\/navbar\u0022;\n@import \u0022~bootstrap\/scss\/card\u0022;\n\/\/@import \u0022~bootstrap\/scss\/breadcrumb\u0022;\n\/\/@import \u0022~bootstrap\/scss\/pagination\u0022;\n\/\/@import \u0022~bootstrap\/scss\/badge\u0022;\n\/\/@import \u0022~bootstrap\/scss\/jumbotron\u0022;\n@import \u0022~bootstrap\/scss\/alert\u0022;\n\/\/@import \u0022~bootstrap\/scss\/progress\u0022;\n\/\/@import \u0022~bootstrap\/scss\/media\u0022;\n\/\/@import \u0022~bootstrap\/scss\/list-group\u0022;\n\/\/@import \u0022~bootstrap\/scss\/close\u0022;\n\/\/@import \u0022~bootstrap\/scss\/toasts\u0022;\n\/\/@import \u0022~bootstrap\/scss\/modal\u0022;\n\/\/@import \u0022~bootstrap\/scss\/tooltip\u0022;\n\/\/@import \u0022~bootstrap\/scss\/popover\u0022;\n\/\/@import \u0022~bootstrap\/scss\/carousel\u0022;\n\/\/@import \u0022~bootstrap\/scss\/spinners\u0022;\n@import \u0022~bootstrap\/scss\/utilities\u0022;\n@import \u0022~bootstrap\/scss\/print\u0022;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe only issue is that I do use \u003Ccode\u003Eforms.scss\u003C\/code\u003E \u003Cem\u003Ea bit\u003C\/em\u003E.\nThere is a search form in the header that has its \u003Ccode\u003E\u0026lt;input\u0026gt;\u003C\/code\u003E field styled.\u003C\/p\u003E\n\u003Cp\u003ESo I just inspected that element in Opera and pretty much just copy-pasted the three relevant selectors.\u003C\/p\u003E\n\u003Cp\u003EBum! Starting off with a minified CSS file of \u003Cstrong\u003E244 KB\u003C\/strong\u003E, now it\u2019s down to \u003Cstrong\u003E184 KB\u003C\/strong\u003E.\nA third of its weight is now gone.\u003C\/p\u003E\n\u003Cp\u003EBut that\u2019s just the first step.\u003C\/p\u003E\n\u003Ch3\u003EFontAwesome\u003C\/h3\u003E\n\u003Cp\u003EThe real big deal in terms of the website weight were the \u003Ca href=\u0022https:\/\/fontawesome.com\/icons\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E FontAwesome icons\u003C\/a\u003E.\nThere\u2019s thousands of icons included, but I only use a dozen \u2013 so why do I make visitors download them all?\u003C\/p\u003E\n\u003Cp\u003EYou can load FontAwesome in a number of different ways. One of them are \u003Ca href=\u0022https:\/\/fontawesome.com\/how-to-use\/on-the-web\/advanced\/svg-sprites\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E SVG sprites\u003C\/a\u003E.\nYou can include the definitions of the icons in a form of SVG \u003Ccode\u003E\u0026lt;symbols\u0026gt;\u003C\/code\u003Es, and whenever they\u2019re used,\njust use a \u003Ccode\u003E\u0026lt;use\u0026gt;\u003C\/code\u003E tag to reference it.\u003C\/p\u003E\n\u003Cp\u003ESo a wrote a simple service (plus a Twig extension) that would do exactly that:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Eput \u003Ccode\u003E\u0026lt;use\u0026gt;\u003C\/code\u003E tags wherever an icon should be displayed,\u003C\/li\u003E\n\u003Cli\u003Ekeep track of the icons used,\u003C\/li\u003E\n\u003Cli\u003Edump the definions of the used icons at the bottom of the page.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EI just had to add some CSS to display the SVG icons the same way as webfonts\nin terms of size, position and using the color of the surrounding text:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-css\u0022\u003E.icon {\n    width: 1.1em;\n    height: 1.1em;\n    vertical-align: -.125em;\n    fill: currentColor;\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EEt voil\u00e0!\nThe homepage of my blog went down from \u003Cstrong\u003E765 KB\u003C\/strong\u003E at the beginning,\nto \u003Cstrong\u003E704 KB\u003C\/strong\u003E after the first step, to \u003Cstrong\u003E393 KB\u003C\/strong\u003E now!\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-optimised_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-optimised_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002260\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EBtw, I\u2019ve put my little helper into \u003Ca href=\u0022https:\/\/packagist.org\/packages\/avris\/fontawesome-optimiser\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E a library\u003C\/a\u003E,\nif you want to check it out.\u003C\/p\u003E\n\u003Cp\u003EThere\u2019s caveats though...\nSVG is heavy. The two \u003Ccode\u003E.woff2\u003C\/code\u003E files I was using are \u003Cstrong\u003E261 KB\u003C\/strong\u003E overall,\nwhile the corresponding two sprites are \u003Cstrong\u003E2.1 MB\u003C\/strong\u003E.\nBut if I filter their content to just the icons I actually use (which is way simpler to do in SVG than in webfonts),\nit goes down to just \u003Cstrong\u003E44 KB\u003C\/strong\u003E!\nSo if your website is using a looot of fonts, you\u2019ll probably be better of generating a custom webfont.\u003C\/p\u003E\n\u003Cp\u003EThere can also be issues related to warm caches possibly circumventing the Optimiser,\nwith data that includes new icons being loaded dynamically in JS (which I don\u2019t do),\nwith the increased execution time (which doesn\u2019t bother me since I use an HTTP cache),\netc. Still, in many cases this trick can be very useful. Like mine.\u003C\/p\u003E\n\u003Cp\u003ESwitching from webfonts to dynamically filtered SVG sprites\nnot only removed the need for two requests \u003Ccode\u003E.woff2\u003C\/code\u003E files,\nbut also the need for the CSS that maps class names to font glyphs.\nMy CSS file went down again, from \u003Cstrong\u003E184 KB\u003C\/strong\u003E to just \u003Cstrong\u003E96 KB\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Ch3\u003ESumming up\u003C\/h3\u003E\n\u003Cp\u003ESo here I am: having spent not even a full evening on it, doing optimisations as simple as they can get,\nand ending up with the website trimmed of \u003Cstrong\u003Ehalf\u003C\/strong\u003E of its fat.\u003C\/p\u003E\n\u003Cp\u003ENice \ud83d\ude0e\u003C\/p\u003E","words":752,"readTime":4,"lang":"en"}}},"blog\/technology\/new-year-new-digital-me":{"key":"blog\/technology\/new-year-new-digital-me","type":"article","published":true,"meta":{"createdAt":"2019-12-31T11:22:05+01:00","publishedAt":"2019-12-31T11:22:05+01:00","group":"redesign","category":"blog","subcategory":"technology","slug":"new-year-new-digital-me"},"content":{"en":{"slug":"new-year-new-digital-me","title":"New year \u2013 new (digital) me","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4_small.png\u0022 alt=\u0022Screenshot of the new version of the blog\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022234.07874015748\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADFklEQVRIiaWWz24cRRDGf9XTf2aXJSvHYCLlgEDiyCkQiRtXrhw4IfEaSBx4AA55hQiJIxIvwM0kAiQgcoQcEsmAZGJsrx2CPd6dnunisJ71zu7au0BJo\/7UXfVNTdVXvSu33nlXRUAVAGZxlhlEDAAxVgt9GoyMl+AcYgyqabIpIqgqMUZSE6Dnx1PxVuSCuLEG3377FiLCzs6vpKQcDgZzPrPYWkvIA945rHWE4HHO4pwnBE+WZTjrCN7hg8d7T\/DjNc9z5ONPPlXnHN57fLg4DC0cJoEhzOxN\/ALeO7IsQ0QufZpqTa\/TJiklndtdwfb3D8hDhjCiSjlVVeODZzQckeeBfr+Pnremadcq+F8lVMbI3tM9nHPEKqIITs4oa09KiTzkxBhRFJtZjDFsbLyMtXblDxVV\/U8VAkgpTVqhqgtbsKqpKqqKbYiavFSVlNLEYfppzqfXacL\/YyKCMQZbFEWLzBjTEqExZhKwTJRlWTIYHOH9eOyvr61N\/FbW0LKWNdW5qhvNPVXXNSenp+O4pIgRyjJyWnte7HVZfyFbWilzVSIXuAaUqiq589kdPr\/7BVUsAaWuUyvGiCCMK21EcJml37VYja12X4bNIq1cppPtBz+wu3WfJ99+zeDwoJXItBZbHChnwxLnw9LqANhlk9HSVyrpWUGrClMWk\/1pjmKkdLyQZYaTYU0sayrJKIaRrvdz\/rP40pYtsnRSIJpwGjk5Opw7FxHWruXk+fgWv36tg+t26PdyrHOtj2xL4qIjdrYt08pv7NHWPeKzP\/hrlBgmJZ4VxKOHbG0e8Mprb7Jx8\/UpclBN5z+4Sj8Y6lgRCQvvqtl3zV2hi4bu9+\/uUR7\/yYPdZ\/S6yvrNde5+uUmv2+HDj16C84RUlbIcTSpgTEZVFtS+T27m+RfhlTS0F2u+2nzM91s73Fjr8NYbN9jefc6j3QHvvf8Br55zjBMBRDAy\/l9hvcebEomKBH\/lu4DxlF2QzWOAnx4\/5f6P2wg1x0XJN7\/sc3xW0nHCz7\/tt6cMRWguUeHvYaIoCorh85XG\/h9McAJLnmVpFQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris4_small.png\u0022 alt=\u0022Screenshot of the new version of the blog\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022234.07874015748\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt wasn\u2019t really supposed for the New Year, but I\u2019ve had plenty of free time on my hands\nduring the holiday break, so here it is already: a brand new version of my blog \ud83e\udd73\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4_big.png\u0022 alt=\u0022Screenshot of the new version of the blog\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022468.15748031496\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADFklEQVRIiaWWz24cRRDGf9XTf2aXJSvHYCLlgEDiyCkQiRtXrhw4IfEaSBx4AA55hQiJIxIvwM0kAiQgcoQcEsmAZGJsrx2CPd6dnunisJ71zu7au0BJo\/7UXfVNTdVXvSu33nlXRUAVAGZxlhlEDAAxVgt9GoyMl+AcYgyqabIpIqgqMUZSE6Dnx1PxVuSCuLEG3377FiLCzs6vpKQcDgZzPrPYWkvIA945rHWE4HHO4pwnBE+WZTjrCN7hg8d7T\/DjNc9z5ONPPlXnHN57fLg4DC0cJoEhzOxN\/ALeO7IsQ0QufZpqTa\/TJiklndtdwfb3D8hDhjCiSjlVVeODZzQckeeBfr+Pnremadcq+F8lVMbI3tM9nHPEKqIITs4oa09KiTzkxBhRFJtZjDFsbLyMtXblDxVV\/U8VAkgpTVqhqgtbsKqpKqqKbYiavFSVlNLEYfppzqfXacL\/YyKCMQZbFEWLzBjTEqExZhKwTJRlWTIYHOH9eOyvr61N\/FbW0LKWNdW5qhvNPVXXNSenp+O4pIgRyjJyWnte7HVZfyFbWilzVSIXuAaUqiq589kdPr\/7BVUsAaWuUyvGiCCMK21EcJml37VYja12X4bNIq1cppPtBz+wu3WfJ99+zeDwoJXItBZbHChnwxLnw9LqANhlk9HSVyrpWUGrClMWk\/1pjmKkdLyQZYaTYU0sayrJKIaRrvdz\/rP40pYtsnRSIJpwGjk5Opw7FxHWruXk+fgWv36tg+t26PdyrHOtj2xL4qIjdrYt08pv7NHWPeKzP\/hrlBgmJZ4VxKOHbG0e8Mprb7Jx8\/UpclBN5z+4Sj8Y6lgRCQvvqtl3zV2hi4bu9+\/uUR7\/yYPdZ\/S6yvrNde5+uUmv2+HDj16C84RUlbIcTSpgTEZVFtS+T27m+RfhlTS0F2u+2nzM91s73Fjr8NYbN9jefc6j3QHvvf8Br55zjBMBRDAy\/l9hvcebEomKBH\/lu4DxlF2QzWOAnx4\/5f6P2wg1x0XJN7\/sc3xW0nHCz7\/tt6cMRWguUeHvYaIoCorh85XG\/h9McAJLnmVpFQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris4_big.png\u0022 alt=\u0022Screenshot of the new version of the blog\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022468.15748031496\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt wasn\u2019t really supposed for the New Year, but I\u2019ve had plenty of free time on my hands\nduring the holiday break, so here it is already: a brand new version of my blog \ud83e\udd73\u003C\/p\u003E\n\u003Ch3\u003EWhy?\u003C\/h3\u003E\n\u003Cp\u003EWhere to start? I got increasingly annoyed by the old version.\nThe design started seeming boring and blunt.\nThe code started growing unstable.\nIt was using the \u003Ca href=\u0022\/projects\/micrus-v4\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus framework\u003C\/a\u003E,\nwhich I \u003Ca href=\u0022\/blog\/how-and-why-i-ve-built-and-killed-a-php-framework\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E stopped supporting\u003C\/a\u003E a year ago.\nIt was using \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Micrus-Assetic\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus Assetic\u003C\/a\u003E\n\u2013 an outdated method of asset management,\nwhich highly depended on the server configuration and binaries installed.\nThe deployments were \u201ciffy\u201d, to say the least.\nI was afraid of sending even small changes to the server, for fear something might blow up again.\nSome small things I didn\u2019t even notice were wrong: like still warning about Google Analytics tracking,\neven though I migrated to \u003Ca href=\u0022https:\/\/matomo.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Matomo\u003C\/a\u003E ages ago.\u003C\/p\u003E\n\u003Ch3\u003EWhat changed?\u003C\/h3\u003E\n\u003Cp\u003EI decided to keep it simple. To go with a \u201cless is more\u201d approach.\nI\u2019ve removed soooo many features that just weren\u2019t useful enough.\u003C\/p\u003E\n\u003Cp\u003EI used to have an admin panel: except I didn\u2019t need any fancy editor,\nthe main content was written in an (enhanced) \u003Ca href=\u0022https:\/\/www.markdownguide.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Markdown\u003C\/a\u003E anyway.\nSo for this version, I\u2019ve decided for a filesystem-based approach: I\u2019ve ditched the database completely,\nI don\u2019t need any ORM, I don\u2019t need an admin panel. I just have a bunch of \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/SUML\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E SUML\u003C\/a\u003E files\ntracked by GIT. Using \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Esse\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Esse CMS\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EI used to have three language versions of the UI \u2013 but why?\nI don\u2019t think anyone really cared about not seeing the names of the categories in Polish,\nwhen most of recent my posts were in English anyway.\nSo now the posts are still available in the language(s) they were written in,\nbut I\u2019m no longer maintaining the multiple versions of the UI, or the features to filter content by language.\nWhat a relief!\u003C\/p\u003E\n\u003Cp\u003EI used to have a \u201crandom post\u201d box. I used to have tag clouds. I used to have an embedded Twitter timeline.\nI used to have the latest posts on the \u201cabout me\u201d page (really?). I used to have a link shortening feature\n(\u201davris.it\/l\/\u0026lt;whatever\u0026gt;\u201d) that I\u2019ve never used, not a single time.\nI used to have a separate controller and database fields to support redirects for legacy URLs from the even earlier version.\nI used to have database fixtures. I used to have a console command to export legacy comments to \u003Ca href=\u0022https:\/\/disqus.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Disqus\u003C\/a\u003E.\nI used to have tooltips and popovers.\nAll gone now! \ud83d\ude0d\u003C\/p\u003E\n\u003Cp\u003EI replaced the infinite scroll with... just loading the whole page at once \ud83e\udd37\u200d\nIt\u2019s not that big for today\u2019s standards anyway \u2013 the heaviest list of posts is 113 KB of compressed HTML.\nInstead, I now lazy load images using the \u003Ccode\u003EIntersectionObserver\u003C\/code\u003E API.\nWay simpler than infinite scroll or pagination \u2013 which aren\u2019t really necessary with this amount of data.\u003C\/p\u003E\n\u003Cp\u003EOh, and the website is now using a fast an sleek \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony\u003C\/a\u003E setup with an HTTP cache \ud83e\udd70\u003C\/p\u003E\n\u003Cp\u003EDesign-wise, I use the default \u003Ca href=\u0022https:\/\/getbootstrap.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Bootstrap\u003C\/a\u003E theme,\nwith only minor changes of variables and minimal additional styling.\nThe main feature, obviously, are the tilted elements. That\u2019s enough to add some personality to the website,\nwithout making it overcomplicated.\nCompared to the previous version, it\u2019s way more contrasting, better tailored for wider screens and clearer.\u003C\/p\u003E\n\u003Cp\u003EOverall, 41090 (!) lines of code were removed:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-3-4-diff_big.png\u0022 alt=\u0022424 files changed, 6711 insertions (+), 47801 deletions (-)\u0022 class=\u0022border\u0022 width=\u0022550\u0022 height=\u002289\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAFCAYAAAAt8E4LAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABbUlEQVQokZ2RTY4TQQyFP7uqKwlh0skIISSExBHYchPEATgVaxaciQVigRAw+emku6q6K2UWCYPYDBJePVnPz7I\/ef3slT1\/+YLcnzBtsDJSypmbdcv3r9+YzWesNi2xjwz9QN91pJgB4+GS\/\/L438I5hzaeVEZEhGpGe7tBqRy2B1SVWg1V+RNm18wHF\/6r\/vZ4EGqZMDPCLHDqjghwPBxRjNX6BhMh9pH93Y4nT28J8wXd\/siqXWIohsH5jGsaSimMKSMinKvRrleE4Nn+3LF4vKSWQhMCOV88ghHjyHm6kPFv3r2l3bTUanx8\/4G+O+GcEofEYrkg55FHyzkpjXin5JQQ58EqoopvLkc0zuGcAp7iJkIIDENizBnMQARBqNWotQKgqqgqItP9t\/yXT58RFXyYcTx0dPsDZoYIpBgB4w6wK6JpGu\/Zb3\/sQEAwEtB1ghiYGLGPmBlTzleyRhoGDLlOX5TZtSOAGL8AA7fCc1N6DsoAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-3-4-diff_big.png\u0022 alt=\u0022424 files changed, 6711 insertions (+), 47801 deletions (-)\u0022 class=\u0022border\u0022 width=\u0022550\u0022 height=\u002289\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThere\u2019s nothing else in the (programming) world I love more than removing useless code!\u003C\/p\u003E\n\u003Cp\u003EDeployments are now stable, simple, reproducible and revertible, thanks to\n\u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/webpack.js.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Webpack\u003C\/a\u003E,\nlack of database (no db = no migrations),\nand most importantly my recent child: \u003Ca href=\u0022\/projects\/avris-deployer\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Avris Deployer\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-deployer_big.png\u0022 alt=\u0022Console output of deployment\u0022 class=\u0022border\u0022 width=\u0022848\u0022 height=\u0022237\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAKCAYAAADcpvzeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB1klEQVQ4ja2TMXPUMBCFvyfJdw6JyUDLpKOloOf\/\/w9mAqkokkDu7LP0KNZOLpmbpAAVlvbN0+767ZO+fflsgG4QhzujBK6F\/a8Luov3uE3U8UDfiYvznjbPgLi5\/olbA8T\/XPp6dWUJ1Jt6l0l9Q9tGe0jQhDZG2bgRcTFuggo2tD8JED5Am9JTYsBvFT\/BKZ4S6hv1NpPeNTwJbYSryGeGYtpDQimutjFFliVOvVFp1F2iG2bwUsSE2g2wAjRoYzyDSsSe9Yh5FsUN2iQ8iZaFxwSKZPU+BbnC\/Lvgw9OviVAIgouhGqQjfJmmX8FfrpL6aF1DDeKmQjbeJdSZep\/wlB6llXwk9nFncY7iEdtGKwcj6VE9a4kXjgXCJM+Qtku5tEiYQ1oyKJs8VMpQF\/uuJhZaax19n8UL4SUnsNOc4lm0fYIGrjG+NmaUQJ1Rt8y+b6RZeI7xvmpY\/4Op1S1QMVSFWsl4TNTbDDlwxnXwoG2LZNNrT1680fZJTgFI2xaj6mO3IQ+VdN5QZw43Ja6XMPj6ek6Z8mm91cxpTvnYf+KwHxk+XLJ\/2LEfd5wN53Ql8+P7dTxZwDZb9UzjiI9NvZh15YS3FlNj5GU\/4qzmjtvPOX8BswgOy6gNMP4AAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris4-deployer_big.png\u0022 alt=\u0022Console output of deployment\u0022 class=\u0022border\u0022 width=\u0022848\u0022 height=\u0022237\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EVersion 1 (\u201dSilva Idearum\u201d)\u003C\/h3\u003E\n\u003Cp\u003ESo, to finish this post, let me just quickly show you the four versions I\u2019ve been through so far:\u003C\/p\u003E\n\u003Cp\u003EMy first blog was called \u201cSilva Idearum\u201d (Latin for \u201cForest of ideas\u201d).\nIt was anonymous, spirituality-oriented, Polish-speaking, Joomla-running and with a \u201ctoo much\u201d design.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris1-post_big.png\u0022 alt=\u0022Screenshot of the post page in version 1\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGJUlEQVRIiS2UO49kZxGGn6rvdk736Z6+THt21pfF69sagYUsIECIhAjxL5BICIiQSEj4AyT8AmIiiEgXgQRItgAhC3vB9trMzM7Ozuz09O2cPt+FYLaSkkqvKqnnKfntL94uH58rg8mCz06\/yvok4k1h0AsLvmButxzdW3B4UOMOLMtux\/V6SW+Fq5j4bLOiDApfvz9jVNWYYnHF4kV4\/p8nKHtSdNjgmR7NSD5wcn1FbwzWWUosbG5a+rMnzCeLP9hHV4bZ6xOwR4yvN4zqPSmCN5F5UN585x7TqcebPV3j0Ww4S2fssDx8fMqTYpn3M\/78xy\/55Y++zzDMCOWIkjbE6hFSOtqLFcE4SjXAjGbMAxwMeh4cj3i+CqyWW\/J0zTx32LsP7jGZLoi9MkxbWhcZhinLizWz114nv3zElQ0Ym3FW8P2a98YLOHiF33zwa0LcIvWQeVjx17895N6rb+HNOSVH7h2\/RUlbar\/ExEgYvcR+d4M4gx8M6UOg7QY0s5cIuwva6y+xd195wG67IZcObYYIzwiaGNrAQTTsB4fYwYBQO3wVsKagqtgq8Kuf\/pzPv\/gUlxJvvPMyk4MRRg2npyfEPtGMDlAZIeMZOe4RqdCqQWPDrn3OZX+HVhJ+GJDhAp9W2O0msu96sjqaxUuM2sBhGPOstITNjnmj9NM5zXiM9w5VJZ99gvQbHsxG3K\/fwFWBv4vnal94LRjuD6fknHHZ0G5ajBRkdki2DTrosWkKN4Hd3pCMZ31zQx4echAcNkWDCyPscI7aEfZORTWsubM\/wZoJ86MxebHAhwYVQUTRyTcpWGK+hbeQ+bYqlELJGX0FcopYa2jUUdc1z59+QteuwVZIqqgpdJstlydnbDEU3bHwE6xBMDqAEnDWoIcv0w7HVPWI5maJEbDe4JxirENEEPEg4LktEUMpCTUBck+KHdlEVAXRQru5RNQhpsI5g0k91lasnn2MNY63H7zLo0cf8rTbYW0xEA1pF0kFqmmgV0+ZvYUZr6jiBicGNSBqoPTk0rO6WSMCIpBTRo2iLiBaiCnSOAMUIKNGKDlS8h41FSKC8TXNZErpr5Cy53ix4Pz0c+yiarjedCA99aTC1iNULNYUejth78Z4tXRtAjaIAESC91g\/wBpFbocgt2eDctsFKIJaj+hznHOU0kFZEsKUWf1f\/MKSVp8xn46ZTO9jTTVi3CvPrzqa+yPw1YvlmVDVZCJ9KpScUDUgDqGQU6HsVkQKooailpvLc549PWc2n7DbtjRNw9PHn7Ludrz3rW9DycS4J8anVBKZ3xlgdsLy4gLvGtquxYbaENOIsAewWBswKmQMJHDekzO07R4o5FzwzoMYJAREQVXo+45HH\/6Jf3\/wF8Jkwj8+PueH3\/saD3\/\/O4Z37\/L+d74LuaeoY992RHuCHnjCZol51uCzwWmDbUum626DOfZovyIJmDCh9IloE5VTmqa55SVnhAxiKCUjovT7Fms9fbfhfAOr88d88NEZunnCbHbM9OgQeWEjoohVri8umZgRuhuS1h2pGPZhjd13heRHCBGjYIwi6lABDYILFWgg5oxKIaf4gpmCtZa+7yg5UxB20TCcHfPuN95nefOQeLHk83+dQAkIGTUWRGhGr7KJheVKafwRaXzG5fUl5WyLPaoMZ9s9W23Q0QIzGCEFVBU1FuuHWDVQCsYqwgChEGNGVagHAyADhni9ptlfc\/lFZHB6SXA13DvAHhySzz8ipRYd3cG6Q+qmZfnsKdglySZyUxGGAVsVy2vn\/+Offo6++RWcH76wJWKMR42j37fc3KyBggDeO3JOGDWkXFAVVA0\/+PFPbuE3BvOzFhtb8voU2W+R5RkKZPGUcYPzd3B+w\/X1GjdsyO0TZDDCeh\/guuP+fIujoMYiqlDAqGKN4OsKZz0FEFEgUXKhlIJznhg7VC0xRiRHpF0S+x0xC+wVkRHN4BK1hl1vsH5IFRyD9oqzx2ckZ9l2icPjI6yaAcbXHBvYdlsiHU4NKSdEFZFISYbdboMYf2tgTrcvBqHv15RcEN0jYjBqiAxRGyj9mqI1g7omhxa9OWUwuUvrK0K6IXrP6NW7ZFdDUmLX8X\/09s8geltpKwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris1-post_big.png\u0022 alt=\u0022Screenshot of the post page in version 1\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EVersion 2\u003C\/h3\u003E\n\u003Cp\u003EAfter coming out and becoming independent from my parents,\nI was finally able to put my name on my posts. New domain and a redesign was also in place.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris2-home_big.png\u0022 alt=\u0022Screenshot of the homepage in version 2\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEQklEQVRIiZWWO2xcRRSGv3nd1+56d+21DY6xnYctIkAIRxGCCAGK6Hg1FFSICgloEAiJBikUFCkCDQUNLVJ6RKjpKJEQUhwLYYKVxHYSdm3f3bk7MxR3d+MkDlmmOpq5959zzv+f\/16xuroaqrUaIgQ6u7t8deEClWoVYyKiyJDnOQDGGJxzHD9xAiUlhy2lFMaYQ8\/GXJe0tZZOu02kBNZaGs0G9XoD7z2tVuuuC7z3dO0ecZSxc\/MGWhuKwqKkwjnPRK2OEBKtNZubm6ysrPzvjHS73WZxaoKF6QY\/\/7ZNllVozUwjEQghCCEghEBKydbNv\/nsm9d485W3WL\/6O9f+uk3e73D5yp\/YQvP5+19zcvE08\/PzLC8vjy4ZYowT6zPPnGR+QhFHGp1UiSODUZper0cABOC8J00SBIpqd4rrv3Y4Ov0Up559nnZ7h4n+T1z9Y41+J2CMptNu07UWrTVKStI0JYqi8To0u3CEONVIZWjEt9jZ2WF3bx9rLVmWkec5cZKQ7+8T6YhHry2RTR\/n1vU6353\/GELOS2fPcpNjFD1D+5823W6POI7Z292lUqkQxzEhhLs69qBYr6+vcWR+njipUTiNMYYkTZmamgKgXq+X1DUatG\/cYLMvqedbSK84c\/oNxETO3NIM3\/\/wLWdefhFtDEIKiqJPCIGiKJBSjk\/ZnkpY21gnMRUiAvn+HkJqCtvD2hKsKCxRFCMkzC1M0r29TdZMmHriSfTeL0w3Fec+eYflpx9Ha4W1Bc45jDFYa+n3++NTNp0ErDAECppxgzhOmJxsAiClJISADx6tNFprPv3iy3sgXh1FSik2NzeZm5tDaw1QVq31+JTVqkdRyR6ul2OdwBaO7e1tpJR474miaORBSkoQAu\/94DwAgRACUsqS3riGcw7vPVBaRbVaRQ6866GULZ1YZmvrOtb2SLUmTROiOB6MPGitEEKglCJ4TxCQRAnGGJSShHCnyiiKyFyOlALv79iFc26U0MOWWF1dDQc3Ll68yPTsDLE2MPCh0cNAGFA5rGy4vPcIIdjY2KBSqZSUC0Gj2RxbP8AlfS+wlJJKmrF2+TJiVFVASjWYGAGIUdXDylutFrVaDSkyarXagEZBYYvSj5QaKyP9oAMfAniP0XqkhyzLRiItEymtM4RAFMUANCdTNtavQAg0WjMkSUKlWhnhPlRDBykBcM7R7XZZWlq6L8mDAIcBOudoNpuc\/+hDlo\/MsfTcCxxZPE5zanKs7hzaoU6ngxCgtSHLspE2hokPrWC4N5wwhCBNEkIITCweI9QibrfbRDvbrPDfo34wvk9Dttej14vpdnvs75efkNJHPEKUehGD0VdK4ZwbdWl29hGq1Sqvv\/sB17Z2qJGzsPDY6J3DunofZYdRAZCm6ej\/RimFNqYc+wDeO6A0QiEE\/X5\/oKsS49yP62w7jcs7vH2qynszM2NT9i\/Q3AYk6KDr5QAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris2-home_big.png\u0022 alt=\u0022Screenshot of the homepage in version 2\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EVersion 3\u003C\/h3\u003E\n\u003Cp\u003EAs announced in \u003Ca href=\u0022\/blog\/brand-new-blog\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Brand new blog\u003C\/a\u003E\u2026\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris3-home_big.png\u0022 alt=\u0022Screenshot of the homepage in version 3\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221603.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAkCAYAAABmMXGeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFE0lEQVRIia2Wy48cVxXGf+feenRVd0+P7Ywn47ESk4kTiEE8LEACsUECCQHZIRZs2CL+EZD4A9iyjmADUjYIgSJhQmyEIjBCKLKxsScT2zPdPT1Vdd8seqY1j3Y0SHybUl3V+e79zvnOqSt\/uPXnJEqBCKIUSmlaY8mLnKKsECVY4xCBhAAgMWBcoq5ylAgheJJ3xOAhRmT46udTMbpIUqCUJqsHqKIk74\/Iqj55URG9IwGZaBKgQ4QErmuwzmAOptj9Xdxsim8aMm8thfegFSEkwkGDdgGScOOlDWwUHh8U6GpEqTLq1FBoxdNH92mmewRriaYhNDOSDxAiKkWhmU7o9me4zqFUge6tcOO11\/jx975DayM2CNZYunaGFsHZjpgE0zZY0xF8IgaIzhFDQIorbySV5UiezyX3R+i8ABKfePllDlxkajwAKYR57qwlmJZoGnzXEJ0jeEM0Hcl2yDu33jsslELpjHklZF44USAgIoBASiQSpAQxklIixTB\/T4mUIqSEWGsTh0gpISKMx2OUUvT7fZRSADRNQwiBuq7RWh+FICKLuCOoI7LjKMsS7z2TyYQQAj\/76Y\/Ii4KpLdFZASLcfXCw2PA40vNPus9k\/ARFxmBlSDObsHH1JRKCEogxYnyilyuUUidO+lzSGOMJOUeYNJGVfk6KgZ2xY+NCMW+K88h3zuG9X3woInRdR6kszrQIifWRnhdmifzsKOg4fvm7P\/H+Bw8ZDGpsSGTlgO9++VO88sIQ0Zper7cgWIZs2eJf\/vEBv7\/9PvVwxJNpy3C4ws2tdTYv5uiQY42hqmtCCGeIRWS5\/GgNdZbTI3F11MPOxiTnSQeWzphDD5\/N+Qn5p+GN4fHjbRBFVVfM2pboLVlviODpug5IZFm+lHxpTp0x+K7BeU8vS2hvicFTDWu0koU\/T1f9Y3MavUNFj+86ullGWRSYtiN4RxRhMBgsSJdhKen33\/wmNz\/zOvPGn6994cbrdI1hY\/NFnm0\/ZOWFFxfGP42l5j+O4w3RHjSMLqwy29uhHFxckJ6OE2ttOlo8\/TxOehR8GsvadGmhmqbBWkuWZdR1jek66n6fe9v77E92WS0dXSzw2So3ro3Ol1M1GRP2JlRbW4QYefTMMNxP1FnFxitXmZnEWi+nypdFH5KezoleW6d34TIojVbwk7dm8M+\/8uFkk7d+8Vl8SEwPLMUoJzuvT4N3eGPIej3QBV+\/HpleGvF0\/AwRUAIJEJZ31VL5P\/\/NA+78a4x1kW\/cXOPbXxpQ1jfp5TmZVlwc5ljnIUUOB90CIrJcfq+5y9qzv3Otang1fZHB8FsE59FKePu3j7i7k4j+31zpwQ9\/8LUTpM+tfnvvNtu33+ajAtavXUZI9PsVdVVy7+EOt+48ZnfvXb56\/QpwkhSeY\/73bt\/h3v0HiGje+OQW6+uXsS4xGFQ4B+N9S1koRoOS4bBe\/js5bfq2bTFdh840\/f6A8XiKKCjzHKUVs\/0ZohSrq6torc9nfqXmIy8laI3n1+8+oSo1Lio2LxX856MZCWFrM\/KVT6+dT\/4f\/\/aE7d0O7yNbV\/p87volYoKqzGhaQ0QhApmCTKv\/vffj4U1EKYWIYIwhBI9SOb1eceIwHyv\/xK4iJ0bcfuvZHTdUVY+BS1wYlmdiz14xODt8rYv86p1HWBfZmwWezuD+TsuHu92y8JM5\/X9B0hynLNUQk8ZH0EoQSaR09AREKDMhy7IztQD4L+DGHxjr8QA8AAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris3-home_big.png\u0022 alt=\u0022Screenshot of the homepage in version 3\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221603.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris3-posts_big.png\u0022 alt=\u0022Screenshot of the list of posts in version 3\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADMElEQVRIib2WzW4cRRSFv1vV1T09f5AZx5EiJAiKWCDxIzZIkYxX7PCCBQs\/BO\/AM\/gV2PEEXrJha4UNwgpKVg6yzHg89sz0X1VdFh0bO1EyvaI2t\/vWUZ1T957WbYkxKhvW2dkZxhim0+kbe+fn54xGI4qixBjBOUdRFDjn8CGQuozZZcWDSY5zbhPVodR1vVHQ\/7gOE9XNek5mJQj0pGJ5tWCQ91gvL0mc4+EHH76BV1VCCAA0PhC852wtPNruv5NHRJCqqjYqqr3iIzhr6KUGAO89Ozs7nJyc3MHu7+9zdHTE8fHxnfze3h4HBwebqA6TTQgAX5c0vsFkGfPSMBmmiAinp6f8\/fLlHexiseCrjx\/z6P4nvDc2JLPf+fnXp8zn8y5UJCLyToCqkqYO5xJ6ec7YtBWirnkyGNO8P+VFYshDZOgjH7mM33qP+Wt7zmS6Yvb0CV989y02PGcTF0AnD5VlyeXlJaPRiMFgQJZlAGzvfsPsnxlfDvsISihLHnz+GT\/ee4F7\/gdJYbnYNfz5cAddf08Xrk4eqqqKEAJZlmFeVSjGSFk1BBVcYqgb2LrXx3vPxapmWSrjfkKIyrifYiV2EXTYqWViU3xUxll6k2+aBmugXC1Ra0mc4+oqkOc5qXimfUG1wpiUzBm8j91athEB+LoA76mqAS5CMsgREYL3eO9pmgYtCvr9Pnmeo6osLhaIEVSVusiYTCZdqLp5yDlH0zSEEIgilMslaZpiE9tG28brdgIYa1BVrDUoEFXZXJ+OX5mIMBwO7+RDCMQQKcsCaxPW6zXOJSRuiqq2LbUW7yMxKqgitwS\/VVAH0dgkJSI4KyS2PbSua9raCjFGjAjD4QgjgjEGY8yNZ4y1ncRAx5bF0KCqqDhiCIh7dQ9jSbMcRBABxdAWIyIIIq2HNEZQpcvQ7FSh69mUZdmdm\/70yzMu1p7pKOWq8BR1YPfTKT98vUXUiKgQNZKYTjQAbJz2twdlkrQHt97wRIWo\/3mwl7b5uq6p65per9e205guvx7wtll2beTX3733ADexbbdgrMFJ65lr3HK5ZLVaEVVJrGFr6\/7N\/usct5\/\/BSOPoERFJpF9AAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris3-posts_big.png\u0022 alt=\u0022Screenshot of the list of posts in version 3\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris3-post_big.png\u0022 alt=\u0022Screenshot of the top of the post page in version 3\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACrElEQVRIib2VTW7cRhBGX1V3s0nOUGNLTrIIggTeBYJhJSfwVQzoBr6FDpO1LxB4lUXuIMABpAiSrJnhX3d5IWlkw3ZIB0E+gADRLLJedX2slpyzMaGzszNUlYODg0+eXVxc0DQN222LqhBCYLvdEkJgTIkiRP6+7vhuvyKEMJXqtfR9Pwn0P+q1N5vm+evtWxChiJFmuZxT6b+SiODnBPoQcM6hqqzXa0SElBJFUdC27S2gGUMSDOXJ\/vKLCf9JZjYP6PDwkMvLyzmhHB8fc3JyQtu2mBl1veCPN7\/x8y8veLL\/\/eT7fg7112pz0zGMLWUsyTlTL35C\/WpyhwBmeehrZWJsc2bpHNkyz49+xcVyVnGzWnZfmbu7DDBVyIZgGJAAUUVEMBv4drVCnaMsy1tIs3k7NKdlT0MklzV7zlOpIgJ\/eqEaRp6iDNm4TCPv0shKlNXqEaqKquJDQICc8zygyQjgWb3EkiFApY7TsSfuNXRdy6M+sRChy5kuZX6MJaYFF9uEU3DdSB0dpZ+GgZkeerO+YnN9hRMhmTEWBU04IBQFv5+e4oeBDJjBD92WMRvdkInBURZCWTjIaZ6H5rTs5atXtG27W0t3CUWgKtxH8UdHR6gIhVdU4Go9MCZjVSlOp3dp1tFxfn7OOI6ICKq6q1REdt64H5Z1vaCoFqw7Y9snCicY8E3j0WmgeUeHmaHOoSKYGTFGvH+w3z1QzgnnPGZGPyaiV\/ox87gpUJ0302aZOqWEc+4WTJW265CuRZ2\/NQ6gqvR9T13XlHVkr1YEIQwj19fvKB8v\/pvf\/j5ZSpnlcgFAJUL+oG1mRlVVO+jNZkOMEYBYCk1Z74qZBPrc4odDzMxY1DXGg2fuUBB5mC+bzYamaQC4ubmh6zq8D7hYgUEd3Sff\/dz9e6J1Rd1KBbTbAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris3-post_big.png\u0022 alt=\u0022Screenshot of the top of the post page in version 3\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris3-post-end_big.png\u0022 alt=\u0022Screenshot of the bottom of the post page in version 3\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACD0lEQVRIia2VTW7bMBBG3wxJmaptpE4CFGgO0C56id46y+56ha56gaABEieWLIkzXeTPRZuatTsrShp8fPpmhhQzc\/bE1dUVqsrZ2dlv366vr1kul3Rdj6qQUqLrOlJKTKXQpBk\/bre8O21JKe3b6lKGYdgLtF6vCaqYP6S6OyKCu6Oq5JwREVR1n9ReoOi+l4ebmxsEMHdCCLg77k5QZSrl+R1A27asVquDaESEWJMYYwAEsYJqADfMQVSIO06JCCqHu+TudUA5t5gZzWxGk9IvJRORZzGAEKskX434JPi36PseM2MYBkopAKgq0zjyZj4nPUKaGTlnYtseDlTTQ22bEdHnTZ+ad9cpMyfGiJlRo\/kqUE1SKUaMSlvx58dOWlXJuq5jsVgwjuOjK9A0s5pz5d+BapJ6z+gotDExmqPANEB\/39M2gaCCilDcWeQjm7qm3jO2tCkxn0VUX6Zq0UYE2DX5mP6BypLN354TgjIWYxqcnAJNOvpU\/jNQTdLl12\/ENCPEwMnJyV9zL04zHy+WhwPVWPzlu7PZ3j8+3bKaJxAQhHU3MpYXjc+fzvnwfnEwkGy32+OK\/n\/jMtaM7t3dHapK0zTc9kZOAXi4XIsZQYVhclJ4mLSkSj8WFvllCGpDn5paRHhtrapIaOgnyCmgPoI7UzHERqxMqBheBnCnTFuiOv04sdls9urvrn8CnvD1+u2+X7sAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris3-post-end_big.png\u0022 alt=\u0022Screenshot of the bottom of the post page in version 3\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EVersion 4 (current)\u003C\/h3\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-home_big.png\u0022 alt=\u0022Screenshot of the homepage in version 4\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221666\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAYAAACJ8xqgAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEA0lEQVRIiY2Wz4scRRTHP1VdP3pmd2fdDSIkm7\/CeDC5aPAvEEHwIngSD168ePLi3T9CEFFEzFmQEBFFNqd48WwiyLgTd3p3pqu6uspDd+9sT3eyeXTxul\/xXr336lvfLnHr9huJS3Lz6IhlUbBcFqQUL08hhEQrhRCCBMRYE2NCa43RGmMN6t133sYYg7UGay2zvT2Ai+9mGKyxl2ytNhatFVJKhBDNiDH2MuzEOcf5asV6tSRGSGSkFNmf7TOdTjDGjLkhUkqDgCml0dHNPU+Uc258pa4EIdqSYD4\/wVpLnluUUmRZNvCTmz41wxiDUhn\/zv\/hwf2fkbILLJnN9jBG41zg6XnsLXqx+FhZAH8e\/8IfP90DNrYQamKMhDpis\/G2yLFyV2cLVmcF5X8nlMv5BXxi5ygg1OO9lNspA\/z2w5c8evgrk92MLz7\/DHd2CoDRikwpJloyndjRktXYKt88eMSP94955XCPxVnJh58GJkBZOqQUhDqiQkFuZgPf0YCHL1\/nrbt3yCc5mczoOpPntnXSSDFa8RDYY40OIeCc43RZ4JxrQe\/QSl58O+dx3iM++viTVLZG7zwpJVbrNWXp8JWnqirqOnIFnjcl\/378sGeYTqdYY1gWS25cv8GTv59gbVOqc47Dg0MWTxfcPDrir8ePx3rYb8ZqtW7xKFgWS0BQ1x3rCNblGhCcLBYIIQdHcQDslBJ5npNSajYkpQtIpJQ4ODggpUSMkRjjiwG7qioAsqyZViojb8v2zgMQY0TKobu4dfvNF2z3RrTWGKMx2mCMxlqDaflSfPX1t6khWNsj1bx9v0y+1liM0Ugpe6QKbPQ2H87nC8pyRWZ2uHY4I3sGgAESCa36Z0Nt71Ke1xi7jwDqUMEI53XSbVQvYJdqJ4Vz5FJRx0imRk\/mJsMWAc\/NcL+SrHRNSs1OXiVXZrhEotLV\/4423CDDAZAOMoWQkkxK6rq+IuBwxwZsMy8cJnlijL0TorVGaz0IYHS\/zwPYrFxAxEBq\/yVCCLTaBEokmqfRUoqLY+i9R333\/T3Ky5zWvXvft3mP77T3OOfxvsJXjQ4hNAm8+nr\/bvPS\/j46y1icnlLXAaU0QkCsGoekJLJOkJoatrs8AFpVlgghmWYRpSQxZQgBfmIb3BnI1hVG1\/g6UrhBwC0+9J61EIBAAImq7WVoV2zUeQlKaXZ2+iShPnj\/va2b1dYty2zZWrIw1pKNkcT2LhdFgQ9w7WCP5ToxmwhKn0BArgU+JIwSnJeJnXyIwwGwpzu7ZGYXgHXDpfgaQtv9zuZCc5PopGNsUZZlqqoK5xzl82DjPM432rffpe\/DzXuPeO3O3V7V0zxHZBJoACuAqsVYJyGEZ571\/wHlDJySzIsFTgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris4-home_big.png\u0022 alt=\u0022Screenshot of the homepage in version 4\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221666\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-posts_big.png\u0022 alt=\u0022Screenshot of the list of posts in version 4\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADcklEQVRIiaWWz08kVRDHP+9n\/5gZdkFEgrBZ4wE18Wb8EcOiiRf\/BC\/GswlXjx688U9w5GSMx71hPJLswURijAc3JBrWhGGEZqaZ6ffKQ08PAzuQgJV06tv1rVevurpedav3PvpEBFAKRLgUBQhYa1BKATCqqtosNT8TA2nqiVHQWiMxAmCspaoqqqoixtpxek+lIITwk22CNcZpefLkY3q9HkdH\/xBi4Pi4+5LfNNYarHWkSYq1Bu893nuctSRpgrUWZy3OObz3JGPeJzUGtP3s081Lh8RfOiaexCeXtvF9s7i2JVO+tU1rjVJqopurTn62bqQoClRs6ndP6fcHFOcFxhheWViYbCIid8ZFUfxs\/08yABhLkj+gioLUkSeU3BED2Otlu6u0Uj\/T3mwUY0REJrqxX8cAIYTKlmVJHJ+E2zK\/jzT9M91P07jxaSTP86F1zl0hph365ZBuH6JAogJpcUK6tADjgH+dgtPgZUjOENduTda+KBRW1\/gigNUwn0UybzHG3PgQ9lZSQ8cMsNaSZRk8XJ5wu7u7bG9vz1y3s7PD\/sEhTgtp\/4R8cX7CbWxssLxcx5nV4PYmosFleYFSFxhj6qTG9m63y8HBwcyE9vf32dra4uFchyjC6Vkx4fb29iYJzSzC9caaxiLCoBwAijzPKc7PaeU5AKnSrDpPRxt6RuFDxETh3xhZWVrmmy++opetsTg34tHFb\/y4\/wtPnz2\/ca8G33rKtPWsrj0mSn2atYYqQhRhwVreSVvkRvN7p4UfjXh9UFJUgZFpsztcw6xn5B1D8ewt1tff5+3e98DLA\/FKhW5kgKqqCGFIiNAfgTOQWhDgzQ8\/4PPvvgVgUynGQwilFKuP4OvHP7By1KX994jDNzJ+Xdnkj3e\/vBJ\/VqvcOqkH5ZAXBXgdmQ\/n6Ln2ZfW04s\/nhxhjEIloXetOu8ODTouzkxOiqHFlK7TVmKxF5nPSNL0poae3Vsho8KNjFIpRK4eLISKRLM8BIUkSjNaEEHDO0Wq18N6hreVsOEJE0KrmkzSh7TXOufv3ENqy9NrKlV8MqHuIOCTPMgRhrjM3eV3OOUIItNtttNKIRASwxuL91Zl352NfVRUhDgkBiiF4C5mrGzz3htOzM4wxDAYlEiPaaF5dXMRaS1mWKBQxBrSxiBd8MvszMy3\/AclyutTtBlE0AAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris4-posts_big.png\u0022 alt=\u0022Screenshot of the list of posts in version 4\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-post_big.png\u0022 alt=\u0022Screenshot of the top of the post page in version 4\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACVUlEQVRIib2Wz04bMRDGf+P1er2ABKrUC2ovPXLupapEi1SpT0DfgqfgoXqteu1DVOqhQfwvCoRge6aHJGSBQKIU9ZMsfzv+Zjy2x7srb999NANEwIwpBDDwvkJEAEg5j8w2Gp\/JgRgDqoZzDlMFoPKenDM5Z1RHwu6cIlBK+eYnwSbGLra333N+fs7BwSFFCycnpw90Xe4ceF8Tm4j3FSEEQgjU3tPEBu89tffUdU0IgWY8HpoRB5z\/tPNhKmjCVNgEmtBMbePnifPI1nS0I5tzDhG57SdtlPzsfoJ+v4\/oZP+WxOHREVqUto3EOGoAZnY74aK83+9\/98skMRgmcDUAzeoGognNiZwzV1dXOBG8QdXGWx\/rFOhjHMDf37ZFsBLDlIcAhAeap3YCQFUxszutlKK+lDJzsOv81IqWwaSuunXmnGNtbe3ap5QeFU3s+\/v79Hq9bsgHN3IePu7s8GV3d77QFsDW1pYB\/9T29vbMzExVb+PO4F\/dOKlugjP5\/4KfVyfPmdQicy11y5bFInO55wp0R3\/Pt3tJ5p2EX+RIvAhRHI1AFEcUoRZH5YSkymkM2E3i5ThUUuXajKEZGUgC1YKLWuhN\/cYHYtPSVhWtq6hFECA4x680ZLDaUkJic1hYdx7FuFFlqMpFyQxU2RD3fDX0OkbadoW28lyXzIsQGKoSXcUPTayvb6Cq\/Pzd43NcxczIalyWzCvXcpZu2AwNIjL3u+YfG+jyZMafUtAxv8iZG1MuS+EkZ8LxGSLClcFxSmxUFQNVFOiXQjbjevxfNA9\/AVXov5JBOanJAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris4-post_big.png\u0022 alt=\u0022Screenshot of the top of the post page in version 4\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-post-end_big.png\u0022 alt=\u0022Screenshot of the bottom of the post page in version 4\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACx0lEQVRIiZ2Wy44cNRSGv2Mfu6qnJ5NZgMSKp2CDkAJIvBALFrwZy4gFQnkMFihCBLVGM9NdrrIPC1dXVV8nyS+V\/Nv++9x8a\/nm2x\/MABEwY4YABqoeEQGgH4Y6bHX+LAfaNlKK4ZzDSgHAqzIMA8MwUEoVLn2KQM75re6N7QeXePPmOzabDe\/f\/0MumQ8f\/jvRLblzgqrSNi2qSoyBGCNBlaZtUFWCKiHU8SbG2ja1VdVBf\/rx+ypojgUNzchTSoQQaJuG2ERUlVW7IgQlhkC7amnbFvUe7z3OecQJVgoiDucdr+\/upkoftwsMUvb1u4KHhwdKKYgIZrUSIJgVEMHMcAsntlh7o67lzc0NMUbMbArkDP9NXwoGYLfrKFawYtXFIjPvHEPOeO9ZtSuKGewdyVglIIQwBXoQ8BHXM2U7watXt+ScAZliKcWIMeC9n4zGGA+MX6nERa57Y8elXvZDCDjncM6RcwEBRQhB60kadaWUgyqc+5aaY5iZ0+fn54uCl5DzcNBfbtZj7r2f+KVVeXp6anW9Xl90mFLCjyfnU\/E5S2Zm6DXRcyr8u3nkqy\/vEXGkDI2Hbmz7Ak7AOxgyIIY6IQ2gHroBVlpPWp8heLgJ1xO5euy3A6QM6xeMfAq8my\/iYzw+Pv5+9ZR5mYMZCvz9AHdtzfyLdZ3fz6mbf\/fXBm4bKFbH79t5LpdaqUu4eg+5Razq4Ov7U81mV9+jbNCqcRtl1I2PHIdcZObHWwWYj\/05nDy4Z7DMfnZ+ym3kQr0e9thzMyPnXAM6vkHP3RulFFJKdCmRutp2XTeNdV0ipW5sa79L3aRNk2buz19PSoldt0N\/\/uXXyfB+IvU9KfX1zuh7tjmTS67ZjBU3myt4uA3H\/y0GeUziY5HzgP7x57uLghgCIYbJqXee1Pd47\/De0fcDpRRUFRFhu91+tPNzEJHyP7\/y5So+jfmBAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris4-post-end_big.png\u0022 alt=\u0022Screenshot of the bottom of the post page in version 4\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022464.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["programming","php","javascript","webpack","symfony","symfony encore","doctrine","orm","cms","esse","columnist","version","new year","blog","design","redesign"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris4_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris4_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4_mini.png\u0022 alt=\u0022Screenshot of the new version of the blog\u0022 width=\u0022240\u0022 height=\u0022117.03937007874\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt wasn\u2019t really supposed for the New Year, but I\u2019ve had plenty of free time on my hands\nduring the holiday break, so here it is already: a brand new version of my blog \ud83e\udd73\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris4_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4_mini.png\u0022 alt=\u0022Screenshot of the new version of the blog\u0022 width=\u0022240\u0022 height=\u0022117.03937007874\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt wasn\u2019t really supposed for the New Year, but I\u2019ve had plenty of free time on my hands\nduring the holiday break, so here it is already: a brand new version of my blog \ud83e\udd73\u003C\/p\u003E\n\u003Ch3\u003EWhy?\u003C\/h3\u003E\n\u003Cp\u003EWhere to start? I got increasingly annoyed by the old version.\nThe design started seeming boring and blunt.\nThe code started growing unstable.\nIt was using the \u003Ca href=\u0022\/projects\/micrus-v4.lite\u0022\u003E Micrus framework\u003C\/a\u003E,\nwhich I \u003Ca href=\u0022\/blog\/how-and-why-i-ve-built-and-killed-a-php-framework.lite\u0022\u003E stopped supporting\u003C\/a\u003E a year ago.\nIt was using \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Micrus-Assetic\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Micrus Assetic\u003C\/a\u003E\n\u2013 an outdated method of asset management,\nwhich highly depended on the server configuration and binaries installed.\nThe deployments were \u201ciffy\u201d, to say the least.\nI was afraid of sending even small changes to the server, for fear something might blow up again.\nSome small things I didn\u2019t even notice were wrong: like still warning about Google Analytics tracking,\neven though I migrated to \u003Ca href=\u0022https:\/\/matomo.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Matomo\u003C\/a\u003E ages ago.\u003C\/p\u003E\n\u003Ch3\u003EWhat changed?\u003C\/h3\u003E\n\u003Cp\u003EI decided to keep it simple. To go with a \u201cless is more\u201d approach.\nI\u2019ve removed soooo many features that just weren\u2019t useful enough.\u003C\/p\u003E\n\u003Cp\u003EI used to have an admin panel: except I didn\u2019t need any fancy editor,\nthe main content was written in an (enhanced) \u003Ca href=\u0022https:\/\/www.markdownguide.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Markdown\u003C\/a\u003E anyway.\nSo for this version, I\u2019ve decided for a filesystem-based approach: I\u2019ve ditched the database completely,\nI don\u2019t need any ORM, I don\u2019t need an admin panel. I just have a bunch of \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/SUML\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E SUML\u003C\/a\u003E files\ntracked by GIT. Using \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Esse\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Esse CMS\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EI used to have three language versions of the UI \u2013 but why?\nI don\u2019t think anyone really cared about not seeing the names of the categories in Polish,\nwhen most of recent my posts were in English anyway.\nSo now the posts are still available in the language(s) they were written in,\nbut I\u2019m no longer maintaining the multiple versions of the UI, or the features to filter content by language.\nWhat a relief!\u003C\/p\u003E\n\u003Cp\u003EI used to have a \u201crandom post\u201d box. I used to have tag clouds. I used to have an embedded Twitter timeline.\nI used to have the latest posts on the \u201cabout me\u201d page (really?). I used to have a link shortening feature\n(\u201davris.it\/l\/\u0026lt;whatever\u0026gt;\u201d) that I\u2019ve never used, not a single time.\nI used to have a separate controller and database fields to support redirects for legacy URLs from the even earlier version.\nI used to have database fixtures. I used to have a console command to export legacy comments to \u003Ca href=\u0022https:\/\/disqus.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Disqus\u003C\/a\u003E.\nI used to have tooltips and popovers.\nAll gone now! \ud83d\ude0d\u003C\/p\u003E\n\u003Cp\u003EI replaced the infinite scroll with... just loading the whole page at once \ud83e\udd37\u200d\nIt\u2019s not that big for today\u2019s standards anyway \u2013 the heaviest list of posts is 113 KB of compressed HTML.\nInstead, I now lazy load images using the \u003Ccode\u003EIntersectionObserver\u003C\/code\u003E API.\nWay simpler than infinite scroll or pagination \u2013 which aren\u2019t really necessary with this amount of data.\u003C\/p\u003E\n\u003Cp\u003EOh, and the website is now using a fast an sleek \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony\u003C\/a\u003E setup with an HTTP cache \ud83e\udd70\u003C\/p\u003E\n\u003Cp\u003EDesign-wise, I use the default \u003Ca href=\u0022https:\/\/getbootstrap.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Bootstrap\u003C\/a\u003E theme,\nwith only minor changes of variables and minimal additional styling.\nThe main feature, obviously, are the tilted elements. That\u2019s enough to add some personality to the website,\nwithout making it overcomplicated.\nCompared to the previous version, it\u2019s way more contrasting, better tailored for wider screens and clearer.\u003C\/p\u003E\n\u003Cp\u003EOverall, 41090 (!) lines of code were removed:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-3-4-diff_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-3-4-diff_mini.png\u0022 alt=\u0022424 files changed, 6711 insertions (+), 47801 deletions (-)\u0022 width=\u0022240\u0022 height=\u002238.836363636364\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThere\u2019s nothing else in the (programming) world I love more than removing useless code!\u003C\/p\u003E\n\u003Cp\u003EDeployments are now stable, simple, reproducible and revertible, thanks to\n\u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/webpack.js.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Webpack\u003C\/a\u003E,\nlack of database (no db = no migrations),\nand most importantly my recent child: \u003Ca href=\u0022\/projects\/avris-deployer.lite\u0022\u003E Avris Deployer\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris4-deployer_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-deployer_mini.png\u0022 alt=\u0022Console output of deployment\u0022 width=\u0022240\u0022 height=\u002267.075471698113\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EVersion 1 (\u201dSilva Idearum\u201d)\u003C\/h3\u003E\n\u003Cp\u003ESo, to finish this post, let me just quickly show you the four versions I\u2019ve been through so far:\u003C\/p\u003E\n\u003Cp\u003EMy first blog was called \u201cSilva Idearum\u201d (Latin for \u201cForest of ideas\u201d).\nIt was anonymous, spirituality-oriented, Polish-speaking, Joomla-running and with a \u201ctoo much\u201d design.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris1-post_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris1-post_mini.png\u0022 alt=\u0022Screenshot of the post page in version 1\u0022 width=\u0022240\u0022 height=\u0022116.125\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EVersion 2\u003C\/h3\u003E\n\u003Cp\u003EAfter coming out and becoming independent from my parents,\nI was finally able to put my name on my posts. New domain and a redesign was also in place.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris2-home_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris2-home_mini.png\u0022 alt=\u0022Screenshot of the homepage in version 2\u0022 width=\u0022240\u0022 height=\u0022116.125\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EVersion 3\u003C\/h3\u003E\n\u003Cp\u003EAs announced in \u003Ca href=\u0022\/blog\/brand-new-blog.lite\u0022\u003E Brand new blog\u003C\/a\u003E\u2026\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris3-home_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris3-home_mini.png\u0022 alt=\u0022Screenshot of the homepage in version 3\u0022 width=\u0022240\u0022 height=\u0022400.875\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris3-posts_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris3-posts_mini.png\u0022 alt=\u0022Screenshot of the list of posts in version 3\u0022 width=\u0022240\u0022 height=\u0022116.125\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris3-post_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris3-post_mini.png\u0022 alt=\u0022Screenshot of the top of the post page in version 3\u0022 width=\u0022240\u0022 height=\u0022116.125\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris3-post-end_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris3-post-end_mini.png\u0022 alt=\u0022Screenshot of the bottom of the post page in version 3\u0022 width=\u0022240\u0022 height=\u0022116.125\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003EVersion 4 (current)\u003C\/h3\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris4-home_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-home_mini.png\u0022 alt=\u0022Screenshot of the homepage in version 4\u0022 width=\u0022240\u0022 height=\u0022416.5\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris4-posts_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-posts_mini.png\u0022 alt=\u0022Screenshot of the list of posts in version 4\u0022 width=\u0022240\u0022 height=\u0022116.125\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris4-post_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-post_mini.png\u0022 alt=\u0022Screenshot of the top of the post page in version 4\u0022 width=\u0022240\u0022 height=\u0022116.125\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris4-post-end_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris4-post-end_mini.png\u0022 alt=\u0022Screenshot of the bottom of the post page in version 4\u0022 width=\u0022240\u0022 height=\u0022116.125\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E","words":694,"readTime":3,"lang":"en"}}},"blog\/technology\/cleaning-up-outdated-subdomains":{"key":"blog\/technology\/cleaning-up-outdated-subdomains","type":"article","published":true,"meta":{"createdAt":"2019-08-28T14:40:42+02:00","publishedAt":"2019-08-28T18:39:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"cleaning-up-outdated-subdomains"},"content":{"en":{"slug":"cleaning-up-outdated-subdomains","title":"Cleaning up outdated subdomains","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/askara-redirect_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022184.02266288952\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAANCAYAAADBo8xmAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABb0lEQVQ4jc2UTU8bMRCGn7E9m0AI0A\/1V8CF8v8R50rlzK23HqoiEbJBu2vP9BASbZKlqqKA+lw8tuzxOx+23P\/46eC4g6pSL2qqqiJIAGA0HgNQSmY2m3E0PqK\/P6liJTOmYzKZUMxIMXF8coyZ8ev3Iw+zOTEmqqoiqa79mTn6Ml8hbdu6quLuywWRvez+COxtSy7F+Y8QX4X6Qu46bm5uCSly\/fWKu2\/f+fD5nFiNyE2L46gmLi4u30aQme1kqJ7P0dGISpVFvcDciDHSNg2IEEJgOp0uHfTKdwjS9oK7kc0oz8+0TUvTNKSUyF1HCJHTs9ODi+izW7KceXqaE1OkdB2mE4yAsGw8c4hByOYY8OUkkOJOXK8272usm3pbkLu\/WfRDiMjGCx0sWV0vcDfMQAQESEkppQDLLJWcCcD5p48bwez77NcCtzM0xNDB\/j90CEErOwxd8jdhQ3sOWeK1oL7T9+6jDUH\/kpX35A+PhxaIl\/hdhgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/askara-redirect_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022184.02266288952\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFor quite a while my VPS was misconfigured \u2013 any HTTP requests it got but couldn\u2019t assign to a vhost, it redirected to the main website, \u003Ca href=\u0022https:\/\/avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E avris.it\u003C\/a\u003E. I didn\u2019t think it would be a big deal, until I recently found out that my post \u003Ca href=\u0022\/blog\/ungoogling\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Ungoogling\u003C\/a\u003E is indexed by Google under \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022\u003Ehttps:\/\/askara.avris.it\/blog\/ungoogling\u003C\/a\u003E\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EThis subdomain hadn\u2019t existed for a long time already, my server doesn\u2019t serve a certificate for it anymore, but it requires \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/HTTP_Strict_Transport_Security\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E HSTS\u003C\/a\u003E, so browsers end up showing users a scary error message.\u003C\/p\u003E\n\u003Cp\u003EI had to do something about it.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/askara-redirect_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022368.04532577904\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAANCAYAAADBo8xmAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABb0lEQVQ4jc2UTU8bMRCGn7E9m0AI0A\/1V8CF8v8R50rlzK23HqoiEbJBu2vP9BASbZKlqqKA+lw8tuzxOx+23P\/46eC4g6pSL2qqqiJIAGA0HgNQSmY2m3E0PqK\/P6liJTOmYzKZUMxIMXF8coyZ8ev3Iw+zOTEmqqoiqa79mTn6Ml8hbdu6quLuywWRvez+COxtSy7F+Y8QX4X6Qu46bm5uCSly\/fWKu2\/f+fD5nFiNyE2L46gmLi4u30aQme1kqJ7P0dGISpVFvcDciDHSNg2IEEJgOp0uHfTKdwjS9oK7kc0oz8+0TUvTNKSUyF1HCJHTs9ODi+izW7KceXqaE1OkdB2mE4yAsGw8c4hByOYY8OUkkOJOXK8272usm3pbkLu\/WfRDiMjGCx0sWV0vcDfMQAQESEkppQDLLJWcCcD5p48bwez77NcCtzM0xNDB\/j90CEErOwxd8jdhQ3sOWeK1oL7T9+6jDUH\/kpX35A+PhxaIl\/hdhgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/askara-redirect_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022368.04532577904\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFor quite a while my VPS was misconfigured \u2013 any HTTP requests it got but couldn\u2019t assign to a vhost, it redirected to the main website, \u003Ca href=\u0022https:\/\/avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E avris.it\u003C\/a\u003E. I didn\u2019t think it would be a big deal, until I recently found out that my post \u003Ca href=\u0022\/blog\/ungoogling\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Ungoogling\u003C\/a\u003E is indexed by Google under \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022\u003Ehttps:\/\/askara.avris.it\/blog\/ungoogling\u003C\/a\u003E\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EThis subdomain hadn\u2019t existed for a long time already, my server doesn\u2019t serve a certificate for it anymore, but it requires \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/HTTP_Strict_Transport_Security\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E HSTS\u003C\/a\u003E, so browsers end up showing users a scary error message.\u003C\/p\u003E\n\u003Cp\u003EI had to do something about it.\u003C\/p\u003E\n\u003Ch3\u003ECertificate\u003C\/h3\u003E\n\u003Cp\u003EFirst of all, users have to see \u003Cem\u003Eanything\u003C\/em\u003E other than a security warning. I need a wildcard certificate.\u003C\/p\u003E\n\u003Cp\u003EFortunately, Let\u2019s Encrypt offers them now, and it\u2019s totally free. I just followed \u003Ca href=\u0022https:\/\/medium.com\/@saurabh6790\/generate-wildcard-ssl-certificate-using-lets-encrypt-certbot-273e432794d7\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E an instruction\u003C\/a\u003E to obtain one, and then configured Apache to serve the \u003Ccode\u003E\/www\/default\u003C\/code\u003E directory with the \u003Ccode\u003E*.avris.it\u003C\/code\u003E certificate for all requests that don\u2019t fit to any vhost.\u003C\/p\u003E\n\u003Ch3\u003ERedirect for users\u003C\/h3\u003E\n\u003Cp\u003EOnce the users can see the website, I can show them things. Ideally, just a 404 with an information that it\u2019s not a valid domain, and a suggestion where they might have wanted to go (same request string, but with the base domain). Easy.\u003C\/p\u003E\n\u003Cp\u003EBtw, I used \u003Ca href=\u0022https:\/\/watercss.netlify.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Water.css\u003C\/a\u003E, a ridiculously simple CSS framework \u2013 I just added two lines, no classes, and the page already looks way better!\u003C\/p\u003E\n\u003Ch3\u003ERedirect for bots\u003C\/h3\u003E\n\u003Cp\u003EBut that doesn\u2019t solve the root cause: bots are confused about which domains they should be using. They don\u2019t care whether my certificate is working or not, they don\u2019t understand the message I left there for the users.\u003C\/p\u003E\n\u003Cp\u003EThey need a proper \u003Ccode\u003EHTTP 301 -- Moved permanently\u003C\/code\u003E. So I had to add a simple recognition whether I\u2019m serving a bot or a user, and adjust the response for each of them.\u003C\/p\u003E\n\u003Ch3\u003ESource\u003C\/h3\u003E\n\u003Cp\u003ESo, here\u2019s what I ended up with:\u003C\/p\u003E\n\u003Ch4\u003E.htaccess\u003C\/h4\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs border\u0022\u003EDirectoryIndex index.php\n\n\u0026lt;IfModule mod_rewrite.c\u0026gt;\n    RewriteEngine On\n\n    RewriteCond %{REQUEST_URI}::$1 ^(\/.+)\/(.*)::\\2$\n    RewriteRule ^(.*) - [E=BASE:%1]\n\n    RewriteCond %{ENV:REDIRECT_STATUS} ^$\n    RewriteRule ^index\\.php(\/(.*)|$) %{ENV:BASE}\/$2 [R=301,L]\n\n    RewriteCond %{REQUEST_FILENAME} -f\n    RewriteRule .? - [L]\n\n    RewriteRule .? %{ENV:BASE}\/index.php [L]\n\u0026lt;\/IfModule\u0026gt;\n\n\u0026lt;IfModule !mod_rewrite.c\u0026gt;\n    \u0026lt;IfModule mod_alias.c\u0026gt;\n        RedirectMatch 302 ^\/$ \/index.php\/\n    \u0026lt;\/IfModule\u0026gt;\n\u0026lt;\/IfModule\u0026gt;\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch4\u003Eindex.php\u003C\/h4\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\n\u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EisBrowser\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($ua)\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003Ebool\u003C\/span\u003E\n\u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!$ua) {\n                \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n        }\n        $isProbablyBot = (bool) preg_match(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027#bot|crawler|baiduspider|80legs|ia_archiver|voyager|curl|wget|yahoo! slurp|mediapartners-google|facebookexternalhit|twitterbot|whatsapp|php|python#i\u0027\u003C\/span\u003E, mb_strtolower($ua));\n        $isProbablyBrowser = (bool) preg_match(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027#mozilla|msie|gecko|firefox|edge|opera|safari|netscape|konqueror|android#i\u0027\u003C\/span\u003E, mb_strtolower($ua));\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $isProbablyBrowser || !$isProbablyBot;\n}\n\n$url = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027https:\/\/avris.it\u0027\u003C\/span\u003E . $_SERVER[\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027REQUEST_URI\u0027\u003C\/span\u003E];\n\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!isBrowser($_SERVER[\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027HTTP_USER_AGENT\u0027\u003C\/span\u003E] ?? \u003Cspan class=\u0022hljs-keyword\u0022\u003Enull\u003C\/span\u003E)) {\n    http_response_code(\u003Cspan class=\u0022hljs-number\u0022\u003E301\u003C\/span\u003E);\n    header(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Location: \u0027\u003C\/span\u003E . $url);\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Edie\u003C\/span\u003E;\n}\n\nhttp_response_code(\u003Cspan class=\u0022hljs-number\u0022\u003E404\u003C\/span\u003E);\n\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Eecho\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0026lt;\u0026lt;\u0026lt;HTML\n\n\u0026lt;!DOCTYPE html\u0026gt;\n\u0026lt;html lang=\u0022en\u0022\u0026gt;\n\u0026lt;head\u0026gt;\n    \u0026lt;meta charset=\u0022UTF-8\u0022\u0026gt;\n    \u0026lt;title\u0026gt;404 \u2013 Not found\u0026lt;\/title\u0026gt;\n    \u0026lt;meta name=\u0022viewport\u0022 content=\u0022width=device-width, initial-scale=1\u0022\u0026gt;\n\n    \u0026lt;link rel=\u0022shortcut icon\u0022 href=\u0022https:\/\/avris.it\/assetic\/gfx\/favicon.png\u0022 \/\u0026gt;\n    \u0026lt;link rel=\u0022stylesheet\u0022 href=\u0022https:\/\/cdn.jsdelivr.net\/gh\/kognise\/water.css@latest\/dist\/light.min.css\u0022\u0026gt;\n\u0026lt;\/head\u0026gt;\n\u0026lt;body\u0026gt;\n \u0026lt;h1\u0026gt;\n    404 \u2013 Not found\n\u0026lt;\/h1\u0026gt;\n\u0026lt;p\u0026gt;\n    This is not a valid subdomain.\n\u0026lt;\/p\u0026gt;\n\u0026lt;p\u0026gt;\n    Did you mean \u0026lt;a href=\u0022\u003Cspan class=\u0022hljs-subst\u0022\u003E$url\u003C\/span\u003E\u0022\u0026gt;\u003Cspan class=\u0022hljs-subst\u0022\u003E$url\u003C\/span\u003E\u0026lt;\/a\u0026gt; ?\n\u0026lt;\/p\u0026gt;\n\u0026lt;hr\/\u0026gt;\n\u0026lt;p\u0026gt;\n    \u0026lt;small\u0026gt;\n        You\u0027ll be redirected there in \u0026lt;span id=\u0022countdown\u0022\u0026gt;15\u0026lt;\/span\u0026gt; seconds anyway... \ud83e\udd37\n    \u0026lt;\/small\u0026gt;\n\u0026lt;p\u0026gt;\n\u0026lt;script\u0026gt;\n    const \\$el = document.getElementById(\u0027countdown\u0027);\n    seconds = 15;\n    setInterval(_ =\u0026gt; {\n        if (seconds === 0) {\n            window.location.href = \u0027\u003Cspan class=\u0022hljs-subst\u0022\u003E$url\u003C\/span\u003E\u0027;\n            return;\n        }\n        seconds--;\n        \\$el.innerHTML = seconds;\n    }, 1000);\n\u0026lt;\/script\u0026gt;\n\u0026lt;\/body\u0026gt;\n\u0026lt;\/html\u0026gt;\nHTML;\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["apache","bots","certbot","certificate","domain","https","letsencrypt","php","subdomain","wildcard"],"hasMore":true,"image":"https:\/\/avris.it\/image\/askara-redirect_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/askara-redirect_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/askara-redirect_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002292.011331444759\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFor quite a while my VPS was misconfigured \u2013 any HTTP requests it got but couldn\u2019t assign to a vhost, it redirected to the main website, \u003Ca href=\u0022https:\/\/avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E avris.it\u003C\/a\u003E. I didn\u2019t think it would be a big deal, until I recently found out that my post \u003Ca href=\u0022\/blog\/ungoogling.lite\u0022\u003E Ungoogling\u003C\/a\u003E is indexed by Google under \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022\u003Ehttps:\/\/askara.avris.it\/blog\/ungoogling\u003C\/a\u003E\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EThis subdomain hadn\u2019t existed for a long time already, my server doesn\u2019t serve a certificate for it anymore, but it requires \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/HTTP_Strict_Transport_Security\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E HSTS\u003C\/a\u003E, so browsers end up showing users a scary error message.\u003C\/p\u003E\n\u003Cp\u003EI had to do something about it.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/askara-redirect_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/askara-redirect_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002292.011331444759\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFor quite a while my VPS was misconfigured \u2013 any HTTP requests it got but couldn\u2019t assign to a vhost, it redirected to the main website, \u003Ca href=\u0022https:\/\/avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E avris.it\u003C\/a\u003E. I didn\u2019t think it would be a big deal, until I recently found out that my post \u003Ca href=\u0022\/blog\/ungoogling.lite\u0022\u003E Ungoogling\u003C\/a\u003E is indexed by Google under \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u003Ca href=\u0022https:\/\/askara.avris.it\/blog\/ungoogling\u0022\u003Ehttps:\/\/askara.avris.it\/blog\/ungoogling\u003C\/a\u003E\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EThis subdomain hadn\u2019t existed for a long time already, my server doesn\u2019t serve a certificate for it anymore, but it requires \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/HTTP_Strict_Transport_Security\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E HSTS\u003C\/a\u003E, so browsers end up showing users a scary error message.\u003C\/p\u003E\n\u003Cp\u003EI had to do something about it.\u003C\/p\u003E\n\u003Ch3\u003ECertificate\u003C\/h3\u003E\n\u003Cp\u003EFirst of all, users have to see \u003Cem\u003Eanything\u003C\/em\u003E other than a security warning. I need a wildcard certificate.\u003C\/p\u003E\n\u003Cp\u003EFortunately, Let\u2019s Encrypt offers them now, and it\u2019s totally free. I just followed \u003Ca href=\u0022https:\/\/medium.com\/@saurabh6790\/generate-wildcard-ssl-certificate-using-lets-encrypt-certbot-273e432794d7\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E an instruction\u003C\/a\u003E to obtain one, and then configured Apache to serve the \u003Ccode\u003E\/www\/default\u003C\/code\u003E directory with the \u003Ccode\u003E*.avris.it\u003C\/code\u003E certificate for all requests that don\u2019t fit to any vhost.\u003C\/p\u003E\n\u003Ch3\u003ERedirect for users\u003C\/h3\u003E\n\u003Cp\u003EOnce the users can see the website, I can show them things. Ideally, just a 404 with an information that it\u2019s not a valid domain, and a suggestion where they might have wanted to go (same request string, but with the base domain). Easy.\u003C\/p\u003E\n\u003Cp\u003EBtw, I used \u003Ca href=\u0022https:\/\/watercss.netlify.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Water.css\u003C\/a\u003E, a ridiculously simple CSS framework \u2013 I just added two lines, no classes, and the page already looks way better!\u003C\/p\u003E\n\u003Ch3\u003ERedirect for bots\u003C\/h3\u003E\n\u003Cp\u003EBut that doesn\u2019t solve the root cause: bots are confused about which domains they should be using. They don\u2019t care whether my certificate is working or not, they don\u2019t understand the message I left there for the users.\u003C\/p\u003E\n\u003Cp\u003EThey need a proper \u003Ccode\u003EHTTP 301 -- Moved permanently\u003C\/code\u003E. So I had to add a simple recognition whether I\u2019m serving a bot or a user, and adjust the response for each of them.\u003C\/p\u003E\n\u003Ch3\u003ESource\u003C\/h3\u003E\n\u003Cp\u003ESo, here\u2019s what I ended up with:\u003C\/p\u003E\n\u003Ch4\u003E.htaccess\u003C\/h4\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-htaccess\u0022\u003EDirectoryIndex index.php\n\n\u0026lt;IfModule mod_rewrite.c\u0026gt;\n    RewriteEngine On\n\n    RewriteCond %{REQUEST_URI}::$1 ^(\/.+)\/(.*)::\\2$\n    RewriteRule ^(.*) - [E=BASE:%1]\n\n    RewriteCond %{ENV:REDIRECT_STATUS} ^$\n    RewriteRule ^index\\.php(\/(.*)|$) %{ENV:BASE}\/$2 [R=301,L]\n\n    RewriteCond %{REQUEST_FILENAME} -f\n    RewriteRule .? - [L]\n\n    RewriteRule .? %{ENV:BASE}\/index.php [L]\n\u0026lt;\/IfModule\u0026gt;\n\n\u0026lt;IfModule !mod_rewrite.c\u0026gt;\n    \u0026lt;IfModule mod_alias.c\u0026gt;\n        RedirectMatch 302 ^\/$ \/index.php\/\n    \u0026lt;\/IfModule\u0026gt;\n\u0026lt;\/IfModule\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Ch4\u003Eindex.php\u003C\/h4\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E\u0026lt;?php\n\nfunction isBrowser($ua): bool\n{\n        if (!$ua) {\n                return false;\n        }\n        $isProbablyBot = (bool) preg_match(\u0027#bot|crawler|baiduspider|80legs|ia_archiver|voyager|curl|wget|yahoo! slurp|mediapartners-google|facebookexternalhit|twitterbot|whatsapp|php|python#i\u0027, mb_strtolower($ua));\n        $isProbablyBrowser = (bool) preg_match(\u0027#mozilla|msie|gecko|firefox|edge|opera|safari|netscape|konqueror|android#i\u0027, mb_strtolower($ua));\n\n        return $isProbablyBrowser || !$isProbablyBot;\n}\n\n$url = \u0027https:\/\/avris.it\u0027 . $_SERVER[\u0027REQUEST_URI\u0027];\n\nif (!isBrowser($_SERVER[\u0027HTTP_USER_AGENT\u0027] ?? null)) {\n    http_response_code(301);\n    header(\u0027Location: \u0027 . $url);\n    die;\n}\n\nhttp_response_code(404);\n\necho \u0026lt;\u0026lt;\u0026lt;HTML\n\n\u0026lt;!DOCTYPE html\u0026gt;\n\u0026lt;html lang=\u0022en\u0022\u0026gt;\n\u0026lt;head\u0026gt;\n    \u0026lt;meta charset=\u0022UTF-8\u0022\u0026gt;\n    \u0026lt;title\u0026gt;404 \u2013 Not found\u0026lt;\/title\u0026gt;\n    \u0026lt;meta name=\u0022viewport\u0022 content=\u0022width=device-width, initial-scale=1\u0022\u0026gt;\n\n    \u0026lt;link rel=\u0022shortcut icon\u0022 href=\u0022https:\/\/avris.it\/assetic\/gfx\/favicon.png\u0022 \/\u0026gt;\n    \u0026lt;link rel=\u0022stylesheet\u0022 href=\u0022https:\/\/cdn.jsdelivr.net\/gh\/kognise\/water.css@latest\/dist\/light.min.css\u0022\u0026gt;\n\u0026lt;\/head\u0026gt;\n\u0026lt;body\u0026gt;\n \u0026lt;h1\u0026gt;\n    404 \u2013 Not found\n\u0026lt;\/h1\u0026gt;\n\u0026lt;p\u0026gt;\n    This is not a valid subdomain.\n\u0026lt;\/p\u0026gt;\n\u0026lt;p\u0026gt;\n    Did you mean \u0026lt;a href=\u0022$url\u0022\u0026gt;$url\u0026lt;\/a\u0026gt; ?\n\u0026lt;\/p\u0026gt;\n\u0026lt;hr\/\u0026gt;\n\u0026lt;p\u0026gt;\n    \u0026lt;small\u0026gt;\n        You\u0027ll be redirected there in \u0026lt;span id=\u0022countdown\u0022\u0026gt;15\u0026lt;\/span\u0026gt; seconds anyway... \ud83e\udd37\n    \u0026lt;\/small\u0026gt;\n\u0026lt;p\u0026gt;\n\u0026lt;script\u0026gt;\n    const \\$el = document.getElementById(\u0027countdown\u0027);\n    seconds = 15;\n    setInterval(_ =\u0026gt; {\n        if (seconds === 0) {\n            window.location.href = \u0027$url\u0027;\n            return;\n        }\n        seconds--;\n        \\$el.innerHTML = seconds;\n    }, 1000);\n\u0026lt;\/script\u0026gt;\n\u0026lt;\/body\u0026gt;\n\u0026lt;\/html\u0026gt;\nHTML;\u003C\/code\u003E\u003C\/pre\u003E","words":651,"readTime":3,"lang":"en"}}},"blog\/technology\/g\u0142osowanie-elektroniczne-spoko-a-jutro-obiecamy-teleporter-w-ka\u017cdym-domu":{"key":"blog\/technology\/g\u0142osowanie-elektroniczne-spoko-a-jutro-obiecamy-teleporter-w-ka\u017cdym-domu","type":"article","published":true,"meta":{"createdAt":"2019-08-15T10:49:16+02:00","publishedAt":"2019-08-15T10:47:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"g\u0142osowanie-elektroniczne-spoko-a-jutro-obiecamy-teleporter-w-ka\u017cdym-domu"},"content":{"pl":{"slug":"g\u0142osowanie-elektroniczne-spoko-a-jutro-obiecamy-teleporter-w-ka\u017cdym-domu","title":"G\u0142osowanie elektroniczne? Spoko, a jutro obiecamy teleporter w ka\u017cdym domu...","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/g\u0142osowanie-elektroniczne_small.jpg\u0022 alt=\u0022? Chcemy, \u017ceby jak najwi\u0119cej Obywateli mog\u0142o wzi\u0105\u0107 udzia\u0142 w wyborach i referendach. G\u0142osowanie elektroniczne to ju\u017c standard w zachodnich demokracjach. Czas i na Polsk\u0119! #KoalicjaObywatelska #Sz\u00f3stkaSchetyny\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022480\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAACXBIWXMAAA7EAAAOxAGVKw4bAAANYklEQVRYhT2YWa9e11mAnzXs8ZvPfHwG28fTsWM7cyK3SSdSCAghVdxUSNxxBRf8AG7yA\/gBvUACJIqgUoXaCmirCmgbIICbNE2cpLbj2T4+w3e+ce9vD2vg4jPcbmnttd73Xetdz3pEe2XTe1PhnENKjQ5jvHM4a9BBQJFPQCiCqIEXAiEkabNNPhninEVIDc4hAoXSEUprhJQ4a3HOgLM4a8F7vLNU2RipA3SY4HFo4THGUOZTZBCg8YKtrS2KogAUSodYWyOEIIhTAh2QTwYgA7x3oBQSQbuxCgKklAgESI0KI+qqROoAUxXYqiCMUryzIBwgKKdNvHN0V0\/Q6rQoZwXHBweESnD\/wQM0QmAs5BVk42OkDvCAdw5cHx1ovDOoIEbpAKk1QkiEsCAEAo9HgBA4nwGeIp\/gnMXUNaubp1nf2qQuSx7euUc5zSimY6Y18HieSe8dS702SI121mKqirqYIQQIIdBaI4MAJTV4R1XM0GFMmKYooUAIwOMdCOGIkoQoTUAIjo9G+HyC1pq6KMjGAx7czDGmwhhDlDSZTcaYqiKIEvAe5zxCBgih0FqHBFEMkxwVRsggJIibCCFwzqGEpByPkDogjhvESczi6hLdhS5CaWxdI5Ti4Mk+g6M+SoBWilBrcuuoZjO0jnFeYq0niproKMFYC3WJFBKt9f8HqZUOQCpEGGFnOQhLp7dAo9Nm\/+EjhIcgSqjrmmanw8raOkeHh4yOJxR5Po\/Qe6y1OOeIogTR7FIVU+I0wTtHNh0hpUJKQVlmCBXgnGNxdQNjDaaqUEFIEKdoa2ukkCipCJMGVTHDlIZ8NCYKQqy1RHGDyeCQbJqz92gPaw11VWHrGm8NEoF1lrIuqeuKMEyxxtJsdekfHbB+6jQIj6lL6tmMsBsy6B9QG8PG9inCNKSejDnqH6OdF1hTI4RERwnZdIyUkpNnz3P300\/xHja2d\/j0eJ+Dp0+I0ybOWiQCcOA8TkX4oIlPl\/FBwmg6RM6e0llcZtA\/xFQlL77xBYQW1HnOh+\/9DxIo84zxYER1UJLGASKI0EJKLFBVBa2khfAw6B\/w8fX\/24g1zc4yC2vbBEFElDY4PnhCTszK7huIsIVQCmtqjPVYYxDpEtnxHaIoReqAcjblwecPmU2nzPIJSE3caJPnGUgFQgMSrWM0CIQQWOcwpiROmvMGqCT5cEjaaLK2eYIwCimLEikFy6vb3DsY0l3eJhIFp0606bYiOs2U7\/70Fs5ZsnSZoqpotDrk+RRvPWGUUpYloGh2Vxn29+j3+\/PD02lQzHI0UjxbpaS3uESjvYyQgiAMwVumo2PKoiJOUsqioigrOu0u5e3bOGeoVMhwUtKfWvrjPsiAIIwIe5sUs3t0FlcoipKDR\/cQWj87AIYoigmTJkprIh3Q7i7iZYoOwwSBoLewBCKg0ZqvtJjNCKOUqnxMNpmyurlOluUgBNYLpIDp4JCVzdOMrMIYC0oShgXOWOLeOpNbH3HyzCWy8RilQlQwv5qSOCEIY5CK2lqcEOgkglmNNlVJkiyzsbLN08M+vXaLqqyAila7y551jEd9OouLVFXNLM9YXN2g2Wyxd+cTnAhYWDvBeDDmT99eJ003+d71Pd6\/VTKyGlNX7Fy4gnM86+YOU9dIBMZ7vNbUxuCReBQyCALO717lzu2bCKmJG00A8JLeygZhnNI\/3OeTD97nYP8xVVWy9\/g+26fO0EkC7n34U+7eusmF+JilyYDVlSX+8OuXabfaBN0TjIZDdBijggBg3pWForYOLyRWaQgTCGO8jlAvvP71d2rjufXrjyirktFgzHg8IJ\/NqKqS3vIyVVEwGh5w8sw5Xnj1GjoIkVKQBIrJ+JDhOOONU106qUdKi3AzrE749eMhZrrPyvIawgus89hnBwghsFKBCrFSk8QJRW2Rx8fHjKcTmgurKK0ZHu\/RbLd54ZWXWFxYJAgbnNx9Hh2GTKYTnATvwXpPWVfgLdRjDkcTyrJisvcIZwq+uA0n1jfIsgwjBD4IIU7wQoFSWKnxUmOlpj8aUaDJCZCzsqauS7SKOLF9AWsKwiCg2e6iVTC\/y2ZzjJgMB4xHGXEzxVg7j9Q7vC3ZH2X0h1Mms5LxOKOuK37jyjK1bJDnM5yfc4+1ltpYnLEYY2kGnlPLTdppQJymqIuvvPkO1jLNZwghyKcjlA5ot3oUdUX9DA+qqiKbDOgsrSODgGF\/wHg8YDYdYb1gUhjOLnexHpxSVAYWAsvplRb74wKHwjiPE5KGEiyGggsbHdZWemye2WFzewNRlehsOiNUkjAI55dj3CDLJqAkOtBIY6iqirTdY9h\/yu2P38cLSVnmc5DzEIQRha248XTI1Sii2h\/QW5ZEOuDUxUusnnf8+N0beGfYSCWyFtSVxTpBpVOslXSsJmy0UedeuPYOwKyoCaMIpCDSjqJ0+LrEmZJGrPEyYG2xiUGysLTExsYmi90FQJGkCQudNkZIemnCyuoKzkPSbNDsdXEqRElJ2e\/TaTaxKsBahxGaWkhsbZFIxsfH6Hu3b7G40GUyPsYNHatbO7x26SoXL5wHIajLgqtXrjCcZCwvdnl6cIzWksPBhKV2yqO9fZz3FGXN6y9d5ns\/+AlffuvLOGv5xcefsXv2NFltef2lK3zn7x1\/9Ae\/w4\/e\/SWr3ZS\/+vYPCByQ1ARBCkIi88mQIhtTTAfEcUwSB3x254g3Xn+ZE+sb\/Ou774GAv\/7uj4njmNp5oiRlodfh+z\/6GVcvnuXC2R3G4wmf33nApefOo7WmMo5Lu+e4u3dEbRwPnhzwxS88z8+u3+A7P\/xPxuOcbGbIs5xZVpBnE5qBRJx87k2\/urbOjY8+YGXzDM9ducKjh08INFgU9x7epRGFtJa2OHdmi6ODPnlVMZuMOBqMaabRvME5T57PaCQhL53bAaHpLnUJGylWh9Re8fmjQw739imLmo2GpsgytFb4KKS7tISQAq2UQiqN0ppylvHg3kOklEwmJb\/\/e18jDq5x9\/59aplwcmuD3ssX+fzhU66e3+Lf3vuQFy\/uMJyWJEnIykKXD27cRFrPV774MjfvPkGEIb1OgzhN+OZbr\/Ktb\/8zv7hxh3FmoCqpaoGsS+pWi0AKpHcOW5VoIaizMd5aet0W1llOb69zf++IL117mWas2Fjp8Jd\/933ObCxhjOUbv\/Umf\/tPP2djfYlGs4nwjm+8\/SXOXbpAp92k12uxtdRmoZkQa0UjVAyGI6QQlHVJVVWUxYyyLKmLea8Sp6+86Zd6Pe7eu081m7KwugVC0GnGXL64w9bps\/z8v67zytXn+I\/rH3LttRf5ybvv89abr\/GPP\/1vfvsrr3P9l59ig4ijwz67Z08RCEE2ydk9u8mnN++ys70OWrO5uc6Hn9zhvfdvEmvw2QgPzxhrkXarjWq0l9\/RSpDPSqrZhCKfcO3Vq\/zJN3+XC2fOsrW5xmgyY311iSCKWOz1SNOU01sn+Jd\/\/4C1tWU2TqxRFSVnttd57fkL6CBkZ2uFKAzY2VojCgJuPz6gEYdcPrvFcjvm7a++xv0HDxkNR3hXE0eaMIrQk+NDEu0pszHeOWQgefGFK6TNNq1uFxUnrC4s0Ou0WZ6VDAdDRtMCLwVKSV6\/fJbL509jnOeP\/+zPee35XU5trPKrjz7jN7\/8Ks4ZimnOiy9cYjgY0G41+Iu\/+Qcu7+7w+GiIczWYClvGFFmIjtMmaatLVBist3gpefjwCTfffY9rb30VJwTntleoraPMprQaKdfWV5mOR0jhufX5fT74+DPWVpaps4xbt+8idMRSt8n7v\/qUKI6ZDIfsH15n++QGW+vLLC50+fzufTA12BprSuoyQ8YBYnlj1y+vLHF4NCCfjlE6pJ02eHHnNF46IinQUYQIEz787DaPRzlBnOIQeKnwAnACpART4ZUCqWlHIUp4kArr\/LPXsMYJgTc1zhjsbIqrc0xVsrTQodXpop2bP\/Csc4DHmZqsmLHfPyJWnjSOCKoCH1YstVs86h9jZg4fpXgxZxHhHN56hKnBADrEYfHC46XCWTM3IlGMlwq8x5qa+dxgqwJnG1hToZ13eGvAmWek6LC1IctG1FpjvSexBpwDIUnjhNxLvNSgAvAOYQqEM+AdOItA4LQCBG42wUuNcwZZzRBag5C4usS5Gm8t3husKbHVDO393AW5ukICzjucrShMiHUWEHgXzn\/OM7IrDV6IOZxJCVIinJhrF6XnmXZujqxC4W0FzuGqaq50hEBIOU8EAiED8B4lFdoUE6xJqascjwQ\/h\/GyKDBK4pzDe4\/0FocklnNp5YMQpMI7i7QWb6p5tqScf8c\/0zo1zlRIxFzb4HGmmpdRCKSaP7f8sy2j66pACstCt4WQCinmAxMlkUoTBgFREBGE81Q3dIKsBZUK5xM4h4gFvg7nJZcCLyTXnj5i1xbMrCd\/9SWq3V3Ont7i8PCIbq9DnuWoH\/4IfeMG31paIYr1nK\/CKPbOOZSce5+5hvFESqGURAlFEIREoX6ma1JmxpNZwIP3Dl8Wc20l5NwxSUUg\/DzqusACzs\/Lb20B3iJVgHAecNTO4oxBhRH\/CymuId3ddm7PAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/g\u0142osowanie-elektroniczne_small.jpg\u0022 alt=\u0022? Chcemy, \u017ceby jak najwi\u0119cej Obywateli mog\u0142o wzi\u0105\u0107 udzia\u0142 w wyborach i referendach. G\u0142osowanie elektroniczne to ju\u017c standard w zachodnich demokracjach. Czas i na Polsk\u0119! #KoalicjaObywatelska #Sz\u00f3stkaSchetyny\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022480\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EPlatforma Obywatelska obieca\u0142a, \u017ce wprowadz\u0105 g\u0142osowanie elektroniczne. Ta partia nie jest znana z realizowania obietnic, wi\u0119c nie boj\u0119 si\u0119 zbytnio, \u017ce ten okropny, okropny pomys\u0142 wejdzie dzi\u0119ki nim w \u017cycie. Ale temat mnie poruszy\u0142, bo widz\u0119, jak bardzo ludzie s\u0105 zafascynowani tak\u0105 opcj\u0105 i jak bezkrytycznie j\u0105 popieraj\u0105, my\u015bl\u0105c, \u017ce skoro wszystko inne jest lepsze dzi\u0119ki komputerom, to g\u0142osowanie te\u017c musi.\u003C\/p\u003E\n\u003Cp\u003EOt\u00f3\u017c wcale nie musi.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/g\u0142osowanie-elektroniczne_big.jpg\u0022 alt=\u0022? Chcemy, \u017ceby jak najwi\u0119cej Obywateli mog\u0142o wzi\u0105\u0107 udzia\u0142 w wyborach i referendach. G\u0142osowanie elektroniczne to ju\u017c standard w zachodnich demokracjach. Czas i na Polsk\u0119! #KoalicjaObywatelska #Sz\u00f3stkaSchetyny\u0022 class=\u0022border\u0022 width=\u0022680\u0022 height=\u0022680\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAACXBIWXMAAA7EAAAOxAGVKw4bAAANYklEQVRYhT2YWa9e11mAnzXs8ZvPfHwG28fTsWM7cyK3SSdSCAghVdxUSNxxBRf8AG7yA\/gBvUACJIqgUoXaCmirCmgbIICbNE2cpLbj2T4+w3e+ce9vD2vg4jPcbmnttd73Xetdz3pEe2XTe1PhnENKjQ5jvHM4a9BBQJFPQCiCqIEXAiEkabNNPhninEVIDc4hAoXSEUprhJQ4a3HOgLM4a8F7vLNU2RipA3SY4HFo4THGUOZTZBCg8YKtrS2KogAUSodYWyOEIIhTAh2QTwYgA7x3oBQSQbuxCgKklAgESI0KI+qqROoAUxXYqiCMUryzIBwgKKdNvHN0V0\/Q6rQoZwXHBweESnD\/wQM0QmAs5BVk42OkDvCAdw5cHx1ovDOoIEbpAKk1QkiEsCAEAo9HgBA4nwGeIp\/gnMXUNaubp1nf2qQuSx7euUc5zSimY6Y18HieSe8dS702SI121mKqirqYIQQIIdBaI4MAJTV4R1XM0GFMmKYooUAIwOMdCOGIkoQoTUAIjo9G+HyC1pq6KMjGAx7czDGmwhhDlDSZTcaYqiKIEvAe5zxCBgih0FqHBFEMkxwVRsggJIibCCFwzqGEpByPkDogjhvESczi6hLdhS5CaWxdI5Ti4Mk+g6M+SoBWilBrcuuoZjO0jnFeYq0niproKMFYC3WJFBKt9f8HqZUOQCpEGGFnOQhLp7dAo9Nm\/+EjhIcgSqjrmmanw8raOkeHh4yOJxR5Po\/Qe6y1OOeIogTR7FIVU+I0wTtHNh0hpUJKQVlmCBXgnGNxdQNjDaaqUEFIEKdoa2ukkCipCJMGVTHDlIZ8NCYKQqy1RHGDyeCQbJqz92gPaw11VWHrGm8NEoF1lrIuqeuKMEyxxtJsdekfHbB+6jQIj6lL6tmMsBsy6B9QG8PG9inCNKSejDnqH6OdF1hTI4RERwnZdIyUkpNnz3P300\/xHja2d\/j0eJ+Dp0+I0ybOWiQCcOA8TkX4oIlPl\/FBwmg6RM6e0llcZtA\/xFQlL77xBYQW1HnOh+\/9DxIo84zxYER1UJLGASKI0EJKLFBVBa2khfAw6B\/w8fX\/24g1zc4yC2vbBEFElDY4PnhCTszK7huIsIVQCmtqjPVYYxDpEtnxHaIoReqAcjblwecPmU2nzPIJSE3caJPnGUgFQgMSrWM0CIQQWOcwpiROmvMGqCT5cEjaaLK2eYIwCimLEikFy6vb3DsY0l3eJhIFp0606bYiOs2U7\/70Fs5ZsnSZoqpotDrk+RRvPWGUUpYloGh2Vxn29+j3+\/PD02lQzHI0UjxbpaS3uESjvYyQgiAMwVumo2PKoiJOUsqioigrOu0u5e3bOGeoVMhwUtKfWvrjPsiAIIwIe5sUs3t0FlcoipKDR\/cQWj87AIYoigmTJkprIh3Q7i7iZYoOwwSBoLewBCKg0ZqvtJjNCKOUqnxMNpmyurlOluUgBNYLpIDp4JCVzdOMrMIYC0oShgXOWOLeOpNbH3HyzCWy8RilQlQwv5qSOCEIY5CK2lqcEOgkglmNNlVJkiyzsbLN08M+vXaLqqyAila7y551jEd9OouLVFXNLM9YXN2g2Wyxd+cTnAhYWDvBeDDmT99eJ003+d71Pd6\/VTKyGlNX7Fy4gnM86+YOU9dIBMZ7vNbUxuCReBQyCALO717lzu2bCKmJG00A8JLeygZhnNI\/3OeTD97nYP8xVVWy9\/g+26fO0EkC7n34U+7eusmF+JilyYDVlSX+8OuXabfaBN0TjIZDdBijggBg3pWForYOLyRWaQgTCGO8jlAvvP71d2rjufXrjyirktFgzHg8IJ\/NqKqS3vIyVVEwGh5w8sw5Xnj1GjoIkVKQBIrJ+JDhOOONU106qUdKi3AzrE749eMhZrrPyvIawgus89hnBwghsFKBCrFSk8QJRW2Rx8fHjKcTmgurKK0ZHu\/RbLd54ZWXWFxYJAgbnNx9Hh2GTKYTnATvwXpPWVfgLdRjDkcTyrJisvcIZwq+uA0n1jfIsgwjBD4IIU7wQoFSWKnxUmOlpj8aUaDJCZCzsqauS7SKOLF9AWsKwiCg2e6iVTC\/y2ZzjJgMB4xHGXEzxVg7j9Q7vC3ZH2X0h1Mms5LxOKOuK37jyjK1bJDnM5yfc4+1ltpYnLEYY2kGnlPLTdppQJymqIuvvPkO1jLNZwghyKcjlA5ot3oUdUX9DA+qqiKbDOgsrSODgGF\/wHg8YDYdYb1gUhjOLnexHpxSVAYWAsvplRb74wKHwjiPE5KGEiyGggsbHdZWemye2WFzewNRlehsOiNUkjAI55dj3CDLJqAkOtBIY6iqirTdY9h\/yu2P38cLSVnmc5DzEIQRha248XTI1Sii2h\/QW5ZEOuDUxUusnnf8+N0beGfYSCWyFtSVxTpBpVOslXSsJmy0UedeuPYOwKyoCaMIpCDSjqJ0+LrEmZJGrPEyYG2xiUGysLTExsYmi90FQJGkCQudNkZIemnCyuoKzkPSbNDsdXEqRElJ2e\/TaTaxKsBahxGaWkhsbZFIxsfH6Hu3b7G40GUyPsYNHatbO7x26SoXL5wHIajLgqtXrjCcZCwvdnl6cIzWksPBhKV2yqO9fZz3FGXN6y9d5ns\/+AlffuvLOGv5xcefsXv2NFltef2lK3zn7x1\/9Ae\/w4\/e\/SWr3ZS\/+vYPCByQ1ARBCkIi88mQIhtTTAfEcUwSB3x254g3Xn+ZE+sb\/Ou774GAv\/7uj4njmNp5oiRlodfh+z\/6GVcvnuXC2R3G4wmf33nApefOo7WmMo5Lu+e4u3dEbRwPnhzwxS88z8+u3+A7P\/xPxuOcbGbIs5xZVpBnE5qBRJx87k2\/urbOjY8+YGXzDM9ducKjh08INFgU9x7epRGFtJa2OHdmi6ODPnlVMZuMOBqMaabRvME5T57PaCQhL53bAaHpLnUJGylWh9Re8fmjQw739imLmo2GpsgytFb4KKS7tISQAq2UQiqN0ppylvHg3kOklEwmJb\/\/e18jDq5x9\/59aplwcmuD3ssX+fzhU66e3+Lf3vuQFy\/uMJyWJEnIykKXD27cRFrPV774MjfvPkGEIb1OgzhN+OZbr\/Ktb\/8zv7hxh3FmoCqpaoGsS+pWi0AKpHcOW5VoIaizMd5aet0W1llOb69zf++IL117mWas2Fjp8Jd\/933ObCxhjOUbv\/Umf\/tPP2djfYlGs4nwjm+8\/SXOXbpAp92k12uxtdRmoZkQa0UjVAyGI6QQlHVJVVWUxYyyLKmLea8Sp6+86Zd6Pe7eu081m7KwugVC0GnGXL64w9bps\/z8v67zytXn+I\/rH3LttRf5ybvv89abr\/GPP\/1vfvsrr3P9l59ig4ijwz67Z08RCEE2ydk9u8mnN++ys70OWrO5uc6Hn9zhvfdvEmvw2QgPzxhrkXarjWq0l9\/RSpDPSqrZhCKfcO3Vq\/zJN3+XC2fOsrW5xmgyY311iSCKWOz1SNOU01sn+Jd\/\/4C1tWU2TqxRFSVnttd57fkL6CBkZ2uFKAzY2VojCgJuPz6gEYdcPrvFcjvm7a++xv0HDxkNR3hXE0eaMIrQk+NDEu0pszHeOWQgefGFK6TNNq1uFxUnrC4s0Ou0WZ6VDAdDRtMCLwVKSV6\/fJbL509jnOeP\/+zPee35XU5trPKrjz7jN7\/8Ks4ZimnOiy9cYjgY0G41+Iu\/+Qcu7+7w+GiIczWYClvGFFmIjtMmaatLVBist3gpefjwCTfffY9rb30VJwTntleoraPMprQaKdfWV5mOR0jhufX5fT74+DPWVpaps4xbt+8idMRSt8n7v\/qUKI6ZDIfsH15n++QGW+vLLC50+fzufTA12BprSuoyQ8YBYnlj1y+vLHF4NCCfjlE6pJ02eHHnNF46IinQUYQIEz787DaPRzlBnOIQeKnwAnACpART4ZUCqWlHIUp4kArr\/LPXsMYJgTc1zhjsbIqrc0xVsrTQodXpop2bP\/Csc4DHmZqsmLHfPyJWnjSOCKoCH1YstVs86h9jZg4fpXgxZxHhHN56hKnBADrEYfHC46XCWTM3IlGMlwq8x5qa+dxgqwJnG1hToZ13eGvAmWek6LC1IctG1FpjvSexBpwDIUnjhNxLvNSgAvAOYQqEM+AdOItA4LQCBG42wUuNcwZZzRBag5C4usS5Gm8t3husKbHVDO393AW5ukICzjucrShMiHUWEHgXzn\/OM7IrDV6IOZxJCVIinJhrF6XnmXZujqxC4W0FzuGqaq50hEBIOU8EAiED8B4lFdoUE6xJqascjwQ\/h\/GyKDBK4pzDe4\/0FocklnNp5YMQpMI7i7QWb6p5tqScf8c\/0zo1zlRIxFzb4HGmmpdRCKSaP7f8sy2j66pACstCt4WQCinmAxMlkUoTBgFREBGE81Q3dIKsBZUK5xM4h4gFvg7nJZcCLyTXnj5i1xbMrCd\/9SWq3V3Ont7i8PCIbq9DnuWoH\/4IfeMG31paIYr1nK\/CKPbOOZSce5+5hvFESqGURAlFEIREoX6ma1JmxpNZwIP3Dl8Wc20l5NwxSUUg\/DzqusACzs\/Lb20B3iJVgHAecNTO4oxBhRH\/CymuId3ddm7PAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/g\u0142osowanie-elektroniczne_big.jpg\u0022 alt=\u0022? Chcemy, \u017ceby jak najwi\u0119cej Obywateli mog\u0142o wzi\u0105\u0107 udzia\u0142 w wyborach i referendach. G\u0142osowanie elektroniczne to ju\u017c standard w zachodnich demokracjach. Czas i na Polsk\u0119! #KoalicjaObywatelska #Sz\u00f3stkaSchetyny\u0022 class=\u0022border\u0022 width=\u0022680\u0022 height=\u0022680\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/twitter.com\/Platforma_org\/status\/1161551915093831680\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        twitter.com\/Platforma_org\/status\/1161551915093831680\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EPlatforma Obywatelska obieca\u0142a, \u017ce wprowadz\u0105 g\u0142osowanie elektroniczne. Ta partia nie jest znana z realizowania obietnic, wi\u0119c nie boj\u0119 si\u0119 zbytnio, \u017ce ten okropny, okropny pomys\u0142 wejdzie dzi\u0119ki nim w \u017cycie. Ale temat mnie poruszy\u0142, bo widz\u0119, jak bardzo ludzie s\u0105 zafascynowani tak\u0105 opcj\u0105 i jak bezkrytycznie j\u0105 popieraj\u0105, my\u015bl\u0105c, \u017ce skoro wszystko inne jest lepsze dzi\u0119ki komputerom, to g\u0142osowanie te\u017c musi.\u003C\/p\u003E\n\u003Cp\u003EOt\u00f3\u017c wcale nie musi.\u003C\/p\u003E\n\u003Cp\u003ECho\u0107 na pierwszy rzut oka mo\u017ce si\u0119 tak wydawa\u0107, to wybory wcale nie s\u0105 z punktu widzenia informatyki na podobnym \u201cpoziomie trudno\u015bci\u201d co na przyk\u0142ad p\u0142atno\u015bci przez Internet. Ludzie my\u015bl\u0105, \u017ce skoro mog\u0105 z poziomu przegl\u0105darki bezpiecznie wys\u0142a\u0107 przelew na kilka tysi\u0119cy albo za\u0142atwi\u0107 spraw\u0119 urz\u0119dow\u0105, to czemu mia\u0142o by by\u0107 tak trudno za\u0142atwi\u0107 tam r\u00f3wnie\u017c i g\u0142osowanie?\u003C\/p\u003E\n\u003Cp\u003EW pierwszym przypadku g\u0142\u00f3wnym problemem do rozwi\u0105zania jest to, aby obie strony komunikacji (klient i bank, petent i urz\u0105d, itp.) mia\u0142y pewno\u015b\u0107 co do \u003Cstrong\u003Eto\u017csamo\u015bci\u003C\/strong\u003E rozm\u00f3wcy, oraz to, \u017ceby nikt postronny ich \u003Cstrong\u003Enie pods\u0142ucha\u0142\u003C\/strong\u003E. Te problemy rozwi\u0105zali\u015bmy ju\u017c dawno i wci\u0105\u017c udoskonalamy nasze rozwi\u0105zania.\u003C\/p\u003E\n\u003Cp\u003ENatomiast w przypadku g\u0142osowania dochodzi do tego kolejny element: gdy ju\u017c upewnimy si\u0119, \u017ce naprawd\u0119 rozmawiamy z Janem Kowalskim, i \u017ce Jan Kowalski ma prawo do g\u0142osu, i \u017ce jeszcze swojego g\u0142osu nie odda\u0142, musimy zapewni\u0107 mu pe\u0142n\u0105 anonimowo\u015b\u0107. Nie mo\u017cemy wiedzie\u0107, jak Jan Kowalski zag\u0142osowa\u0142. \u003Cstrong\u003EProfil Zaufany\u003C\/strong\u003E zapewni nam pierwsz\u0105 cz\u0119\u015b\u0107, ale nie drug\u0105. Tak samo wszystkie inne \u003Cem\u003Ebuzz words\u003C\/em\u003E, kt\u00f3re s\u0142ysza\u0142em od zwolennik\u00f3w pomys\u0142u: rozpoznawanie twarzy, odcisk\u00f3w palca, a przede wszystkim ten mityczny \u003Cem\u003Eblockhain\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EBlockchain\u003C\/strong\u003E, moi drodzy, jest w gruncie rzeczy bardzo skomplikowan\u0105 i bardzo woln\u0105 \u003Cem\u003Ebaz\u0105 danych\u003C\/em\u003E. Nie rozwi\u0105zuje problem\u00f3w z elektronicznym g\u0142osowaniem. Przede wszystkim dlatego, \u017ce z definicji jest weryfikowalny. \u003C\/p\u003E\n\u003Cp\u003EA Konstytucja gwarantuje \u003Cstrong\u003Etajno\u015b\u0107\u003C\/strong\u003E wybor\u00f3w. I bardzo dobrze!\u003C\/p\u003E\n\u003Cp\u003ENie chodzi tu o to, \u017ce wstydz\u0119 si\u0119 mojego g\u0142osu i wola\u0142bym, \u017ceby nikt o nim nie wiedzia\u0142. Chodzi o integralno\u015b\u0107 ca\u0142ego procesu.\u003C\/p\u003E\n\u003Cp\u003EGdyby wybory tajne nie by\u0142y, otworzy\u0142oby to furtk\u0119 dla r\u00f3\u017cnej ma\u015bci matactw: kupowania g\u0142os\u00f3w, zastraszania wyborc\u00f3w, etc. Nie mo\u017cna natomiast zmusi\u0107 kogo\u015b do zag\u0142osowania w konkretny spos\u00f3b, je\u017celi nie ma si\u0119 fizycznej mo\u017cliwo\u015bci sprawdzenia, jak ten kto\u015b zag\u0142osowa\u0142.\u003C\/p\u003E\n\u003Cp\u003EProblemem jest r\u00f3wnie\u017c to, \u017ce wybory elektroniczne s\u0105 zdecydowanie \u003Cstrong\u003E\u0142atwiejsze do sfa\u0142szowania\u003C\/strong\u003E. To, \u017ce tobie jest wygodniej zag\u0142osowa\u0107 nie ruszaj\u0105c si\u0119 z domu, znaczy te\u017c, \u017ce fa\u0142szerzowi wygodniej jest fa\u0142szowa\u0107 \u2013 on te\u017c nie musi si\u0119 rusza\u0107 z domu.\u003C\/p\u003E\n\u003Cp\u003E\u017beby sfa\u0142szowa\u0107 tradycyjne wybory, trzeba du\u017cego nak\u0142adu \u015brodk\u00f3w. \u017beby sfa\u0142szowa\u0107 wybory elektroniczne, w najgorszym wypadku wystarczy jedna luka w zabezpieczeniach jednego serwera, wykorzystana zdalnie z drugiego ko\u0144ca \u015bwiata.\u003C\/p\u003E\n\u003Cp\u003EW tradycyjnym g\u0142osowaniu masz fizyczne lokale wyborcze, ludzi b\u0119d\u0105cych na miejscu, r\u0119cz\u0105cych za poprawno\u015b\u0107 g\u0142osowania i liczenia g\u0142os\u00f3w, a przede wszystkim kontroluj\u0105cych si\u0119 nawzajem.\u003C\/p\u003E\n\u003Cp\u003EW g\u0142osowaniu elektronicznym natomiast masz system informatyczny, kt\u00f3ry dla wyborcy jest raptem czarn\u0105 skrzynk\u0105 kontrolowan\u0105 przez rz\u0105d. Czy serio by\u015b mu ufa\u0142?\u003C\/p\u003E\n\u003Cp\u003EWyobra\u017a sobie \u017ce PiS otwiera \u201cniezale\u017cn\u0105\u201d central\u0119 telefoniczn\u0105, w kt\u00f3rej \u201cniezale\u017cni\u201d telefoni\u015bci zbieraliby od ludzi g\u0142osy bez wychodzenia z domu. Uzna\u0142by\u015b to za wygodny spos\u00f3b g\u0142osowania czy raczej za wygodny spos\u00f3b sfa\u0142szowania wyniku?\u003C\/p\u003E\n\u003Cp\u003EGdy doda\u0107 do tego komputery, wci\u0105\u017c dzia\u0142a\u0142oby to mniej wi\u0119cej tak samo. Po prostu istnia\u0142aby opcja zweryfikowania twojej to\u017csamo\u015bci, natomiast nie by\u0142oby opcji, \u017ce kto\u015b pods\u0142ucha konwersacj\u0119 mi\u0119dzy tob\u0105 a central\u0105. Kwestia braku zaufania do centrali wci\u0105\u017c pozostaje nierozwi\u0105zana. Tak samo jak kwestia potencjalnego pistoletu przystawionego do twojej skroni, by\u015b zaznaczy\u0142 odpowiednie pole na ekranie.\u003C\/p\u003E\n\u003Cp\u003EG\u0142osowania elektroniczne ju\u017c mia\u0142y miejsce w kilku krajach na \u015bwiecie. Najg\u0142o\u015bniejszym przyk\u0142adem jest chyba Estonia, w kt\u00f3rej eksperyment ten okaza\u0142 si\u0119 by\u0107, surprise surprise, fiaskiem: \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Electronic_voting_in_Estonia#Criticism\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Wikipedia\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/estoniaevoting.org\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E estoniaevoting.org\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003ENie w\u0105tpi\u0119, \u017ce kiedy\u015b uda si\u0119 informatykom wymy\u015bli\u0107 system, w kt\u00f3rym integralno\u015b\u0107 wybor\u00f3w b\u0119dzie r\u00f3wnie (lub bardziej) bezpieczna co w przypadku tradycyjnych g\u0142osowa\u0144. Ale ten dzie\u0144 jeszcze nie nast\u0105pi\u0142. W 2019 roku nie mamy technologii by przeprowadzi\u0107 wybory elektroniczne, kt\u00f3re spe\u0142nia\u0142yby standardy demokratyczne i odpowiednie standardy bezpiecze\u0144stwa.\u003C\/p\u003E\n\u003Cp\u003ECo nast\u0119pne? Platforma obiecuj\u0105ca wszystkim \u201cteleporter w ka\u017cdym domu\u201d?\u003C\/p\u003E\n\u003Cp\u003EMam taki pomys\u0142: mo\u017ce najpierw wynajd\u017amy t\u0119 technologi\u0119, a dopiero p\u00f3\u017aniej obiecujmy wyborcom jej wdro\u017cenie, hmm?\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["anonimizacja","blockchain","fa\u0142szerstwo","g\u0142osowanie","informatyka","wybory"],"hasMore":true,"image":"https:\/\/avris.it\/image\/g\u0142osowanie-elektroniczne_small.jpg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/g\u0142osowanie-elektroniczne_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/g\u0142osowanie-elektroniczne_mini.jpg\u0022 alt=\u0022? Chcemy, \u017ceby jak najwi\u0119cej Obywateli mog\u0142o wzi\u0105\u0107 udzia\u0142 w wyborach i referendach. G\u0142osowanie elektroniczne to ju\u017c standard w zachodnich demokracjach. Czas i na Polsk\u0119! #KoalicjaObywatelska #Sz\u00f3stkaSchetyny\u0022 width=\u0022240\u0022 height=\u0022240\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EPlatforma Obywatelska obieca\u0142a, \u017ce wprowadz\u0105 g\u0142osowanie elektroniczne. Ta partia nie jest znana z realizowania obietnic, wi\u0119c nie boj\u0119 si\u0119 zbytnio, \u017ce ten okropny, okropny pomys\u0142 wejdzie dzi\u0119ki nim w \u017cycie. Ale temat mnie poruszy\u0142, bo widz\u0119, jak bardzo ludzie s\u0105 zafascynowani tak\u0105 opcj\u0105 i jak bezkrytycznie j\u0105 popieraj\u0105, my\u015bl\u0105c, \u017ce skoro wszystko inne jest lepsze dzi\u0119ki komputerom, to g\u0142osowanie te\u017c musi.\u003C\/p\u003E\n\u003Cp\u003EOt\u00f3\u017c wcale nie musi.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/g\u0142osowanie-elektroniczne_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/g\u0142osowanie-elektroniczne_mini.jpg\u0022 alt=\u0022? Chcemy, \u017ceby jak najwi\u0119cej Obywateli mog\u0142o wzi\u0105\u0107 udzia\u0142 w wyborach i referendach. G\u0142osowanie elektroniczne to ju\u017c standard w zachodnich demokracjach. Czas i na Polsk\u0119! #KoalicjaObywatelska #Sz\u00f3stkaSchetyny\u0022 width=\u0022240\u0022 height=\u0022240\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/twitter.com\/Platforma_org\/status\/1161551915093831680\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Etwitter.com\/Platforma_org\/status\/1161551915093831680\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EPlatforma Obywatelska obieca\u0142a, \u017ce wprowadz\u0105 g\u0142osowanie elektroniczne. Ta partia nie jest znana z realizowania obietnic, wi\u0119c nie boj\u0119 si\u0119 zbytnio, \u017ce ten okropny, okropny pomys\u0142 wejdzie dzi\u0119ki nim w \u017cycie. Ale temat mnie poruszy\u0142, bo widz\u0119, jak bardzo ludzie s\u0105 zafascynowani tak\u0105 opcj\u0105 i jak bezkrytycznie j\u0105 popieraj\u0105, my\u015bl\u0105c, \u017ce skoro wszystko inne jest lepsze dzi\u0119ki komputerom, to g\u0142osowanie te\u017c musi.\u003C\/p\u003E\n\u003Cp\u003EOt\u00f3\u017c wcale nie musi.\u003C\/p\u003E\n\u003Cp\u003ECho\u0107 na pierwszy rzut oka mo\u017ce si\u0119 tak wydawa\u0107, to wybory wcale nie s\u0105 z punktu widzenia informatyki na podobnym \u201cpoziomie trudno\u015bci\u201d co na przyk\u0142ad p\u0142atno\u015bci przez Internet. Ludzie my\u015bl\u0105, \u017ce skoro mog\u0105 z poziomu przegl\u0105darki bezpiecznie wys\u0142a\u0107 przelew na kilka tysi\u0119cy albo za\u0142atwi\u0107 spraw\u0119 urz\u0119dow\u0105, to czemu mia\u0142o by by\u0107 tak trudno za\u0142atwi\u0107 tam r\u00f3wnie\u017c i g\u0142osowanie?\u003C\/p\u003E\n\u003Cp\u003EW pierwszym przypadku g\u0142\u00f3wnym problemem do rozwi\u0105zania jest to, aby obie strony komunikacji (klient i bank, petent i urz\u0105d, itp.) mia\u0142y pewno\u015b\u0107 co do \u003Cstrong\u003Eto\u017csamo\u015bci\u003C\/strong\u003E rozm\u00f3wcy, oraz to, \u017ceby nikt postronny ich \u003Cstrong\u003Enie pods\u0142ucha\u0142\u003C\/strong\u003E. Te problemy rozwi\u0105zali\u015bmy ju\u017c dawno i wci\u0105\u017c udoskonalamy nasze rozwi\u0105zania.\u003C\/p\u003E\n\u003Cp\u003ENatomiast w przypadku g\u0142osowania dochodzi do tego kolejny element: gdy ju\u017c upewnimy si\u0119, \u017ce naprawd\u0119 rozmawiamy z Janem Kowalskim, i \u017ce Jan Kowalski ma prawo do g\u0142osu, i \u017ce jeszcze swojego g\u0142osu nie odda\u0142, musimy zapewni\u0107 mu pe\u0142n\u0105 anonimowo\u015b\u0107. Nie mo\u017cemy wiedzie\u0107, jak Jan Kowalski zag\u0142osowa\u0142. \u003Cstrong\u003EProfil Zaufany\u003C\/strong\u003E zapewni nam pierwsz\u0105 cz\u0119\u015b\u0107, ale nie drug\u0105. Tak samo wszystkie inne \u003Cem\u003Ebuzz words\u003C\/em\u003E, kt\u00f3re s\u0142ysza\u0142em od zwolennik\u00f3w pomys\u0142u: rozpoznawanie twarzy, odcisk\u00f3w palca, a przede wszystkim ten mityczny \u003Cem\u003Eblockhain\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EBlockchain\u003C\/strong\u003E, moi drodzy, jest w gruncie rzeczy bardzo skomplikowan\u0105 i bardzo woln\u0105 \u003Cem\u003Ebaz\u0105 danych\u003C\/em\u003E. Nie rozwi\u0105zuje problem\u00f3w z elektronicznym g\u0142osowaniem. Przede wszystkim dlatego, \u017ce z definicji jest weryfikowalny. \u003C\/p\u003E\n\u003Cp\u003EA Konstytucja gwarantuje \u003Cstrong\u003Etajno\u015b\u0107\u003C\/strong\u003E wybor\u00f3w. I bardzo dobrze!\u003C\/p\u003E\n\u003Cp\u003ENie chodzi tu o to, \u017ce wstydz\u0119 si\u0119 mojego g\u0142osu i wola\u0142bym, \u017ceby nikt o nim nie wiedzia\u0142. Chodzi o integralno\u015b\u0107 ca\u0142ego procesu.\u003C\/p\u003E\n\u003Cp\u003EGdyby wybory tajne nie by\u0142y, otworzy\u0142oby to furtk\u0119 dla r\u00f3\u017cnej ma\u015bci matactw: kupowania g\u0142os\u00f3w, zastraszania wyborc\u00f3w, etc. Nie mo\u017cna natomiast zmusi\u0107 kogo\u015b do zag\u0142osowania w konkretny spos\u00f3b, je\u017celi nie ma si\u0119 fizycznej mo\u017cliwo\u015bci sprawdzenia, jak ten kto\u015b zag\u0142osowa\u0142.\u003C\/p\u003E\n\u003Cp\u003EProblemem jest r\u00f3wnie\u017c to, \u017ce wybory elektroniczne s\u0105 zdecydowanie \u003Cstrong\u003E\u0142atwiejsze do sfa\u0142szowania\u003C\/strong\u003E. To, \u017ce tobie jest wygodniej zag\u0142osowa\u0107 nie ruszaj\u0105c si\u0119 z domu, znaczy te\u017c, \u017ce fa\u0142szerzowi wygodniej jest fa\u0142szowa\u0107 \u2013 on te\u017c nie musi si\u0119 rusza\u0107 z domu.\u003C\/p\u003E\n\u003Cp\u003E\u017beby sfa\u0142szowa\u0107 tradycyjne wybory, trzeba du\u017cego nak\u0142adu \u015brodk\u00f3w. \u017beby sfa\u0142szowa\u0107 wybory elektroniczne, w najgorszym wypadku wystarczy jedna luka w zabezpieczeniach jednego serwera, wykorzystana zdalnie z drugiego ko\u0144ca \u015bwiata.\u003C\/p\u003E\n\u003Cp\u003EW tradycyjnym g\u0142osowaniu masz fizyczne lokale wyborcze, ludzi b\u0119d\u0105cych na miejscu, r\u0119cz\u0105cych za poprawno\u015b\u0107 g\u0142osowania i liczenia g\u0142os\u00f3w, a przede wszystkim kontroluj\u0105cych si\u0119 nawzajem.\u003C\/p\u003E\n\u003Cp\u003EW g\u0142osowaniu elektronicznym natomiast masz system informatyczny, kt\u00f3ry dla wyborcy jest raptem czarn\u0105 skrzynk\u0105 kontrolowan\u0105 przez rz\u0105d. Czy serio by\u015b mu ufa\u0142?\u003C\/p\u003E\n\u003Cp\u003EWyobra\u017a sobie \u017ce PiS otwiera \u201cniezale\u017cn\u0105\u201d central\u0119 telefoniczn\u0105, w kt\u00f3rej \u201cniezale\u017cni\u201d telefoni\u015bci zbieraliby od ludzi g\u0142osy bez wychodzenia z domu. Uzna\u0142by\u015b to za wygodny spos\u00f3b g\u0142osowania czy raczej za wygodny spos\u00f3b sfa\u0142szowania wyniku?\u003C\/p\u003E\n\u003Cp\u003EGdy doda\u0107 do tego komputery, wci\u0105\u017c dzia\u0142a\u0142oby to mniej wi\u0119cej tak samo. Po prostu istnia\u0142aby opcja zweryfikowania twojej to\u017csamo\u015bci, natomiast nie by\u0142oby opcji, \u017ce kto\u015b pods\u0142ucha konwersacj\u0119 mi\u0119dzy tob\u0105 a central\u0105. Kwestia braku zaufania do centrali wci\u0105\u017c pozostaje nierozwi\u0105zana. Tak samo jak kwestia potencjalnego pistoletu przystawionego do twojej skroni, by\u015b zaznaczy\u0142 odpowiednie pole na ekranie.\u003C\/p\u003E\n\u003Cp\u003EG\u0142osowania elektroniczne ju\u017c mia\u0142y miejsce w kilku krajach na \u015bwiecie. Najg\u0142o\u015bniejszym przyk\u0142adem jest chyba Estonia, w kt\u00f3rej eksperyment ten okaza\u0142 si\u0119 by\u0107, surprise surprise, fiaskiem: \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Electronic_voting_in_Estonia#Criticism\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Wikipedia\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/estoniaevoting.org\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E estoniaevoting.org\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003ENie w\u0105tpi\u0119, \u017ce kiedy\u015b uda si\u0119 informatykom wymy\u015bli\u0107 system, w kt\u00f3rym integralno\u015b\u0107 wybor\u00f3w b\u0119dzie r\u00f3wnie (lub bardziej) bezpieczna co w przypadku tradycyjnych g\u0142osowa\u0144. Ale ten dzie\u0144 jeszcze nie nast\u0105pi\u0142. W 2019 roku nie mamy technologii by przeprowadzi\u0107 wybory elektroniczne, kt\u00f3re spe\u0142nia\u0142yby standardy demokratyczne i odpowiednie standardy bezpiecze\u0144stwa.\u003C\/p\u003E\n\u003Cp\u003ECo nast\u0119pne? Platforma obiecuj\u0105ca wszystkim \u201cteleporter w ka\u017cdym domu\u201d?\u003C\/p\u003E\n\u003Cp\u003EMam taki pomys\u0142: mo\u017ce najpierw wynajd\u017amy t\u0119 technologi\u0119, a dopiero p\u00f3\u017aniej obiecujmy wyborcom jej wdro\u017cenie, hmm?\u003C\/p\u003E","words":780,"readTime":4,"lang":"pl"}}},"blog\/technology\/log-out-for-privacy":{"key":"blog\/technology\/log-out-for-privacy","type":"article","published":true,"meta":{"createdAt":"2019-07-29T11:58:57+02:00","publishedAt":"2019-07-29T11:57:00+02:00","group":"tech-breakups","category":"blog","subcategory":"technology","slug":"log-out-for-privacy"},"content":{"en":{"slug":"log-out-for-privacy","title":"Log out for privacy","intro":"\u003Cp\u003EAn image search brought be to Pinterest, which automatically\u2026 logged me in to an old account, I didn\u2019t even remember I had. I definitely never logged in on this browser.\u003C\/p\u003E\n\u003Cp\u003EThey just logged me in without asking. WTF?!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cp\u003EAn image search brought be to Pinterest, which automatically\u2026 logged me in to an old account, I didn\u2019t even remember I had. I definitely never logged in on this browser.\u003C\/p\u003E\n\u003Cp\u003EThey just logged me in without asking. WTF?!\u003C\/p\u003E\n\u003Cp\u003ESeems like they use a \u201cLogin with Facebook\u201d button as a script that shares cookies with the facebook.com domain, basically giving them access to each other and letting a third-party website know my FB account before I use it to log in!\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve \u003Ca href=\u0022fuck-you-facebook\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E stopped using FB\u003C\/a\u003E over two years ago, removed most of my personal data, and I only go there when I need to contact someone and have no other option.\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve only now realised that\u2019s not nearly enough to protect my privacy. FB keeps lurking on you even on unrelated websites.\u003C\/p\u003E\n\u003Cp\u003ESo I\u2019ve \u003Cstrong\u003Elogged out\u003C\/strong\u003E of Facebook. And \u003Cstrong\u003Eremoved all their cookies\u003C\/strong\u003E. And removed the damn Pinterest account.\u003C\/p\u003E\n\u003Cp\u003EAnd after I move some stuff out of Google ecosystem, I\u2019m going to log out from it as well. They\u2019re even worse at respecting user\u2019s privacy \ud83e\udd2e\u003C\/p\u003E\n\u003Cp\u003EAll the giants thinking you have a right to track me wherever I go online: fuck you all \ud83d\udd95\ud83d\udd95\ud83d\udd95\ud83d\udd95\ud83d\udd95\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["ads","cookies","facebook","google","privacy","tracking"],"hasMore":true,"image":null,"introLite":"\u003Cp\u003EAn image search brought be to Pinterest, which automatically\u2026 logged me in to an old account, I didn\u2019t even remember I had. I definitely never logged in on this browser.\u003C\/p\u003E\n\u003Cp\u003EThey just logged me in without asking. WTF?!\u003C\/p\u003E","contentLite":"\u003Cp\u003EAn image search brought be to Pinterest, which automatically\u2026 logged me in to an old account, I didn\u2019t even remember I had. I definitely never logged in on this browser.\u003C\/p\u003E\n\u003Cp\u003EThey just logged me in without asking. WTF?!\u003C\/p\u003E\n\u003Cp\u003ESeems like they use a \u201cLogin with Facebook\u201d button as a script that shares cookies with the facebook.com domain, basically giving them access to each other and letting a third-party website know my FB account before I use it to log in!\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve \u003Ca href=\u0022fuck-you-facebook\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E stopped using FB\u003C\/a\u003E over two years ago, removed most of my personal data, and I only go there when I need to contact someone and have no other option.\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve only now realised that\u2019s not nearly enough to protect my privacy. FB keeps lurking on you even on unrelated websites.\u003C\/p\u003E\n\u003Cp\u003ESo I\u2019ve \u003Cstrong\u003Elogged out\u003C\/strong\u003E of Facebook. And \u003Cstrong\u003Eremoved all their cookies\u003C\/strong\u003E. And removed the damn Pinterest account.\u003C\/p\u003E\n\u003Cp\u003EAnd after I move some stuff out of Google ecosystem, I\u2019m going to log out from it as well. They\u2019re even worse at respecting user\u2019s privacy \ud83e\udd2e\u003C\/p\u003E\n\u003Cp\u003EAll the giants thinking you have a right to track me wherever I go online: fuck you all \ud83d\udd95\ud83d\udd95\ud83d\udd95\ud83d\udd95\ud83d\udd95\u003C\/p\u003E","words":201,"readTime":null,"lang":"en"}}},"blog\/technology\/recognising-red-flags-in-blackmail-emails":{"key":"blog\/technology\/recognising-red-flags-in-blackmail-emails","type":"article","published":true,"meta":{"createdAt":"2019-01-24T11:50:02+01:00","publishedAt":"2019-01-24T11:46:00+01:00","group":null,"category":"blog","subcategory":"technology","slug":"recognising-red-flags-in-blackmail-emails"},"content":{"en":{"slug":"recognising-red-flags-in-blackmail-emails","title":"Recognising red flags in blackmail emails","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/lame-hacker_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022311.19402985075\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAXCAYAAABj7u2bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADxklEQVRIiY1WzUorMRg9ycQZamtFEMSF+AeFStdqwb0+gFvfwnfQJ3CvCxddu3GjbkQoxYWCoKggrQoig9ramU5mkru4N7lpnGn9YJi\/5Dsn5\/tJSBRFEgAIIZBSghACZVLK1Gf1LqXE3t4earUaoihCkiRgjOHw8BDz8\/Pal+nTfLaNEAJmf7SBTXB7jJQSy8vLKJfLKBaLCIIAzWYTrVYLc3NzqYCmH5uclBJEKZRlJpm0O2MMjDH0ej1wztHr9dDpdDA9Pa1BbaUGKcbMUJn3NDJphG5ubjAyMgIAeHh4QKFQwMzMDIQQQ8OjVTGIsrQQZamURrBUKsFxHABALpeD67pgjKWGXoGqf2mkqC3pIHXUJYTQ1\/f3N5IkQRiG4JwDAPL5fN8YIcSPBZlKm+\/0N+rYSplAz8\/PODg4gJQSnuehVqshjmMkSYIkSfrI2ItLVZBzLk1AG1wRMImEYYj393f4vo+joyNcXV0hjmNwztFut1GpVFCtVlGtVjE7OwvGGAghoJTqJM9K9qGEbDLX19fY2dlBp9MBpRRSSl1dlFJQSsEY0wBra2vY3t6G67p9hCil\/0kYhH6ELK0yFLkwDLG\/v4\/Pz08kSQIpJaIo0k4dx\/lRrWdnZzg\/P9cLM32mYVFbsiyTUuLi4gLNZhPFYhFCCCRJoiuMMaYVUsBJkiCOY9Tr9cyGawvB0kKVRajRaGBiYgIrKytgjKHb7cJxHB0KdWeMaaL39\/e4u7vL9GvjMrMXKKZp5fj4+Ijb21uUSiWsr6+nVpEKg5209Xp9KBk1Xu9ldpOySV1eXoJzjq+vL0gpMwkpX0qtIAgQRRGiKNIdfZD9qg9xznF6eoq3tzd0Op0flWcmrN1zgiAAAAghhpLRjdEOm\/kNAE5OTiCEwNTUFMbGxkAISa0ak4giEIYhAOheNIiMlPJ\/Dg2yl5cX5PN5eJ4Hz\/MynZm5oCwIgr5qtHPMxqd27E1TE8rlMrrdLqIoQrvd1rkjhEAcx\/j4+NDAqh0ohbrdrn7OWryp9I8DWtohanV1FYVCAYQQ9Ho97O7uAgDGx8dBKcXCwgJyuRyenp7gOA6Oj4\/\/rvZf115aWtIJbStjN8i+kGX1CkopKpWKVkQIgSAI4Ps+giBAo9HA6OgoJicn8fr6+jc5KYXnedjc3MTGxoauOnvxtjH7gGS+230FADjnfXuVGuf7Pnzf76sm13WxtbUF13Uz88bG\/FVSm5NbrZbeSE1l0xLaXtQwdYAhfShtUhRFkFLqM4\/aKuw5hBAsLi7q6lLfhgnwB8uPNwrCWTIsAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/lame-hacker_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022311.19402985075\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDid anyone receive a message recently that contained a video of me watching porn? \ud83d\ude06\u003C\/p\u003E\n\u003Cp\u003EBecause apparently I was being blackmailed that all my contacts would receive it, if I don\u2019t pay 202\u20ac in BTC. Alas, I didn\u2019t check the spam folder, so I\u2019d missed the deadline a week ago \ud83e\udd37\u200d\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/lame-hacker_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022622.38805970149\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAXCAYAAABj7u2bAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADxklEQVRIiY1WzUorMRg9ycQZamtFEMSF+AeFStdqwb0+gFvfwnfQJ3CvCxddu3GjbkQoxYWCoKggrQoig9ramU5mkru4N7lpnGn9YJi\/5Dsn5\/tJSBRFEgAIIZBSghACZVLK1Gf1LqXE3t4earUaoihCkiRgjOHw8BDz8\/Pal+nTfLaNEAJmf7SBTXB7jJQSy8vLKJfLKBaLCIIAzWYTrVYLc3NzqYCmH5uclBJEKZRlJpm0O2MMjDH0ej1wztHr9dDpdDA9Pa1BbaUGKcbMUJn3NDJphG5ubjAyMgIAeHh4QKFQwMzMDIQQQ8OjVTGIsrQQZamURrBUKsFxHABALpeD67pgjKWGXoGqf2mkqC3pIHXUJYTQ1\/f3N5IkQRiG4JwDAPL5fN8YIcSPBZlKm+\/0N+rYSplAz8\/PODg4gJQSnuehVqshjmMkSYIkSfrI2ItLVZBzLk1AG1wRMImEYYj393f4vo+joyNcXV0hjmNwztFut1GpVFCtVlGtVjE7OwvGGAghoJTqJM9K9qGEbDLX19fY2dlBp9MBpRRSSl1dlFJQSsEY0wBra2vY3t6G67p9hCil\/0kYhH6ELK0yFLkwDLG\/v4\/Pz08kSQIpJaIo0k4dx\/lRrWdnZzg\/P9cLM32mYVFbsiyTUuLi4gLNZhPFYhFCCCRJoiuMMaYVUsBJkiCOY9Tr9cyGawvB0kKVRajRaGBiYgIrKytgjKHb7cJxHB0KdWeMaaL39\/e4u7vL9GvjMrMXKKZp5fj4+Ijb21uUSiWsr6+nVpEKg5209Xp9KBk1Xu9ldpOySV1eXoJzjq+vL0gpMwkpX0qtIAgQRRGiKNIdfZD9qg9xznF6eoq3tzd0Op0flWcmrN1zgiAAAAghhpLRjdEOm\/kNAE5OTiCEwNTUFMbGxkAISa0ak4giEIYhAOheNIiMlPJ\/Dg2yl5cX5PN5eJ4Hz\/MynZm5oCwIgr5qtHPMxqd27E1TE8rlMrrdLqIoQrvd1rkjhEAcx\/j4+NDAqh0ohbrdrn7OWryp9I8DWtohanV1FYVCAYQQ9Ho97O7uAgDGx8dBKcXCwgJyuRyenp7gOA6Oj4\/\/rvZf115aWtIJbStjN8i+kGX1CkopKpWKVkQIgSAI4Ps+giBAo9HA6OgoJicn8fr6+jc5KYXnedjc3MTGxoauOnvxtjH7gGS+230FADjnfXuVGuf7Pnzf76sm13WxtbUF13Uz88bG\/FVSm5NbrZbeSE1l0xLaXtQwdYAhfShtUhRFkFLqM4\/aKuw5hBAsLi7q6lLfhgnwB8uPNwrCWTIsAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/lame-hacker_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022622.38805970149\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/unsplash.com\/photos\/HJENWbX4t-Q\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        unsplash.com\/photos\/HJENWbX4t-Q\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDid anyone receive a message recently that contained a video of me watching porn? \ud83d\ude06\u003C\/p\u003E\n\u003Cp\u003EBecause apparently I was being blackmailed that all my contacts would receive it, if I don\u2019t pay 202\u20ac in BTC. Alas, I didn\u2019t check the spam folder, so I\u2019d missed the deadline a week ago \ud83e\udd37\u200d\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/alto-pericolo-1_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022968.51063829787\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAkCAYAAAAD3IPhAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFh0lEQVRYhcWYu25jyRGGv+5z5yFFjsQh55ZIyUQOPX4FJxsvnDkxdrAbLeDIgBM\/zryDF04cGI7mEQxhAArSkBLZPLfuPscBt1skRUnjXXm3AII8t67\/VP31VzXFcrns4jjm17aiKAijKCIIAoIgQAjxizi21lLXNUIIrLUkSUIURYQAVVXRNA3D4XDnISnl\/wVg27YURYEQgq7rsNZuglGWZXdzc8OnT58QQrBarTg6OkJKydu3b4nj2D906NvZ9nHXdQAPHu+voZTagDHGcIg3YRgipXzyyBwypdQmTUEQ3HuTe6unMBeN+ywEWC6XD6bpqeyxFxNlWXYuMg65+0RRdDDP2\/cKIe6QfJsL1tqDa0gpadsWKSXWWqqq2ETm+vqGuq6w1tJ1HVmW+d\/GGKSUSCn9YlVVEUURWmtOT08fJPSHDx8IwxAAYwzT6RSlFHEcs1gsGI\/HfPz4kffv32\/AZAiyLMc2DWGS0FQV\/ZMxYRzdicJ+hLbDfygN79698xpmjCFJEoqiYDAYcH19zcnJCS9fvrxNU5IkT0rUn2I3NzebyFxdXTGfz5lOp4xGo18FzOXl5QbMeDxmPB4DT1vK\/4s1TYOEDbG2bZ8DjsywkfLta23b0nWdP79vrtoe+8CPOqOUYj6fkyQJ6\/XaV1NZlkwmE4qi8IsrpRiNRjRN44EYY8jzHCEESimiKKLrOk5PT+8Ae1T0XDu4vr72gAaDgT\/nNCGOY7IsY7Va0e\/3qevaS4HWGtik\/Pj4+KCzxyjgOSOEYDqdEkW35ewW2Ba3+xrlIaf3NdL7zHfBfcU9tOghPXlIY\/bveeyZEDZlVZYlQgiKovCdOggC2rbdiVbTNPR6PV69evVFgL4UiAcTxzHr9Zo8z0mShLquSdMU2IyDWZZRVZXnRxAEXF5eUlUVAL1ej+VySZqmdF1HHMe0bYu1ljiOqarKrxuGIXVdk2UZSZJwdHS0C6bX6\/nRc7uBdV3nrw2HQ4wxnjthGNI0jf+dpunOZOg4Yq0lyzKklP5Fuq7zvpwlSbJpB0opFosF1lrOzs58Wn5Ju7q62kSmaRrSNEVrzWw2Q2uNMcbrSJ7nPlru2rNnz1BKYYzx6Tg7O\/tZk2ForfUpALzTIAiw1gK3lebucanJsoymaQBI09TrjrXWp9SND27s2E5fmqb0er1bMEophsMhZVn6GcVxpW1btNZ+QHKE7bqOJEn8Iq7KAD8sOeBOp9q2pW1bqqpCCEEQBBhjdvQnBFitVlRVxfn5Of1+H2OMV1SllHe4WCyQUpLnOfP5nMFgsFNtQRCQJMnOvqhtW9I0RQjhW47W2gOqqorJZLLxMZvNuiiKUErRti1hGDIYDFgulztE1loTBAFaayaTiXdwSJF\/ylbFjxDD4ZA8z71jKaV35krcWksYhmitPch9AfuS8eNR0ZNSProLcER8aFtzn+P7jvfPhQCz2Yy2bSnLEmMMvV7Pl\/BgMKBpGuq6pt\/vU1UVWZahlKIsS16\/fs3nz5+J49iT1nGprmviOKZpGuI4ZjKZ0O\/3739hgBcvXnzx2x6yk5OTn\/X8Dhi4O\/js75Hg7t5p2w7d\/5gd7NoXFxesViustYxGI5RSpGnKer324uZKWGtN0zS+t4RhyHq99k30+fPnO8XwkJ3\/81\/84y9\/4zd\/\/ANvvvr9prSNMdR17Us7z3NWqxVZlrFer2nbljzP0Vqjtabf71OWJWEY+sZXFIX\/n8WJpatExxtXha59\/P2b79GLG1b\/Oefrf\/9wO+k51UySBCEEeZ4jpeT4+NgrqOtNURR5oXIzsDGGLMt2UuDAAH4s2U7l7777Ez\/8+a\/89vtvEQLExcVFt16v0VoThiFlWXqp3m56QgivykEQ8ObNmyf9u2Q+n\/NfSjbh4azYjuYAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/alto-pericolo-1_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022968.51063829787\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/alto-pericolo-2_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022955.6678700361\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAjCAYAAAD8BaggAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGCUlEQVRYhb2Xy24byxGGv+7puZO0aFmGBQPx0gu\/W5Z5iLxBVnmM8xLZnCykhQ0b9ka27hQ54vRMX85CrgZJS5bik6QAQlRPsae6\/qq\/\/lYhhOicQykFgDGGGCPee4wxeO\/RWqOUIoSAUgql1JYPQAiBGCNKKbz35Hm+tRZCIMsyQgiEEDDGpDXxubi4wMQY+fz5M0VRYK2laRqMMdzc3FDXNeM4YozBWkuMkaqqGMcR5xwvXrzg4uJi64VVVdF1HWVZYq2lrmustXjvaduWrusoigKlFMMwUBQFRVGQ5zla67uAYoys12vyPOfy8pLZbMYwDBhjUErhnKOqKlarFeM4kmUZAGdnZ5RlyTAMKTOHh4dorRGT02\/a7tpmhpT3Pi4WC\/I8B2AcR\/I8x1qbAlJKobXGOUeWZTjnErzDMKQAvfcopSjLknEcGceRsiyJMaYgZf8YY\/KZTCZkWUbXdRhJt\/ceyZb3Hu89WZYleKQmpJ7GcQTAWotSiqqqtvaRfcdxTPsK9GJSYwIdgAkhcH5+ToyR6XTKYrGgKArKsuTg4ODBdMcYAdjb23sSHE\/x6fseA5BlGWVZkuc5k8kE7z1lWfLly5cETQgh\/biua7z3dF1HXddorVM2tNYJFjm1955xHFPWJJvOOUIIvHnzJgWnQgjRWruFrUQsG+R5nupj83QCodZ6K\/USvPjJc+896\/WaqqrSOkBZlgBcXl7eQfbp06etVpxOp+nEr169Is\/zVPSbkO1CURTFo5DVdf1THxVCiLsbP4T9YwH9rD6e4nNxcXFXQ1+\/fmU6nabOkS4zxpDnOc65RJDCS5tM672n73tmsxnC+jFGrLWUZZm6Umv9A6TOOebzeQpOC0dIy2ZZllpZPtba9GKps82RorVOgW82gNSevFzWhQoA+r5PWQohoJxz8ePHjyilyPOccRyZTqesVivKsiSEgLWWvu85ODhgHEestYmbuq6jaRqqqmI+n9M0zS9DdnR0hIoS6hPtf1lDR0dHd7NM6F\/mkVIqQZfnOUoplsslWZahtU6+MkakVgSOqqoSIwst9H1PVVVp4mutU+0VRUFd1wB3RX1+fo61Nm0UY6RpGpbLJVprmqbBe0\/TNFhr6boOgOl0StM0jOPI9fU1dV2zWCwwxqS98jzHGINzjqurK4wxaYR475OfBPQfQ\/aY\/WnIQgicnp4mTSKyQ9pXukYGoXyapmG1WiUIZKoLW8v6OI4URcF6vSbLsrSfUoq6rhPUkhcNpACkLY0xScmJc9d1xBjJsmwrCOGWzbrapAxRoGmafw8otbkwtChWgPV6zTAMLBYL6rpmvV5zc3ND27ZcX1\/Tti37+\/tpsm9O+4fsZz5t2\/7gI39NjJHVasV8Pufm5iZ1TNu2GGPY29uj73uWyyUnJyc0TUPbtiyXS+BuMDrnEgF679NvnHNJHUiXibx5+fIlk8nkh\/pSIYQoqZMWFEoXohRFKKeStt00WRPmvy87m2y9qRLEjo+P7xSjvLBpmvRQ1qToNm0zwJ+t3We7B9nNkPHe8\/79+y3t0rZtGhnCEfLC9XqNc47ZbMZqtUJrzWw2S0Qog1Tkr8w7Ywy3t7dpYPd9n4SeXKWAO5F\/dnYG8IMQK4oibbp7v7LWpqEqTN+2bRJf9xX17tru\/8fHx3ddJuJLOky4RqCQ53L6TRmSZVlq6ftm20PQPGQmxsjJyQnz+ZyrqytijDjnqOua5XKJUopnz57x\/PnzFOR9JwUepYInBaS15t27d\/du+BS++W+bAba0j9TJJsVL1gQqIEEntqWLv\/9G6m0Yhi1NHkLYqk95Bt8hOz09pW3b1AUiM+UK3ff9lgqUq3Nd19ze3iLkenBwgLWWyWTC9fV1UgrCb0KowzDQti3DMNA0zZaENTIAl8tluqXKzSDPc759+4ZSiqIoMMZweHj4pBra39+\/12c6nW6t7ZaEybKMt2\/fbqX9vuL9lXr6lZmnN0\/2Zwv4Ka39mI8JIfDhwwecc+zt7fH69ev\/exBbFkKIMcb4fcj+0vdN2117zOdf\/\/hn\/Puzv8Tf\/vq3+Pvv\/45\/AI6OU9eu93mSAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/alto-pericolo-2_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022955.6678700361\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EIf they really had full access to my computer, they\u2019d know that I almost never use Italian... Only to talk to some old friends once in a blue moon, and to laugh at all the spammers who assume that owning a \u201c.it\u201d domain automatically makes you Italian.\u003C\/li\u003E\n\u003Cli\u003EIf they really had full access to my computer, or even checked out my public posts on social media, they\u2019d know I don\u2019t give a shit about someone seeing me naked or masturbating.\u003C\/li\u003E\n\u003Cli\u003EBlackmailing someone with that is the most obvious choice: almost everyone watches porn \u0026amp; masturbates, and most people are (inexplicably) ashamed of it.\u003C\/li\u003E\n\u003Cli\u003EThey didn\u2019t attach ANY proof whatsoever. Not a piece of a video, not a single URL from browser history, not a screenshot. Not even naming my OS or browser. I have no idea, which of my computers they claim to have attacked \ud83d\ude06\u003C\/li\u003E\n\u003Cli\u003ESending an email from my own address to myself is given as a \u201cproof\u201d that they control my computer. The thing is, via SMTP you can send an email with ANY valid email in the \u201cFrom\u201d field. Most clients will deem it unreliable though and put it in spam \u2013 exactly as has happened here.\u003C\/li\u003E\n\u003Cli\u003EThey claim to have been \u201cobserving me for a couple of months\u201d. Well, to get enough porn \u0026amp; masturbation blackmail material on me, they wouldn\u2019t need more than a day \ud83e\udd2d\u003C\/li\u003E\n\u003Cli\u003E\u201cMalware was undetectable by the antivirus, because driver\u201d is a BS talk for people who don\u2019t know shit about computers. They\u2019ve been watching me for months, they should know I know my shit about computers \ud83d\ude06\u003C\/li\u003E\n\u003Cli\u003EMost importantly: the deadline is over already. And nothing? \u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EDespite so many red flags people seem to be buying this bullshit, apparently. Those criminals \u003Ca href=\u0022https:\/\/www.blockchain.com\/btc\/address\/17YKd1iJBxu616JEVo15PsXvk1mnQyEFVt\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E have received 4,5 BTC\u003C\/a\u003E already (~14k\u20ac). Within A WEEK!\u003C\/p\u003E\n\u003Cp\u003EPlease, educate yourself about cybersecurity, people... And don\u2019t panic! \ud83d\ude42\u003C\/p\u003E\n\u003Ch3\u003EUpdate\u003C\/h3\u003E\n\u003Cp\u003EI just got a report of a scam attempt that \u003Cem\u003Edid\u003C\/em\u003E include a \u201cproof\u201d, so let\u0027s take a look at it:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/lame-hacker-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022479.22829581994\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACg0lEQVRIicWW227jOBBED++WbASw\/ZD\/\/8G1NpYsiiLZ8+AVJ\/EmwSQ7gy1AoCQ2ms1SdVEqTpO8TBOlFJxz5JxxzmGtJedMjBGA\/X5PrRURodYKgLWWdV3RWgOQUkIphfeeeZ4xxhBCIKUEQM4Z7z1KKbTWiAin04kNSinUOkcxwfO7oZRCRL4Uo5TCxhgZhwvee47H428v7CsQEayzFhEhpcQwDIzjyOFwIOd8p1CpFhxjJISA956cMykldrtdSzhNE845jDF477ndbux2O0opwJ2BZVl4enpiGAb2+31jaFmW+6dcc24Jtdbs93tSSpRSWjG11lacMYZxHAHaYjFGRATnHF3XcTqdyDmjtSbn3K51XQHaxqZpQinFuq6EEO5rztdRTLgLrdbaxKa1ppSC91\/Xl4g0fWyb+lVYRBiGoXWYtbZNOue+VdCv4LHobVQvf10k1UIp5V9dEUJo1G9zKSW6rmNZFowxlFLQWrf2L6U0DQGN9WVZCCGglGKe56a9WisxRrquA0At002Usxhj3iz8SPnj+49i3tv1e3kec23P9uXlhWmJXC4X+r7neDw2A2w0\/iPm4\/HYTPB18tdJH1l+L+Yz6BA83nuen58JIbAsC9ba1mlwd9i+798U8ycgIn\/Oqb8Le7vdWKeR8\/n8f9cCgBqHvyXmu2FtujHGsK4r1lpijHjvMcYgIszzTNd1lFKotWKMwVrL9XrlcDhQa8Va+6ZrnXOklFjXtbn8tsbWbUqpu+3AT8sXEbz3LZmIEEJoR0sphb7v22nf9z3TNAE\/\/wZyzpzP528bo5qvVxFjmg98hvda\/LO4r8Rso1bGkF+dZxsz2\/1Hyf4LPrIGgB8oZ+fP826JzAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/lame-hacker-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022479.22829581994\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYes, the attacker knows your password. But they don\u0027t tell you to which service\nthis password grants access to, which is pretty weird...\nIf I were an asshole and had that information, I\u0027d use it:\nat least to further prove to you that I know private shit about you,\nat worse to log in to that account, take it over and demand money for giving it back.\nAnd yet, they didn\u0027t. Suspicious.\u003C\/p\u003E\n\u003Cp\u003EBut anyways... if you go to the \u003Ca href=\u0022https:\/\/haveibeenpwned.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u0027;--have i been pwned?\u003C\/a\u003E website\nand enter your email, you\u0027ll see the list of data breaches over the years where your email was found.\u003C\/p\u003E\n\u003Cp\u003EThis guy\u0027s email was in 18 of them. Some were connected to the same reused password.\nSo here\u0027s how the attacker knew his password: he didn\u0027t hack his computer or gain access to his camera,\nhe just found it (or bought it) on some shady website.\nThe attacker probably doesn\u0027t even know what service was this password for or whether it\u0027s even still valid.\u003C\/p\u003E\n\u003Cp\u003EGood news about this attack: as of today, not a single cent was sent to\n\u003Ca href=\u0022https:\/\/www.blockchain.com\/btc\/address\/bc1qrpmrkdwh2uhnmrsj0803hg909m66rp6ax7y7je\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E that BTC address\u003C\/a\u003E \ud83c\udf89\u003C\/p\u003E\n\u003Cp\u003ESo what\u0027s the takeaway?\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EEven if someone knows your password, it doesn\u0027t automatically prove their other claims.\u003C\/li\u003E\n\u003Cli\u003ESign up for email updates from \u003Ca href=\u0022https:\/\/haveibeenpwned.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u0027;--have i been pwned?\u003C\/a\u003E\nand whenever they notify you about a breach, go to that website and change your password.\u003C\/li\u003E\n\u003Cli\u003EDon\u0027t reuse passwords! The best way to stay secure is to use a different, strong, random password for each service\nand store them in a password manager, like \u003Ca href=\u0022https:\/\/keepass.info\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E KeePass\u003C\/a\u003E or even a browser.\nIf someone told me, they know that my password is \u003Ccode\u003EhiVxV788S2dm8rK6P5qH\u003C\/code\u003E?\nBitch, even \u003Cem\u003EI\u003C\/em\u003E don\u0027t know that\u0027s my password \ud83e\udd37\u200d\u003C\/li\u003E\n\u003Cli\u003EDon\u0027t panic! The vast majority of such attacks is just a bluff.\u003C\/li\u003E\n\u003C\/ul\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["bitcoin","blackmail","cybersecurity","email","masturbation","porn","security"],"hasMore":true,"image":"https:\/\/avris.it\/image\/lame-hacker_small.jpg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/lame-hacker_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/lame-hacker_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022155.59701492537\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDid anyone receive a message recently that contained a video of me watching porn? \ud83d\ude06\u003C\/p\u003E\n\u003Cp\u003EBecause apparently I was being blackmailed that all my contacts would receive it, if I don\u2019t pay 202\u20ac in BTC. Alas, I didn\u2019t check the spam folder, so I\u2019d missed the deadline a week ago \ud83e\udd37\u200d\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/lame-hacker_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/lame-hacker_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022155.59701492537\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/unsplash.com\/photos\/HJENWbX4t-Q\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Eunsplash.com\/photos\/HJENWbX4t-Q\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDid anyone receive a message recently that contained a video of me watching porn? \ud83d\ude06\u003C\/p\u003E\n\u003Cp\u003EBecause apparently I was being blackmailed that all my contacts would receive it, if I don\u2019t pay 202\u20ac in BTC. Alas, I didn\u2019t check the spam folder, so I\u2019d missed the deadline a week ago \ud83e\udd37\u200d\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/alto-pericolo-1_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/alto-pericolo-1_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022242.12765957447\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/alto-pericolo-2_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/alto-pericolo-2_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022238.91696750903\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EIf they really had full access to my computer, they\u2019d know that I almost never use Italian... Only to talk to some old friends once in a blue moon, and to laugh at all the spammers who assume that owning a \u201c.it\u201d domain automatically makes you Italian.\u003C\/li\u003E\n\u003Cli\u003EIf they really had full access to my computer, or even checked out my public posts on social media, they\u2019d know I don\u2019t give a shit about someone seeing me naked or masturbating.\u003C\/li\u003E\n\u003Cli\u003EBlackmailing someone with that is the most obvious choice: almost everyone watches porn \u0026amp; masturbates, and most people are (inexplicably) ashamed of it.\u003C\/li\u003E\n\u003Cli\u003EThey didn\u2019t attach ANY proof whatsoever. Not a piece of a video, not a single URL from browser history, not a screenshot. Not even naming my OS or browser. I have no idea, which of my computers they claim to have attacked \ud83d\ude06\u003C\/li\u003E\n\u003Cli\u003ESending an email from my own address to myself is given as a \u201cproof\u201d that they control my computer. The thing is, via SMTP you can send an email with ANY valid email in the \u201cFrom\u201d field. Most clients will deem it unreliable though and put it in spam \u2013 exactly as has happened here.\u003C\/li\u003E\n\u003Cli\u003EThey claim to have been \u201cobserving me for a couple of months\u201d. Well, to get enough porn \u0026amp; masturbation blackmail material on me, they wouldn\u2019t need more than a day \ud83e\udd2d\u003C\/li\u003E\n\u003Cli\u003E\u201cMalware was undetectable by the antivirus, because driver\u201d is a BS talk for people who don\u2019t know shit about computers. They\u2019ve been watching me for months, they should know I know my shit about computers \ud83d\ude06\u003C\/li\u003E\n\u003Cli\u003EMost importantly: the deadline is over already. And nothing? \u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EDespite so many red flags people seem to be buying this bullshit, apparently. Those criminals \u003Ca href=\u0022https:\/\/www.blockchain.com\/btc\/address\/17YKd1iJBxu616JEVo15PsXvk1mnQyEFVt\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E have received 4,5 BTC\u003C\/a\u003E already (~14k\u20ac). Within A WEEK!\u003C\/p\u003E\n\u003Cp\u003EPlease, educate yourself about cybersecurity, people... And don\u2019t panic! \ud83d\ude42\u003C\/p\u003E\n\u003Ch3\u003EUpdate\u003C\/h3\u003E\n\u003Cp\u003EI just got a report of a scam attempt that \u003Cem\u003Edid\u003C\/em\u003E include a \u201cproof\u201d, so let\u0027s take a look at it:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/lame-hacker-2_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/lame-hacker-2_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022119.80707395498\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EYes, the attacker knows your password. But they don\u0027t tell you to which service\nthis password grants access to, which is pretty weird...\nIf I were an asshole and had that information, I\u0027d use it:\nat least to further prove to you that I know private shit about you,\nat worse to log in to that account, take it over and demand money for giving it back.\nAnd yet, they didn\u0027t. Suspicious.\u003C\/p\u003E\n\u003Cp\u003EBut anyways... if you go to the \u003Ca href=\u0022https:\/\/haveibeenpwned.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u0027;--have i been pwned?\u003C\/a\u003E website\nand enter your email, you\u0027ll see the list of data breaches over the years where your email was found.\u003C\/p\u003E\n\u003Cp\u003EThis guy\u0027s email was in 18 of them. Some were connected to the same reused password.\nSo here\u0027s how the attacker knew his password: he didn\u0027t hack his computer or gain access to his camera,\nhe just found it (or bought it) on some shady website.\nThe attacker probably doesn\u0027t even know what service was this password for or whether it\u0027s even still valid.\u003C\/p\u003E\n\u003Cp\u003EGood news about this attack: as of today, not a single cent was sent to\n\u003Ca href=\u0022https:\/\/www.blockchain.com\/btc\/address\/bc1qrpmrkdwh2uhnmrsj0803hg909m66rp6ax7y7je\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E that BTC address\u003C\/a\u003E \ud83c\udf89\u003C\/p\u003E\n\u003Cp\u003ESo what\u0027s the takeaway?\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EEven if someone knows your password, it doesn\u0027t automatically prove their other claims.\u003C\/li\u003E\n\u003Cli\u003ESign up for email updates from \u003Ca href=\u0022https:\/\/haveibeenpwned.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u0027;--have i been pwned?\u003C\/a\u003E\nand whenever they notify you about a breach, go to that website and change your password.\u003C\/li\u003E\n\u003Cli\u003EDon\u0027t reuse passwords! The best way to stay secure is to use a different, strong, random password for each service\nand store them in a password manager, like \u003Ca href=\u0022https:\/\/keepass.info\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E KeePass\u003C\/a\u003E or even a browser.\nIf someone told me, they know that my password is \u003Ccode\u003EhiVxV788S2dm8rK6P5qH\u003C\/code\u003E?\nBitch, even \u003Cem\u003EI\u003C\/em\u003E don\u0027t know that\u0027s my password \ud83e\udd37\u200d\u003C\/li\u003E\n\u003Cli\u003EDon\u0027t panic! The vast majority of such attacks is just a bluff.\u003C\/li\u003E\n\u003C\/ul\u003E","words":689,"readTime":3,"lang":"en"}}},"blog\/technology\/ungoogling":{"key":"blog\/technology\/ungoogling","type":"article","published":true,"meta":{"createdAt":"2018-12-18T18:16:39+01:00","publishedAt":"2018-12-25T17:07:00+01:00","group":"tech-breakups","category":"blog","subcategory":"technology","slug":"ungoogling"},"content":{"en":{"slug":"ungoogling","title":"Ungoogling","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ungoogled_small.png\u0022 alt=\u0022un-Google-d\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022322.56\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACGElEQVRIie2WQWsTQRiGn5kmNlUjbi4iUeoxEomQQEvBgxbES7yJP8CLHrz6B\/Qf9KQnQfAoqKeCUitJ8BBjhGgUJEQ04mqgaeJumk13djxU7RpNUiUGhLyXWd7vZfl4hplvhNZaA3xbEEKgtUYIQT\/fX+\/N+L1+mUH\/kf7wuORvoldyWOBfaBCACSGYEBqukRH6ZGner6sdZR3P7VsbCaHbzzrcLTmsvNmkuuYNzV97ee8XL5vN0mw2BwIIwM+ETNMkEolQr9dptVrYtk0qleL1Z8XVM7u5U+rywnSZzT9EV6uI+XnMfSW0+4VdB89xsxCm2fFYMzzU6iq6\/Aq5uMjH8F4qlQqxWOzPCJmmSa1WI5\/Pk8lksG2ber2OqzQdFxZmA+Sqm3jlMlOXLrL+4D5hrQgfSvOksMrCkQBHDwToKo238ggMA6anyeVyGIZBL4DfNuQPxONxCoUClmWRTCZJJBIUi0Uun5hhKbPBracdLsyFkKkk6voNjLPnaQf2YH1Y5uTcafLvXB5Xuhzff5ipdBqaTbBtotEojUaDdrs9kJAY5SyzupqlzAYBKbhyagb5F7NM6C1tdziG4TooI7TWWik19ruonySA53k4joMQAinlj\/X7d6\/vr\/dm\/N5OM8\/f2kgpUUptNQQQDAbHRqH3lB0zuttbqrXWjuPguv1v1nFICEEoFBrtKZu8GEelyXtomP4rQl8B1NeDPuzoe2cAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/ungoogled_small.png\u0022 alt=\u0022un-Google-d\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022322.56\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDepending on one company with all of your data is pretty risky. Even if we ignore the obvious privacy concerns of when some corporation knows \u003Cem\u003Eeverything\u003C\/em\u003E about you... Just imagine what would happen to you personally, if one day that corporation would just... disappear for whatever reason. Say, Google gets a huge fine from the European Commission for one of their monopolistic practices or shitting on their users\u2019 privacy, and turns out they don\u2019t recover from that. How screwed are you?\u003C\/p\u003E\n\u003Cp\u003EOne day you lose your emails, photos, passwords, documents, notes, calendar, what else?\u003C\/p\u003E\n\u003Cp\u003ESo, recently I decided to \u003Cem\u003Ediversify\u003C\/em\u003E my technical dependencies. Not to boycott Google completely, but to at least use it less.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/ungoogled_big.png\u0022 alt=\u0022un-Google-d\u0022 class=\u0022border\u0022 width=\u0022625\u0022 height=\u0022420\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACGElEQVRIie2WQWsTQRiGn5kmNlUjbi4iUeoxEomQQEvBgxbES7yJP8CLHrz6B\/Qf9KQnQfAoqKeCUitJ8BBjhGgUJEQ04mqgaeJumk13djxU7RpNUiUGhLyXWd7vZfl4hplvhNZaA3xbEEKgtUYIQT\/fX+\/N+L1+mUH\/kf7wuORvoldyWOBfaBCACSGYEBqukRH6ZGner6sdZR3P7VsbCaHbzzrcLTmsvNmkuuYNzV97ee8XL5vN0mw2BwIIwM+ETNMkEolQr9dptVrYtk0qleL1Z8XVM7u5U+rywnSZzT9EV6uI+XnMfSW0+4VdB89xsxCm2fFYMzzU6iq6\/Aq5uMjH8F4qlQqxWOzPCJmmSa1WI5\/Pk8lksG2ber2OqzQdFxZmA+Sqm3jlMlOXLrL+4D5hrQgfSvOksMrCkQBHDwToKo238ggMA6anyeVyGIZBL4DfNuQPxONxCoUClmWRTCZJJBIUi0Uun5hhKbPBracdLsyFkKkk6voNjLPnaQf2YH1Y5uTcafLvXB5Xuhzff5ipdBqaTbBtotEojUaDdrs9kJAY5SyzupqlzAYBKbhyagb5F7NM6C1tdziG4TooI7TWWik19ruonySA53k4joMQAinlj\/X7d6\/vr\/dm\/N5OM8\/f2kgpUUptNQQQDAbHRqH3lB0zuttbqrXWjuPguv1v1nFICEEoFBrtKZu8GEelyXtomP4rQl8B1NeDPuzoe2cAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/ungoogled_big.png\u0022 alt=\u0022un-Google-d\u0022 class=\u0022border\u0022 width=\u0022625\u0022 height=\u0022420\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDepending on one company with all of your data is pretty risky. Even if we ignore the obvious privacy concerns of when some corporation knows \u003Cem\u003Eeverything\u003C\/em\u003E about you... Just imagine what would happen to you personally, if one day that corporation would just... disappear for whatever reason. Say, Google gets a huge fine from the European Commission for one of their monopolistic practices or shitting on their users\u2019 privacy, and turns out they don\u2019t recover from that. How screwed are you?\u003C\/p\u003E\n\u003Cp\u003EOne day you lose your emails, photos, passwords, documents, notes, calendar, what else?\u003C\/p\u003E\n\u003Cp\u003ESo, recently I decided to \u003Cem\u003Ediversify\u003C\/em\u003E my technical dependencies. Not to boycott Google completely, but to at least use it less.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Google Search \u2192 DuckDuckGo\u003C\/h3\u003E\n\u003Cp\u003EIf you think about it, there\u2019s usually no need for the search engine to know who you are in order to serve you useful search results, right? Even for the purpose of making money on ads: if you\u2019re looking for \u201cbarbecue\u201d, they\u2019ll show you adverts of grills, because that\u2019s what you\u2019re looking for right now, and not adverts of Cloud Storage, because they know from somewhere else that you might need it... Yet, Google still collects plenty of data about you when you search...\u003C\/p\u003E\n\u003Cp\u003EThe switch to the privacy-oriented \u003Ca href=\u0022https:\/\/duckduckgo.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DuckDuckGo\u003C\/a\u003E turned out to be surprisingly easy. I just changed the default search engine in Chrome and... and that\u2019s it! DuckDuckGo offers most of the features that I was used to in Google, has similar interface, and most importantly it serves the search results that are just as relevant as those of Google.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Images \u2192 DuckDuckGo\/Unsplash\u003C\/h3\u003E\n\u003Cp\u003ESame goes for the image search: DuckDuckGo handles it perfectly, and even has way less annoying user interface than Google.\u003C\/p\u003E\n\u003Cp\u003EAnd when I\u2019m looking for a nice photo to use in a project, I go to \u003Ca href=\u0022https:\/\/unsplash.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Unsplash\u003C\/a\u003E. Everything there is high quality and \u003Ca href=\u0022https:\/\/unsplash.com\/license\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E totally free\u003C\/a\u003E to use however you\u2019d like \ud83d\ude0d\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Chrome \u2192 \u003Cdel\u003EOpera\u003C\/del\u003E \u2192 \u003Ca href=\u0022https:\/\/brave.com\/avr418\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Brave Browser\u003C\/a\u003E\u003C\/h3\u003E\n\u003Cp\u003ELet\u2019s not kid ourselves, all the modern browsers are basically the same. They might have this little feature less or this feature more, but I honestly can\u2019t think of any \u003Cem\u003Estrong\u003C\/em\u003E reasons to like one over another. Some even share the same engines, just with a different UI. Even Edge is a good browser already. It doesn\u2019t matter that much, which one you choose, and switching between them shouldn\u2019t be a big issue. They can import all your settings from your previous browser.\u003C\/p\u003E\n\u003Cp\u003EOr not. That\u2019s what I did: started with a clear browser, no history, no passwords, no saved forms. I wanted to do it anyway, so ungoogling my life was a good occasion to also restart my browser.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I found out about \u003Ca href=\u0022https:\/\/brave.com\/avr418\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Brave Browser\u003C\/a\u003E\n\u2013 it focuses on privacy, has a built-in private window with TOR feature,\nand most importantly it blocks most ads and trackers while still staying fair towards the content creators\nby encouraging a new model of digital avertising based on \u003Ca href=\u0022https:\/\/basicattentiontoken.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E BAT\u003C\/a\u003E.\nCheck it out, it\u0027s awesome!\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Passwords \u2192 KeePass\u003C\/h3\u003E\n\u003Cp\u003EI used to use the same password for everything. Then I got smarter and started using different versions of the same password. But it\u2019s obviously not how you should treat your passwords to stay safe.\u003C\/p\u003E\n\u003Cp\u003ESo now I\u2019m using a unique, random, strong password for each service. And I don\u2019t store it in Chrome (or any other browser) anymore. Instead, I put them in a password manager, \u003Ca href=\u0022https:\/\/keepass.info\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E KeePass\u003C\/a\u003E. Opening it, finding the right password and copy-pasting it to the browser might be a bit less convenient than having the browser just remember it for you, but this way the only party that ever has access to my unhashed \/unencrypted passwords is me.\u003C\/p\u003E\n\u003Cp\u003EI sync the KeePass file (encrypted) between devices via \u003Cdel\u003EGoogle Drive, so that\u2019s still in the queue to ungoogle.\u003C\/del\u003E \u2192 via Cubbit.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Analytics \u2192 \u003Cdel\u003EMatomo\u003C\/del\u003E \u2192 Plauisble\u003C\/h3\u003E\n\u003Cp\u003EGetting rid of Google Analytics required a bit more work, because I have 13 websites tracked that would all require new tracking codes, commits, deployments... But when my lovely husband finally published \u003Ca href=\u0022https:\/\/malenkowicz.net\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E his literary blog\u003C\/a\u003E, and I had to do all that anyway, we decided to give \u003Ca href=\u0022https:\/\/matomo.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Matomo\u003C\/a\u003E a go.\u003C\/p\u003E\n\u003Cp\u003EI just had to set it up on my server (it\u2019s totally free, if you self-host it). Aaand I loved it. It\u2019s hard for me to compare their features, since I only use the most basic stuff, but Matomo seems to have all I need (and more), with an interface that I like more than Google\u2019s.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E Matomo is very heavy, slow and offers way more features than I ever needed. I found this gem, though, and it\u0027s amazing: \u003Ca href=\u0022https:\/\/plausible.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Plausible\u003C\/a\u003E.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Inbox \u2192 \u003Cdel\u003EProtonmail\u003C\/del\u003E \u2192 Tutanota\u003C\/h3\u003E\n\u003Cp\u003EI really like Inbox\u2019s extra features, like grouping emails into trips, snoozing etc. I might have some doubts about leaving it, if it weren\u2019t for the fact that \u003Ca href=\u0022https:\/\/steemit.com\/news\/@spidernet\/google-inbox-will-close-down\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Google is killing the project\u003C\/a\u003E, so I won\u2019t use it one way or another. I\u2019m using an email in my own domain, while my @gmail.com address is mostly there collecting spam, so having to change my address won\u2019t be a problem either.\u003C\/p\u003E\n\u003Cp\u003EI don\u2019t want to set up my own IMAP\/SMTP server, because I just don\u2019t know enough about it to risk being classified as spam or not having 99.999% uptime.\u003C\/p\u003E\n\u003Cp\u003EWhat I do now is redirecting all the incoming emails to Gmail on the DNS level, and use Gmail as SMTP. I could do something similar with almost any other mailbox provider, right?\u003C\/p\u003E\n\u003Cp\u003EI guess I\u2019ll try \u003Ca href=\u0022https:\/\/protonmail.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E ProtonMail\u003C\/a\u003E because of their efforts for security and privacy. It\u2019s paid (if you need the features I need), but it seems to be worth it. If one day I finally have time and strength to finally start setting it all up, I\u2019ll let you know how it went.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E Turns out ProtonMail doesn\u2019t have an option to keep you logged in, it just cleans your session after you close the tab, even on a trusted device. Seriously. That\u2019s just laughable! Users \u003Ca href=\u0022https:\/\/protonmail.uservoice.com\/forums\/284483-feedback\/suggestions\/9594603\u2013keep-me-logged-in-option\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E keep requesting it\u003C\/a\u003E, and ProtonMail keeps ignoring them. Since I\u2019m using a password manager and two-factor authentication, that\u2019s a total deal breaker for me.\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve switched to \u003Ca href=\u0022https:\/\/tutanota.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Tutanota\u003C\/a\u003E. So far it looks just as nice, and it\u2019s even 4x cheaper. The transition was smooth and way easier than I expected (setting up an MX and a TXT record on the DNS). So far, I\u2019m pretty happy with it.\u003C\/p\u003E\n\u003Ch3\u003E\u23f3 Keep \u2192  \u003Cdel\u003E\u0026lt;my own project\u003E\u003C\/del\u003E \u2192 \u2705 iCloud Notes\u003C\/h3\u003E\n\u003Cp\u003EI never had a notes app that I was fully happy with. Currently I\u2019m using Google Keep, but it fucks up the synchronization pretty often, leaving me with outdated or missing notes.\u003C\/p\u003E\n\u003Cp\u003EExcept... I was happy with one notes app, but this one I wrote myself. It was hiding right behind the left border of the screen and would slide out if your mouse went it that area, so it was always just a mouse move away. It was the times when I didn\u2019t have to sync it between devices though.\u003C\/p\u003E\n\u003Cp\u003EBut actually... Why not? Why not write my own thing?\u003C\/p\u003E\n\u003Cp\u003ESo... the migration is still in progress.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/notes-app_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022467.89915966387\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFtklEQVRIiXWV229cVxXGf3uf28yZM2fuM7YTJ45p2iiiSh0QBlWVkJoWGoqQoECbSi0SlweEBG888BTxiqASfwB94ipQhdSHAI0CSBEXVUQlpbnLcW1PbI\/tuZ77OZuHscex4i7pSPvsy9prfd+39hLyx7cVu1bKSYJEESaTqUesnteYdTSSDJT66H0AG37Ghp9+5LoUAnv5HwxnFydzwvM8lWUZAEE\/JEsPv0RqIZtLN8lpJgVXJ8MkTmM0KZFGkdQ0SaIAhCBNM9IMEBIFuJUa\/cw81K8uoOno42CEQM\/n88A42\/76kOFgiKZp2HkbO29PDt69fZ2f\/+h7zFRcrJl5NNfFkClGsMGJ2cdpPHEaLehQLhV58KDD+naAn2oEqWTxuS8SFaYJfB9d16jWmwghAIjSGMuy0PVxUPrD0drFPFZuP5OEeH8soVgq8bEzixxbW+ZmaKLZEdcGR7HSAmp9k637\/+XU6XmGW9t4\/ZhRrDEIM9I4ol4qoNzdBFUEu0QIsoOIPfzzXt5jkEsOhbZsalTm5lhbuUPgWiQtjdlmg7Bg0e4J\/OEGw3aXRr3H6nqXTj+i72d0vYiF7T7XbrxLzXU5cbyB4+YZeTERkkwIjjcESqkxZXt0Afi+R3c4QEiJ7ToY1j5avZHH7XaHtbVNBpqDW\/JpaB8S9iSnPvk0Zr1KZxhx5d83WHrQpTcYMfRjolTxhdGQnKYj\/YRaYtIs2aiGS5CC50dkWYaUEqUU+sOVYt1pY3e7mKbF7KxJHA8RAsIwYmr+JF+58C3iMEQaNkbOJAlGaELSaLW4\/Jd36CQFlu\/dJwWSRCOTEiEVpBG3PriJY+TwVv5FdeUx4jDBDxOq1SbPfO7ZSQwiy7JJRBcvXmRm5ggvvHCeSqXMX69cplAoUKvXaNSbaLpOlqmxMKvViZMwDJEqhuxwutsPtvjhd79DMZ9Dl5AJQb8\/YBSkFJszvPnrX05ELdQuREoput0e\/X6PnGXilsoYhgGA542IwginWCRNx+\/KngOAKIoQQjAcjhirVTA11Zqsr292+M2fLqMME103kAKEkIgkwc5ZvHr+HFLKRwN642c\/ZXunSxgGNBrN8QYhWFtb5atff5k791dwbI183sYPIlSastodUilVOffpp+l5AYIUsoQ0TckyhYEkVBGf+PYPkJUqObfK9MxxNtfa6P1tZtwc\/3zzjUnyB0TdbE0hNY04jjFNC6UyhJBMT0+zMUj4xZ\/fxSlXMMouHS+moOsokePjMzErby3zq\/fbFMJ7dNsfkkYRHWcKFRzlJ6\/VqAV9tm+3ybkucuMe20uryCjAnR4nfqDK9uzlxxcQRwME+2W4Z39rNlh\/8ZuY1QLCFFQMSZSCJSVKS7j1vs92uUhhK0eW7uBHJoVQYdQiio1pvn\/hJRQCxEMXqoyy607oeqTKPFJG4QgpJBWniK5r+2f9PsaNa9zSdMplm2jYRyjIOQ5HigaloEHLW2JpsEXVcfBGI0TmEAb3Edki58+8TpalCCEwDAtjT4N6eqAnHkBInz1CsTmGMNr9Jmuddaor15mOAzb9AHpdDMch8kbEZxeIfAv1wXWy5esshxmxF1NqbRNnBbSoi11vEMYJmpToeoJp7KIiDzZffY8WpRSxUIyScYMsOUVse7+XTUd9LpyZ5zBrtVpgl3nqZBUVLRIpidBMNN1ECMWp+Rpa5z\/s7Oxw+snPsNZe4fdvvU2zXuHzn\/0UQpydyOMAQqadQ7eMfQqTcDLuDwZcvXp1Aq9hGBMnc3Nz9Icj\/vje\/3iyYnF3dZO7577G4NgJSklKLUg4ZliYrkVqWxTLeX576W2+8corrPoh9d2X+pHWcSl4h524CwKklGi7sAIs1Bf48pdeOhShSqXMlcuXaPo9Xnz2OdqPDbhbNWmdPMLZgsWcbTBYTSnNPoU\/HPD3P\/yO5qkzPPP880SGfcDX\/wH1KJOXQcntCQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/notes-app_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022467.89915966387\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E Developing that project is taking me quite a while (mostly because I\u0027m focusing on other things\nand not doing this one at all), so I\u0027ve settled for a corporate solution.\nAnd it looks like Apple\u0027s Notes work very well and synchronise without problems.\u003C\/p\u003E\n\u003Ch3\u003E\u23f3 Drive \u2192 \u003Cdel\u003EAmazon S3 + \u0026lt;my own project\u003E\u003C\/del\u003E \u2192 \u2753 Cubbit?\u003C\/h3\u003E\n\u003Cp\u003EI\u2019m not using Google Drive that much, but still...\nI think that when I figure out the synchronisation for my notes app,\nI could just as well use it to sync files as well\n\u2013 most probably hosted on \u003Ca href=\u0022https:\/\/aws.amazon.com\/s3\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Amazon S3\u003C\/a\u003E.\nLet\u2019s see how that goes, keep fingers crossed! \ud83e\udd1e\ud83c\udffc\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I\u0027ve supported \u003Ca href=\u0022https:\/\/www.cubbit.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Cubbit\u003C\/a\u003E on Kickstarter.\nIt looks really promissing \u0026amp; revolutionary! It\u0027s still at its early stages, though.\nTime will tell, if it was worth it.\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Authenticator\u003C\/del\u003E \u2192 \u2705 Authy\u003C\/h3\u003E\n\u003Cp\u003EI\u2019m fine with keeping some Google tools. For instance Authenticator \u2013 it doesn\u2019t store any personal data, it just uses a standardised algorithm to generate time-dependent access codes. There\u2019s plenty of compatible apps that can replace it \u2013 but I\u2019d have to to go all the websites where I use 2FA and regenerate the tokens. Nah, too much work, not worth it.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After switching from Android to iPhone I had to re-configure the MFA anyway, so I decided to find an alternative for Google Authenticator. And there it was \u2013 \u003Ca href=\u0022https:\/\/authy.com\/\u0022\u003EAuthy\u003C\/a\u003E. It has a way better UI \u2013 with icons and colors to more easily select which account you want to log in to \u2013 and it allows you to share your access tokens between multiple devices, making it way easier to migrate to a new device, to use your computer when your phone is not around, and to recover when you lose your device.\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d AdSense\u003C\/del\u003E \u2192 \ud83d\ude15 AdSense + \u2705 BAT \u2192 \u2705 \u003Ca href=\u0022https:\/\/arc.io\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E arc.io\u003C\/a\u003E\u003C\/h3\u003E\n\u003Cp\u003EThe ad revenue from my websites is laughable (it didn\u2019t even reach the minimum for payout, and I had to start over to switch currency and country), but I keep them just in case. One time a post of mine got so popular it almost broke my server, but I had no ads in place at the time... #tyleprzegra\u0107\u003C\/p\u003E\n\u003Cp\u003EStill, seems like AdSense is the simplest (auto ads \ud83d\ude0d), most advanced and most seamless ad platform I could find. And with my level of \u201crevenue\u201d it doesn\u2019t really matter, which one I use. So screw it for now.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I\u0027ve decided to only keep AdSense on the three websites where they make some profit:\n\u003Ca href=\u0022https:\/\/oursong.eurovote.eu\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E oursong.eurovote.eu\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/generator.avris.it\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E generator.avris.it\u003C\/a\u003E \u0026amp; \u003Ca href=\u0022https:\/\/naked-adventure.eu\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E naked-adventure.eu\u003C\/a\u003E.\nAnd instead I\u0027m trying out \u003Ca href=\u0022https:\/\/basicattentiontoken.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E BAT\u003C\/a\u003E-based advertisment\nin the \u003Ca href=\u0022https:\/\/brave.com\/avr418\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Brave Browser\u003C\/a\u003E \ud83d\ude0d\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I found out about \u003Ca href=\u0022https:\/\/arc.io\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E arc.io\u003C\/a\u003E and it\u0027s looking great so far!\nInstead of showing ads, it asks your users to (seamlessly) be nodes in their CDN.\nThe revenue is really good \ud83d\ude0d\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Youtube\u003C\/del\u003E (\u2192 Vimeo?) \u2192 \u2705 \u003Ca href=\u0022https:\/\/piped.kavin.rocks\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Piped\u003C\/a\u003E + \u003Ca href=\u0022https:\/\/nebula.app\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Nebula\u003C\/a\u003E\u003C\/h3\u003E\n\u003Cp\u003EPlenty of my favourite content is on Youtube and nowhere else, so there\u2019s no way for me to stop using it. But screw it.\u003C\/p\u003E\n\u003Cp\u003EAlthough, if I were uploading some videos myself (without needing a popular platform, just hosting), I\u2019d definitely go for some other platform, probably \u003Ca href=\u0022https:\/\/vimeo.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Vimeo\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E It\u0027s still a fresh project, but looks really promissing!\nBasically, it\u0027s an independent, open-source YouTube client that only uses Google\u0027s servers for what\u0027s really necessary.\nNo need for a Google account to keep track of your subscriptions, no tracking, no ads.\nAnd it\u0027s written in VueJS, when I had a problem importing my YT subscriptions, I just fixed it myself and submitted a pull request \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EI also got a subscription for \u003Ca href=\u0022https:\/\/nebula.app\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Nebula\u003C\/a\u003E.\nIt\u0027s really cheap and it lets me support a lot of my favourite youtubers directly, not via a huge corporate proxy,\nplus it\u0027s without any ads and with exclusive content too!\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Maps \u2192 Apple Maps\u003C\/h3\u003E\n\u003Cp\u003EGoogle Maps are good. Apple Maps seem to be better already,\nbut they\u2019re not available in a browser or on Android,\nso absolutely not for me. Screw it.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After migrating to iPhone I now use Apple Maps there.\nAlso, DuckDuckGo is now using Apple Maps for their search results.\nHopefully, a standalone web version of Apple Maps will also be available soon.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After switching to MacBook Pro, I can now use Apple Maps on desktop as well \ud83c\udf89.\nAlso, I remembered that I have a project that uses Google Maps heavily, \u003Ca href=\u0022https:\/\/naked-adventure.eu\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Naked Adventure\u003C\/a\u003E.\nI took some time recently to \u003Ca href=\u0022\/blog\/redesigning-a-website-naked-adventure\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E rewrite it from scratch\u003C\/a\u003E.\nThe new version switched completely to Apple Maps. And it looks gorgeous! \ud83e\udd70\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Translate\u003C\/del\u003E \u2192 \u2705 \u003Ca href=\u0022https:\/\/www.deepl.com\/translator\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DeepL\u003C\/a\u003E\u003C\/h3\u003E\n\u003Cp\u003ESame. Translate is good, I\u2019m keeping it.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E DeepL Translator seems to be doing just as good of a job as Google Translate, except without tracking you \ud83d\udc4d\nAlso, their MacOS app is just amazing! Just press \u003Ccode\u003ECtrl+C\u003C\/code\u003E twice to translate any text, and click one button to insert the translation back.\nSo comfortable! I used to use my own project for similarly easy access (\u003Ca href=\u0022\/projects\/vocabus-dictionary-at-your-fingertips\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Vocabus - Dictionary at your fingertips!\u003C\/a\u003E),\nbut it was just a dictionary, not a translator. Such an improvement!\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Photos\u003C\/del\u003E \u2192 \u2705 Apple Photos\u003C\/h3\u003E\n\u003Cp\u003EThat\u2019s a tricky one. There\u2019s plenty that annoys me in Google Photos,\nand it\u2019s definitely risky to give them access to all your pictures, but on the other hand...\nthey offer unlimited space. Unlimited! Consider me bought, Google...\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EEdit:\u003C\/strong\u003E TBH, there was another reason I was reluctant to move my photos anywhere outside Google:\nbecause they are a complete mess, and migrating would force me to finally clean it up.\u003C\/p\u003E\n\u003Cp\u003EI was postponing that for a long while, but last weekend I finally swallowed that pill.\nI\u0027ve spent two evenings going through 30 GB of data, assigning each picture to an album,\nremoving trash, separating out all the nudes and porn\u2026 Finally, I\u0027m done!\u003C\/p\u003E\n\u003Cp\u003EApple Photos might cost me a bit (2.99\u20ac\/m),\nbut at least I don\u0027t store my most private data on the servers of a company notorious for crapping on privacy.\nPlus it has a slightly better interface and algorithms, that\u0027s nice.\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Android\u003C\/del\u003E \u2192 \u2705 iPhone\u003C\/h3\u003E\n\u003Cp\u003ETricky as well. I\u2019ve used iPhones and MacBooks that my companies provided, and I was really satisfied with them. Just not enough to actually pay \u003Cem\u003Ethat much\u003C\/em\u003E to get one for myself. Though this year I might actually end up switching to an iPhone, who knows.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E Aaaand I did. I needed a new phone anyway, and since my husband had tested iPhone XS on himself and is totally in love with it, I decided to switch as well.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Calendar \u2192 iCloud Calendar\u003C\/h3\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I honestly forgot to mention Calendar here before. I stayed with Google there, but after getting an iPhone I decided to switch their calendar app as well. I don\u2019t see any advantages or disadvantages of iCloud Calendar over Google Calendar yet, except maybe the Apple one being less messy in its settings. But well, at least it\u2019s yet another area where I got Google-free.\u003C\/p\u003E\n\u003Cp\u003EBtw, a tip: if you want to transfer the events from Google to Apple, export them to an \u003Ccode\u003E.ics\u003C\/code\u003E file, and then mail it to yourself. When you open the attachment on your iPhone, it will let you import all the events (just use the Mail app, for some reason this doesn\u2019t work on Tutanota).\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Google Play Music \u2192 Spotify\u003C\/h3\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate\u003C\/strong\u003E: I forgot about this one as well, since that migration I performed a long time ago already. I don\u2019t know, if it\u2019s still relevant today, but if you\u2019re looking for a way to transfer your music from one to another, you might want to check out my old post: \u003Ca href=\u0022\/blog\/exporting-playlists-from-google-play-music-to-spotify\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Exporting playlists from Google Play Music to Spotify\u003C\/a\u003E\u003C\/p\u003E\n\u003Ch3\u003EUpdate: \u2705 reCAPTCHA \u2192 hCaptcha\u003C\/h3\u003E\n\u003Cp\u003EBefore, I just briefly mentioned reCAPTCHA in the last part. But now that I\u0027ve found a perfect replacement for it,\nit deserves a separate caption.\u003C\/p\u003E\n\u003Cp\u003EGoogle offers reCAPTCHA for \u201cfree\u201d, but actually uses it to train machine learning models and to track you on non-google websites that use their tool.\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/www.hcaptcha.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E hCaptcha\u003C\/a\u003E, on the other hand, does not track you,\nand they even share their revenue from training ML with website owners that use their tool.\nhCaptcha is just as accurate and user-friendly as reCAPTCHA \u2013 can totally recommend!\u003C\/p\u003E\n\u003Ch3\u003EOther alternatives\u003C\/h3\u003E\n\u003Cp\u003EAnyways... You can check out \u003Ca href=\u0022https:\/\/nomoregoogle.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E nomoregoogle.com\u003C\/a\u003E, it collects alternatives to different Google products. Let\u2019s keep it diverse! \ud83d\ude09\u003C\/p\u003E\n\u003Ch3\u003EUpdate: logging out\u003C\/h3\u003E\n\u003Cp\u003ERecently, \u003Ca href=\u0022log-out-for-privacy\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E I\u2019ve realised\u003C\/a\u003E once again how omnipresent is Google.\nIt can track us even when we don\u2019t use Google.\nAny website that serves ads from Google, uses Google Analytics, reCAPTCHA, Google Maps, etc. etc.\n(so almost every website, \u003Cdel\u003Eincluding, regrettably, some of mine\u003C\/del\u003E \u2013 not anymore \ud83c\udf89)\nexecutes scripts from Google\u2019s domains,\nwhich gives Google access to your activity on that website, while they also have access to their own cookies.\nThey see almost your every move online!\u003C\/p\u003E\n\u003Cp\u003ESolution: log out from Google and remove all their cookies. Same for Facebook and other companies that make money off your privacy, that you\u2019ve stopped using, but still keep accounts open for whatever reason.\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s hard. With Google it\u2019s all or nothing. Wanna see your Youtube recommendations? Too bad, we\u2019re also going to automatically log you in to Gmail, GA, Keep, Photos, and... \u003Ca href=\u0022https:\/\/spreadprivacy.com\/followed-by-ads\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E most of the websites on the internet...\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EBut it\u2019s doable. I just did. I stayed logged in in a separate browser used as a sandbox if I ever need it.\u003C\/p\u003E\n\u003Cp\u003EOh, and I also disabled any tracking option I could in \u003Ca href=\u0022https:\/\/myaccount.google.com\/data-and-personalization\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E my Google account settings\u003C\/a\u003E, removed my \u003Ca href=\u0022https:\/\/myactivity.google.com\/myactivity\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E activity\u003C\/a\u003E and double-checked all of the OAuth apps that had access to my Google Account.\u003C\/p\u003E\n\u003Cp\u003EI\u2019m feeling so much less watched over already!\u003C\/p\u003E\n\u003Ch3\u003EUpdate: (almost) entirely Google-free! \ud83c\udf89\u003C\/h3\u003E\n\u003Cp\u003EI know I said it\u0027s not about boycotting Google entirely, just diversifying my tools, but daaaamn it\u0027s addictive.\nEvery piece of data taken away from Google feels like a victory \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003ESo\u2026 I just wanted to announce: as of today I\u0027m (almost) entirely Google-free.\nI will keep one piece of Google that I can\u0027t really get rid of: YouTube -\nbut via a sandboxed app on mobile and a sandbox browser on desktop.\nAll other that\u0027s left is a question of time: I\u0027m waiting for a new Apple TV release, to replace my Chromecast\n(one of the most annoying pieces of hardware I ever owned),\nand for the release of iOS 14 that will come with a translator (or maybe DeepL will create a mobile app till then?).\u003C\/p\u003E\n\u003Cp\u003ESo pretty much: mission accomplished \ud83e\udd42\ud83c\udf7e\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["chrome","customer service","email","google","hosting","big tech","monopoly","platform","search engine","ungoogling","privacy"],"hasMore":true,"image":"https:\/\/avris.it\/image\/ungoogled_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ungoogled_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ungoogled_mini.png\u0022 alt=\u0022un-Google-d\u0022 width=\u0022240\u0022 height=\u0022161.28\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDepending on one company with all of your data is pretty risky. Even if we ignore the obvious privacy concerns of when some corporation knows \u003Cem\u003Eeverything\u003C\/em\u003E about you... Just imagine what would happen to you personally, if one day that corporation would just... disappear for whatever reason. Say, Google gets a huge fine from the European Commission for one of their monopolistic practices or shitting on their users\u2019 privacy, and turns out they don\u2019t recover from that. How screwed are you?\u003C\/p\u003E\n\u003Cp\u003EOne day you lose your emails, photos, passwords, documents, notes, calendar, what else?\u003C\/p\u003E\n\u003Cp\u003ESo, recently I decided to \u003Cem\u003Ediversify\u003C\/em\u003E my technical dependencies. Not to boycott Google completely, but to at least use it less.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/ungoogled_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/ungoogled_mini.png\u0022 alt=\u0022un-Google-d\u0022 width=\u0022240\u0022 height=\u0022161.28\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDepending on one company with all of your data is pretty risky. Even if we ignore the obvious privacy concerns of when some corporation knows \u003Cem\u003Eeverything\u003C\/em\u003E about you... Just imagine what would happen to you personally, if one day that corporation would just... disappear for whatever reason. Say, Google gets a huge fine from the European Commission for one of their monopolistic practices or shitting on their users\u2019 privacy, and turns out they don\u2019t recover from that. How screwed are you?\u003C\/p\u003E\n\u003Cp\u003EOne day you lose your emails, photos, passwords, documents, notes, calendar, what else?\u003C\/p\u003E\n\u003Cp\u003ESo, recently I decided to \u003Cem\u003Ediversify\u003C\/em\u003E my technical dependencies. Not to boycott Google completely, but to at least use it less.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Google Search \u2192 DuckDuckGo\u003C\/h3\u003E\n\u003Cp\u003EIf you think about it, there\u2019s usually no need for the search engine to know who you are in order to serve you useful search results, right? Even for the purpose of making money on ads: if you\u2019re looking for \u201cbarbecue\u201d, they\u2019ll show you adverts of grills, because that\u2019s what you\u2019re looking for right now, and not adverts of Cloud Storage, because they know from somewhere else that you might need it... Yet, Google still collects plenty of data about you when you search...\u003C\/p\u003E\n\u003Cp\u003EThe switch to the privacy-oriented \u003Ca href=\u0022https:\/\/duckduckgo.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DuckDuckGo\u003C\/a\u003E turned out to be surprisingly easy. I just changed the default search engine in Chrome and... and that\u2019s it! DuckDuckGo offers most of the features that I was used to in Google, has similar interface, and most importantly it serves the search results that are just as relevant as those of Google.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Images \u2192 DuckDuckGo\/Unsplash\u003C\/h3\u003E\n\u003Cp\u003ESame goes for the image search: DuckDuckGo handles it perfectly, and even has way less annoying user interface than Google.\u003C\/p\u003E\n\u003Cp\u003EAnd when I\u2019m looking for a nice photo to use in a project, I go to \u003Ca href=\u0022https:\/\/unsplash.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Unsplash\u003C\/a\u003E. Everything there is high quality and \u003Ca href=\u0022https:\/\/unsplash.com\/license\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E totally free\u003C\/a\u003E to use however you\u2019d like \ud83d\ude0d\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Chrome \u2192 \u003Cdel\u003EOpera\u003C\/del\u003E \u2192 \u003Ca href=\u0022https:\/\/brave.com\/avr418\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Brave Browser\u003C\/a\u003E\u003C\/h3\u003E\n\u003Cp\u003ELet\u2019s not kid ourselves, all the modern browsers are basically the same. They might have this little feature less or this feature more, but I honestly can\u2019t think of any \u003Cem\u003Estrong\u003C\/em\u003E reasons to like one over another. Some even share the same engines, just with a different UI. Even Edge is a good browser already. It doesn\u2019t matter that much, which one you choose, and switching between them shouldn\u2019t be a big issue. They can import all your settings from your previous browser.\u003C\/p\u003E\n\u003Cp\u003EOr not. That\u2019s what I did: started with a clear browser, no history, no passwords, no saved forms. I wanted to do it anyway, so ungoogling my life was a good occasion to also restart my browser.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I found out about \u003Ca href=\u0022https:\/\/brave.com\/avr418\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Brave Browser\u003C\/a\u003E\n\u2013 it focuses on privacy, has a built-in private window with TOR feature,\nand most importantly it blocks most ads and trackers while still staying fair towards the content creators\nby encouraging a new model of digital avertising based on \u003Ca href=\u0022https:\/\/basicattentiontoken.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E BAT\u003C\/a\u003E.\nCheck it out, it\u0027s awesome!\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Passwords \u2192 KeePass\u003C\/h3\u003E\n\u003Cp\u003EI used to use the same password for everything. Then I got smarter and started using different versions of the same password. But it\u2019s obviously not how you should treat your passwords to stay safe.\u003C\/p\u003E\n\u003Cp\u003ESo now I\u2019m using a unique, random, strong password for each service. And I don\u2019t store it in Chrome (or any other browser) anymore. Instead, I put them in a password manager, \u003Ca href=\u0022https:\/\/keepass.info\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E KeePass\u003C\/a\u003E. Opening it, finding the right password and copy-pasting it to the browser might be a bit less convenient than having the browser just remember it for you, but this way the only party that ever has access to my unhashed \/unencrypted passwords is me.\u003C\/p\u003E\n\u003Cp\u003EI sync the KeePass file (encrypted) between devices via \u003Cdel\u003EGoogle Drive, so that\u2019s still in the queue to ungoogle.\u003C\/del\u003E \u2192 via Cubbit.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Analytics \u2192 \u003Cdel\u003EMatomo\u003C\/del\u003E \u2192 Plauisble\u003C\/h3\u003E\n\u003Cp\u003EGetting rid of Google Analytics required a bit more work, because I have 13 websites tracked that would all require new tracking codes, commits, deployments... But when my lovely husband finally published \u003Ca href=\u0022https:\/\/malenkowicz.net\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E his literary blog\u003C\/a\u003E, and I had to do all that anyway, we decided to give \u003Ca href=\u0022https:\/\/matomo.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Matomo\u003C\/a\u003E a go.\u003C\/p\u003E\n\u003Cp\u003EI just had to set it up on my server (it\u2019s totally free, if you self-host it). Aaand I loved it. It\u2019s hard for me to compare their features, since I only use the most basic stuff, but Matomo seems to have all I need (and more), with an interface that I like more than Google\u2019s.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E Matomo is very heavy, slow and offers way more features than I ever needed. I found this gem, though, and it\u0027s amazing: \u003Ca href=\u0022https:\/\/plausible.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Plausible\u003C\/a\u003E.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Inbox \u2192 \u003Cdel\u003EProtonmail\u003C\/del\u003E \u2192 Tutanota\u003C\/h3\u003E\n\u003Cp\u003EI really like Inbox\u2019s extra features, like grouping emails into trips, snoozing etc. I might have some doubts about leaving it, if it weren\u2019t for the fact that \u003Ca href=\u0022https:\/\/steemit.com\/news\/@spidernet\/google-inbox-will-close-down\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Google is killing the project\u003C\/a\u003E, so I won\u2019t use it one way or another. I\u2019m using an email in my own domain, while my @gmail.com address is mostly there collecting spam, so having to change my address won\u2019t be a problem either.\u003C\/p\u003E\n\u003Cp\u003EI don\u2019t want to set up my own IMAP\/SMTP server, because I just don\u2019t know enough about it to risk being classified as spam or not having 99.999% uptime.\u003C\/p\u003E\n\u003Cp\u003EWhat I do now is redirecting all the incoming emails to Gmail on the DNS level, and use Gmail as SMTP. I could do something similar with almost any other mailbox provider, right?\u003C\/p\u003E\n\u003Cp\u003EI guess I\u2019ll try \u003Ca href=\u0022https:\/\/protonmail.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E ProtonMail\u003C\/a\u003E because of their efforts for security and privacy. It\u2019s paid (if you need the features I need), but it seems to be worth it. If one day I finally have time and strength to finally start setting it all up, I\u2019ll let you know how it went.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E Turns out ProtonMail doesn\u2019t have an option to keep you logged in, it just cleans your session after you close the tab, even on a trusted device. Seriously. That\u2019s just laughable! Users \u003Ca href=\u0022https:\/\/protonmail.uservoice.com\/forums\/284483-feedback\/suggestions\/9594603\u2013keep-me-logged-in-option\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E keep requesting it\u003C\/a\u003E, and ProtonMail keeps ignoring them. Since I\u2019m using a password manager and two-factor authentication, that\u2019s a total deal breaker for me.\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve switched to \u003Ca href=\u0022https:\/\/tutanota.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Tutanota\u003C\/a\u003E. So far it looks just as nice, and it\u2019s even 4x cheaper. The transition was smooth and way easier than I expected (setting up an MX and a TXT record on the DNS). So far, I\u2019m pretty happy with it.\u003C\/p\u003E\n\u003Ch3\u003E\u23f3 Keep \u2192  \u003Cdel\u003E\u0026lt;my own project\u003E\u003C\/del\u003E \u2192 \u2705 iCloud Notes\u003C\/h3\u003E\n\u003Cp\u003EI never had a notes app that I was fully happy with. Currently I\u2019m using Google Keep, but it fucks up the synchronization pretty often, leaving me with outdated or missing notes.\u003C\/p\u003E\n\u003Cp\u003EExcept... I was happy with one notes app, but this one I wrote myself. It was hiding right behind the left border of the screen and would slide out if your mouse went it that area, so it was always just a mouse move away. It was the times when I didn\u2019t have to sync it between devices though.\u003C\/p\u003E\n\u003Cp\u003EBut actually... Why not? Why not write my own thing?\u003C\/p\u003E\n\u003Cp\u003ESo... the migration is still in progress.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/notes-app_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/notes-app_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022116.97478991597\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E Developing that project is taking me quite a while (mostly because I\u0027m focusing on other things\nand not doing this one at all), so I\u0027ve settled for a corporate solution.\nAnd it looks like Apple\u0027s Notes work very well and synchronise without problems.\u003C\/p\u003E\n\u003Ch3\u003E\u23f3 Drive \u2192 \u003Cdel\u003EAmazon S3 + \u0026lt;my own project\u003E\u003C\/del\u003E \u2192 \u2753 Cubbit?\u003C\/h3\u003E\n\u003Cp\u003EI\u2019m not using Google Drive that much, but still...\nI think that when I figure out the synchronisation for my notes app,\nI could just as well use it to sync files as well\n\u2013 most probably hosted on \u003Ca href=\u0022https:\/\/aws.amazon.com\/s3\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Amazon S3\u003C\/a\u003E.\nLet\u2019s see how that goes, keep fingers crossed! \ud83e\udd1e\ud83c\udffc\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I\u0027ve supported \u003Ca href=\u0022https:\/\/www.cubbit.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Cubbit\u003C\/a\u003E on Kickstarter.\nIt looks really promissing \u0026amp; revolutionary! It\u0027s still at its early stages, though.\nTime will tell, if it was worth it.\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Authenticator\u003C\/del\u003E \u2192 \u2705 Authy\u003C\/h3\u003E\n\u003Cp\u003EI\u2019m fine with keeping some Google tools. For instance Authenticator \u2013 it doesn\u2019t store any personal data, it just uses a standardised algorithm to generate time-dependent access codes. There\u2019s plenty of compatible apps that can replace it \u2013 but I\u2019d have to to go all the websites where I use 2FA and regenerate the tokens. Nah, too much work, not worth it.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After switching from Android to iPhone I had to re-configure the MFA anyway, so I decided to find an alternative for Google Authenticator. And there it was \u2013 \u003Ca href=\u0022https:\/\/authy.com\/\u0022\u003EAuthy\u003C\/a\u003E. It has a way better UI \u2013 with icons and colors to more easily select which account you want to log in to \u2013 and it allows you to share your access tokens between multiple devices, making it way easier to migrate to a new device, to use your computer when your phone is not around, and to recover when you lose your device.\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d AdSense\u003C\/del\u003E \u2192 \ud83d\ude15 AdSense + \u2705 BAT \u2192 \u2705 \u003Ca href=\u0022https:\/\/arc.io\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E arc.io\u003C\/a\u003E\u003C\/h3\u003E\n\u003Cp\u003EThe ad revenue from my websites is laughable (it didn\u2019t even reach the minimum for payout, and I had to start over to switch currency and country), but I keep them just in case. One time a post of mine got so popular it almost broke my server, but I had no ads in place at the time... #tyleprzegra\u0107\u003C\/p\u003E\n\u003Cp\u003EStill, seems like AdSense is the simplest (auto ads \ud83d\ude0d), most advanced and most seamless ad platform I could find. And with my level of \u201crevenue\u201d it doesn\u2019t really matter, which one I use. So screw it for now.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I\u0027ve decided to only keep AdSense on the three websites where they make some profit:\n\u003Ca href=\u0022https:\/\/oursong.eurovote.eu\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E oursong.eurovote.eu\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/generator.avris.it\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E generator.avris.it\u003C\/a\u003E \u0026amp; \u003Ca href=\u0022https:\/\/naked-adventure.eu\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E naked-adventure.eu\u003C\/a\u003E.\nAnd instead I\u0027m trying out \u003Ca href=\u0022https:\/\/basicattentiontoken.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E BAT\u003C\/a\u003E-based advertisment\nin the \u003Ca href=\u0022https:\/\/brave.com\/avr418\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Brave Browser\u003C\/a\u003E \ud83d\ude0d\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I found out about \u003Ca href=\u0022https:\/\/arc.io\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E arc.io\u003C\/a\u003E and it\u0027s looking great so far!\nInstead of showing ads, it asks your users to (seamlessly) be nodes in their CDN.\nThe revenue is really good \ud83d\ude0d\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Youtube\u003C\/del\u003E (\u2192 Vimeo?) \u2192 \u2705 \u003Ca href=\u0022https:\/\/piped.kavin.rocks\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Piped\u003C\/a\u003E + \u003Ca href=\u0022https:\/\/nebula.app\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Nebula\u003C\/a\u003E\u003C\/h3\u003E\n\u003Cp\u003EPlenty of my favourite content is on Youtube and nowhere else, so there\u2019s no way for me to stop using it. But screw it.\u003C\/p\u003E\n\u003Cp\u003EAlthough, if I were uploading some videos myself (without needing a popular platform, just hosting), I\u2019d definitely go for some other platform, probably \u003Ca href=\u0022https:\/\/vimeo.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Vimeo\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E It\u0027s still a fresh project, but looks really promissing!\nBasically, it\u0027s an independent, open-source YouTube client that only uses Google\u0027s servers for what\u0027s really necessary.\nNo need for a Google account to keep track of your subscriptions, no tracking, no ads.\nAnd it\u0027s written in VueJS, when I had a problem importing my YT subscriptions, I just fixed it myself and submitted a pull request \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EI also got a subscription for \u003Ca href=\u0022https:\/\/nebula.app\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Nebula\u003C\/a\u003E.\nIt\u0027s really cheap and it lets me support a lot of my favourite youtubers directly, not via a huge corporate proxy,\nplus it\u0027s without any ads and with exclusive content too!\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Maps \u2192 Apple Maps\u003C\/h3\u003E\n\u003Cp\u003EGoogle Maps are good. Apple Maps seem to be better already,\nbut they\u2019re not available in a browser or on Android,\nso absolutely not for me. Screw it.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After migrating to iPhone I now use Apple Maps there.\nAlso, DuckDuckGo is now using Apple Maps for their search results.\nHopefully, a standalone web version of Apple Maps will also be available soon.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E After switching to MacBook Pro, I can now use Apple Maps on desktop as well \ud83c\udf89.\nAlso, I remembered that I have a project that uses Google Maps heavily, \u003Ca href=\u0022https:\/\/naked-adventure.eu\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Naked Adventure\u003C\/a\u003E.\nI took some time recently to \u003Ca href=\u0022\/blog\/redesigning-a-website-naked-adventure.lite\u0022\u003E rewrite it from scratch\u003C\/a\u003E.\nThe new version switched completely to Apple Maps. And it looks gorgeous! \ud83e\udd70\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Translate\u003C\/del\u003E \u2192 \u2705 \u003Ca href=\u0022https:\/\/www.deepl.com\/translator\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DeepL\u003C\/a\u003E\u003C\/h3\u003E\n\u003Cp\u003ESame. Translate is good, I\u2019m keeping it.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E DeepL Translator seems to be doing just as good of a job as Google Translate, except without tracking you \ud83d\udc4d\nAlso, their MacOS app is just amazing! Just press \u003Ccode\u003ECtrl+C\u003C\/code\u003E twice to translate any text, and click one button to insert the translation back.\nSo comfortable! I used to use my own project for similarly easy access (\u003Ca href=\u0022\/projects\/vocabus-dictionary-at-your-fingertips.lite\u0022\u003E Vocabus - Dictionary at your fingertips!\u003C\/a\u003E),\nbut it was just a dictionary, not a translator. Such an improvement!\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Photos\u003C\/del\u003E \u2192 \u2705 Apple Photos\u003C\/h3\u003E\n\u003Cp\u003EThat\u2019s a tricky one. There\u2019s plenty that annoys me in Google Photos,\nand it\u2019s definitely risky to give them access to all your pictures, but on the other hand...\nthey offer unlimited space. Unlimited! Consider me bought, Google...\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EEdit:\u003C\/strong\u003E TBH, there was another reason I was reluctant to move my photos anywhere outside Google:\nbecause they are a complete mess, and migrating would force me to finally clean it up.\u003C\/p\u003E\n\u003Cp\u003EI was postponing that for a long while, but last weekend I finally swallowed that pill.\nI\u0027ve spent two evenings going through 30 GB of data, assigning each picture to an album,\nremoving trash, separating out all the nudes and porn\u2026 Finally, I\u0027m done!\u003C\/p\u003E\n\u003Cp\u003EApple Photos might cost me a bit (2.99\u20ac\/m),\nbut at least I don\u0027t store my most private data on the servers of a company notorious for crapping on privacy.\nPlus it has a slightly better interface and algorithms, that\u0027s nice.\u003C\/p\u003E\n\u003Ch3\u003E\u003Cdel\u003E\ud83d\udc4d Android\u003C\/del\u003E \u2192 \u2705 iPhone\u003C\/h3\u003E\n\u003Cp\u003ETricky as well. I\u2019ve used iPhones and MacBooks that my companies provided, and I was really satisfied with them. Just not enough to actually pay \u003Cem\u003Ethat much\u003C\/em\u003E to get one for myself. Though this year I might actually end up switching to an iPhone, who knows.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E Aaaand I did. I needed a new phone anyway, and since my husband had tested iPhone XS on himself and is totally in love with it, I decided to switch as well.\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Calendar \u2192 iCloud Calendar\u003C\/h3\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate:\u003C\/strong\u003E I honestly forgot to mention Calendar here before. I stayed with Google there, but after getting an iPhone I decided to switch their calendar app as well. I don\u2019t see any advantages or disadvantages of iCloud Calendar over Google Calendar yet, except maybe the Apple one being less messy in its settings. But well, at least it\u2019s yet another area where I got Google-free.\u003C\/p\u003E\n\u003Cp\u003EBtw, a tip: if you want to transfer the events from Google to Apple, export them to an \u003Ccode\u003E.ics\u003C\/code\u003E file, and then mail it to yourself. When you open the attachment on your iPhone, it will let you import all the events (just use the Mail app, for some reason this doesn\u2019t work on Tutanota).\u003C\/p\u003E\n\u003Ch3\u003E\u2705 Google Play Music \u2192 Spotify\u003C\/h3\u003E\n\u003Cp\u003E\u003Cstrong\u003EUpdate\u003C\/strong\u003E: I forgot about this one as well, since that migration I performed a long time ago already. I don\u2019t know, if it\u2019s still relevant today, but if you\u2019re looking for a way to transfer your music from one to another, you might want to check out my old post: \u003Ca href=\u0022\/blog\/exporting-playlists-from-google-play-music-to-spotify.lite\u0022\u003E Exporting playlists from Google Play Music to Spotify\u003C\/a\u003E\u003C\/p\u003E\n\u003Ch3\u003EUpdate: \u2705 reCAPTCHA \u2192 hCaptcha\u003C\/h3\u003E\n\u003Cp\u003EBefore, I just briefly mentioned reCAPTCHA in the last part. But now that I\u0027ve found a perfect replacement for it,\nit deserves a separate caption.\u003C\/p\u003E\n\u003Cp\u003EGoogle offers reCAPTCHA for \u201cfree\u201d, but actually uses it to train machine learning models and to track you on non-google websites that use their tool.\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/www.hcaptcha.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E hCaptcha\u003C\/a\u003E, on the other hand, does not track you,\nand they even share their revenue from training ML with website owners that use their tool.\nhCaptcha is just as accurate and user-friendly as reCAPTCHA \u2013 can totally recommend!\u003C\/p\u003E\n\u003Ch3\u003EOther alternatives\u003C\/h3\u003E\n\u003Cp\u003EAnyways... You can check out \u003Ca href=\u0022https:\/\/nomoregoogle.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E nomoregoogle.com\u003C\/a\u003E, it collects alternatives to different Google products. Let\u2019s keep it diverse! \ud83d\ude09\u003C\/p\u003E\n\u003Ch3\u003EUpdate: logging out\u003C\/h3\u003E\n\u003Cp\u003ERecently, \u003Ca href=\u0022log-out-for-privacy\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E I\u2019ve realised\u003C\/a\u003E once again how omnipresent is Google.\nIt can track us even when we don\u2019t use Google.\nAny website that serves ads from Google, uses Google Analytics, reCAPTCHA, Google Maps, etc. etc.\n(so almost every website, \u003Cdel\u003Eincluding, regrettably, some of mine\u003C\/del\u003E \u2013 not anymore \ud83c\udf89)\nexecutes scripts from Google\u2019s domains,\nwhich gives Google access to your activity on that website, while they also have access to their own cookies.\nThey see almost your every move online!\u003C\/p\u003E\n\u003Cp\u003ESolution: log out from Google and remove all their cookies. Same for Facebook and other companies that make money off your privacy, that you\u2019ve stopped using, but still keep accounts open for whatever reason.\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s hard. With Google it\u2019s all or nothing. Wanna see your Youtube recommendations? Too bad, we\u2019re also going to automatically log you in to Gmail, GA, Keep, Photos, and... \u003Ca href=\u0022https:\/\/spreadprivacy.com\/followed-by-ads\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E most of the websites on the internet...\u003C\/a\u003E\u003C\/p\u003E\n\u003Cp\u003EBut it\u2019s doable. I just did. I stayed logged in in a separate browser used as a sandbox if I ever need it.\u003C\/p\u003E\n\u003Cp\u003EOh, and I also disabled any tracking option I could in \u003Ca href=\u0022https:\/\/myaccount.google.com\/data-and-personalization\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E my Google account settings\u003C\/a\u003E, removed my \u003Ca href=\u0022https:\/\/myactivity.google.com\/myactivity\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E activity\u003C\/a\u003E and double-checked all of the OAuth apps that had access to my Google Account.\u003C\/p\u003E\n\u003Cp\u003EI\u2019m feeling so much less watched over already!\u003C\/p\u003E\n\u003Ch3\u003EUpdate: (almost) entirely Google-free! \ud83c\udf89\u003C\/h3\u003E\n\u003Cp\u003EI know I said it\u0027s not about boycotting Google entirely, just diversifying my tools, but daaaamn it\u0027s addictive.\nEvery piece of data taken away from Google feels like a victory \ud83d\ude05\u003C\/p\u003E\n\u003Cp\u003ESo\u2026 I just wanted to announce: as of today I\u0027m (almost) entirely Google-free.\nI will keep one piece of Google that I can\u0027t really get rid of: YouTube -\nbut via a sandboxed app on mobile and a sandbox browser on desktop.\nAll other that\u0027s left is a question of time: I\u0027m waiting for a new Apple TV release, to replace my Chromecast\n(one of the most annoying pieces of hardware I ever owned),\nand for the release of iOS 14 that will come with a translator (or maybe DeepL will create a mobile app till then?).\u003C\/p\u003E\n\u003Cp\u003ESo pretty much: mission accomplished \ud83e\udd42\ud83c\udf7e\u003C\/p\u003E","words":2922,"readTime":12,"lang":"en"}}},"blog\/technology\/how-and-why-i-ve-built-and-killed-a-php-framework":{"key":"blog\/technology\/how-and-why-i-ve-built-and-killed-a-php-framework","type":"article","published":true,"meta":{"createdAt":"2018-09-22T14:26:34+02:00","publishedAt":"2018-09-22T14:24:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"how-and-why-i-ve-built-and-killed-a-php-framework"},"content":{"en":{"slug":"how-and-why-i-ve-built-and-killed-a-php-framework","title":"How and why I\u0027ve built and killed a PHP framework","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/micrus-rip_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022235.46694648478\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEeElEQVRIiZ2WvW8UVxDAf\/P27d7tnT\/uDP4I4AQsDMSJkLBS0EWKRJEqFTQpQhPlP6ADKRUl\/4ClpIuUzojIKYmUpLBpEqBIMAihGNsnWyf77Fvf7r43KfZ8xjbYSkZavX1fM7+ZN292xTmnvEOSJCFNU0AQAREAwXuPtZY0TYnjmHK5\/Nb93jlar5aJqzHtPCGqDSEixHH8LpPIzNxTVRGk6HaNAm+M9Qa16KKHfdg3pMXS\/fP6xpz2+qoKqoVqAbuxleJ7EF2oLlDRyO4IRgSvigh4LSi0Byh7EF0Dh4APQqhSvBZ9I2Brsd0D2vVgL0w9xZfG63x8ts5qMyEuW35+9ArV7nzXkIgQlwLCwOC8YkzhSruT00lzvO86ql3du051wYyAHeu37HhIHVRCqFjIFUIDzUQphwHlyPDRmX58lvPBcJXmZpvps3UazW1UYXPHs9LKUZTQCrE1hBbiUHj57Cluu8FgxbK4uMjSapNzU1c5e\/EKcWTInMdAEXkUufX9I7XWIAjbqSPJHCKCESF1ijWGi8MWgzJeC3mvPyDpOKRUxncSfnmZ8dd6hndKaA3lKOgdWXX9D778bIqFhQVGR0eZmpqiWq3y4MEDXjR2WK99QlQqMTFYRC00ILe+m1cFktzjFTwgKhgjtDs57dTTzhznx\/qpV0IAIhuw3GyTpI6OUzLnEDFE1hAaQ5I5tteX+fpqH8l2C2MM4+PjjI6OIiLkec7c3Bw\/PnFEwxfwqnivvH6+iL3Qn\/L3WoYl4MMzg9Rjw\/O1jBdrCZ3MYVQJcDxbaqKq2CCgFAaUQkOae5bXWySdlCAwlKOQWl+ZkVqVK+f7mbo0ydraGiMjI7TbbZxzdDodKpUKfX19fHrBs9DYYfWfFRqrK2xvb2F\/erQMUiRlq7nJxJk67586wdhQhdwrae7ZyTxOwfvd2yNkztHJHOdHqxgprrL3RZIbhFO1iEajwZ07d5ienmZkZISJiQlu377NvXv3CMOQwVLKgM0x9TL1eAQ4if3h2y96tUFEUO226F4d+h\/y5PGfjI2Nce3aNdI0pV6vc\/nyZa5fv87k5CSNRoNzYwN889XniHTLhir2KKXGGJ4vLlKv1wms5eSJE3vAb1z1g6KqJEkCwI0bN\/atv3nzJqqKcw7n\/aG9RwIBnD59mizL8N7vr67A5uYmeZ5TLpepVCq9Pd57BgYGjtTrvT9czgFzHJAxgogQBAHNZpM0zXpRybKM3HnEloqKfuA5SqIo4m1ExwJpN5nzPMcYQ6u1WXgH2LgfjfrYTt1xat4q\/i1HdixQlmUkSZs0TXv5k2UZAJIn6M4G2VaT10tL3T8Dup+Cd\/5EFHtFaCcJzuX\/DSiKIuI4Jq5UEBGGhoYolUpdwxAYQxAE2NDSarVIkoT5+Xnm5uZYXl5mY2ODlZUVtra2AJidne2te\/L4Mffvz+6zd2xS7344vXP0HUjUIAiw1uK9JwgiEo0YKpcxxnD37l1mZmYYHh7uRW5gYICHDx9Sq9XI8yIyv\/72+z6d\/wKYTk2khRKRbgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/micrus-rip_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022235.46694648478\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe PHP ecosystem is full of frameworks: \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/laravel.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Laravel\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/www.yiiframework.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Yii\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/framework.zend.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Zend\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/phalconphp.com\/en\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Phalcon\u003C\/a\u003E, and so many, many, many more... All of them built by professionals and supported by big communities. So why on earth would a junior developer, who has just started his first job, try his hand in building yet another one?\u003C\/p\u003E\n\u003Cp\u003EWell, here\u2019s why:\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/micrus-rip_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022470.93389296957\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEeElEQVRIiZ2WvW8UVxDAf\/P27d7tnT\/uDP4I4AQsDMSJkLBS0EWKRJEqFTQpQhPlP6ADKRUl\/4ClpIuUzojIKYmUpLBpEqBIMAihGNsnWyf77Fvf7r43KfZ8xjbYSkZavX1fM7+ZN292xTmnvEOSJCFNU0AQAREAwXuPtZY0TYnjmHK5\/Nb93jlar5aJqzHtPCGqDSEixHH8LpPIzNxTVRGk6HaNAm+M9Qa16KKHfdg3pMXS\/fP6xpz2+qoKqoVqAbuxleJ7EF2oLlDRyO4IRgSvigh4LSi0Byh7EF0Dh4APQqhSvBZ9I2Brsd0D2vVgL0w9xZfG63x8ts5qMyEuW35+9ArV7nzXkIgQlwLCwOC8YkzhSruT00lzvO86ql3du051wYyAHeu37HhIHVRCqFjIFUIDzUQphwHlyPDRmX58lvPBcJXmZpvps3UazW1UYXPHs9LKUZTQCrE1hBbiUHj57Cluu8FgxbK4uMjSapNzU1c5e\/EKcWTInMdAEXkUufX9I7XWIAjbqSPJHCKCESF1ijWGi8MWgzJeC3mvPyDpOKRUxncSfnmZ8dd6hndKaA3lKOgdWXX9D778bIqFhQVGR0eZmpqiWq3y4MEDXjR2WK99QlQqMTFYRC00ILe+m1cFktzjFTwgKhgjtDs57dTTzhznx\/qpV0IAIhuw3GyTpI6OUzLnEDFE1hAaQ5I5tteX+fpqH8l2C2MM4+PjjI6OIiLkec7c3Bw\/PnFEwxfwqnivvH6+iL3Qn\/L3WoYl4MMzg9Rjw\/O1jBdrCZ3MYVQJcDxbaqKq2CCgFAaUQkOae5bXWySdlCAwlKOQWl+ZkVqVK+f7mbo0ydraGiMjI7TbbZxzdDodKpUKfX19fHrBs9DYYfWfFRqrK2xvb2F\/erQMUiRlq7nJxJk67586wdhQhdwrae7ZyTxOwfvd2yNkztHJHOdHqxgprrL3RZIbhFO1iEajwZ07d5ienmZkZISJiQlu377NvXv3CMOQwVLKgM0x9TL1eAQ4if3h2y96tUFEUO226F4d+h\/y5PGfjI2Nce3aNdI0pV6vc\/nyZa5fv87k5CSNRoNzYwN889XniHTLhir2KKXGGJ4vLlKv1wms5eSJE3vAb1z1g6KqJEkCwI0bN\/atv3nzJqqKcw7n\/aG9RwIBnD59mizL8N7vr67A5uYmeZ5TLpepVCq9Pd57BgYGjtTrvT9czgFzHJAxgogQBAHNZpM0zXpRybKM3HnEloqKfuA5SqIo4m1ExwJpN5nzPMcYQ6u1WXgH2LgfjfrYTt1xat4q\/i1HdixQlmUkSZs0TXv5k2UZAJIn6M4G2VaT10tL3T8Dup+Cd\/5EFHtFaCcJzuX\/DSiKIuI4Jq5UEBGGhoYolUpdwxAYQxAE2NDSarVIkoT5+Xnm5uZYXl5mY2ODlZUVtra2AJidne2te\/L4Mffvz+6zd2xS7344vXP0HUjUIAiw1uK9JwgiEo0YKpcxxnD37l1mZmYYHh7uRW5gYICHDx9Sq9XI8yIyv\/72+z6d\/wKYTk2khRKRbgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/micrus-rip_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022470.93389296957\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe PHP ecosystem is full of frameworks: \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/laravel.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Laravel\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/www.yiiframework.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Yii\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/framework.zend.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Zend\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/phalconphp.com\/en\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Phalcon\u003C\/a\u003E, and so many, many, many more... All of them built by professionals and supported by big communities. So why on earth would a junior developer, who has just started his first job, try his hand in building yet another one?\u003C\/p\u003E\n\u003Cp\u003EWell, here\u2019s why:\u003C\/p\u003E\n\u003Cp\u003EWhen I learned PHP, the URLs I knew how to build and use looked like this: \u003Ccode\u003E\/index.php?module=user\u0026amp;action=show\u0026amp;id=123\u003C\/code\u003E. I had no idea, how to make them nice like this: \u003Ccode\u003E\/user\/show\/123\u003C\/code\u003E. Symfony knew though, and I could just use it.\u003C\/p\u003E\n\u003Cp\u003EBut I was used to coding things from scratch and understanding how they work internally, I didn\u2019t like the magic of \u201cit just works\u201d. I know, stupid, if I were still doing that, I\u2019d never finish any project. At the time it did make sense, though.\u003C\/p\u003E\n\u003Cp\u003EI was curious if I can replicate the behaviour. I stole the \u003Ccode\u003E.htaccess\u003C\/code\u003E config from Symfony, I\u2019ve expanded my knowledge about regular expressions, and eventually, I did it! It was buggy and ugly, but it worked and it was mine, and I was so proud of it!\u003C\/p\u003E\n\u003Cp\u003EAnd then I couldn\u2019t stop. Every time I had had to dig into Symfony\u2019s code and had gotten overwhelmed by its complexity, I realised how simple the overall logic actually is, even though it\u2019s overblown by trying to keep it generic and open for modification\/extension. So just like I did with the router, I also rewrote from scratch the event dispatcher, the security layer, the DI container and a couple of other components, eventually ending up with a fully usable framework.\u003C\/p\u003E\n\u003Cp\u003EI don\u2019t think I have access to its source code anymore, but I think it was only 10 files or so. It was crappy, didn\u2019t comply with PSR-4, wasn\u2019t published as a Composer package, and probably was full of bugs that I\u2019ve never found.\u003C\/p\u003E\n\u003Cp\u003EIt didn\u2019t really make much sense to further develop it. Nobody\u2019s gonna use it anyway. It\u2019s not gonna be better than any of the frameworks that have plenty of people working on them. I\u2019ve already learned a lot, isn\u2019t it enough to call it a day?\u003C\/p\u003E\n\u003Cp\u003EBut I took some criticism for the version 0.0 from people who knew better how to code, so I had to address their advice and to make Micrus better. And it turned out to be a great decision because I still had \u003Cem\u003Ea lot\u003C\/em\u003E more to learn.\u003C\/p\u003E\n\u003Cp\u003EThe biggest challenge was managing dependencies. I couldn\u2019t put all the modules like \u201cMailer\u201d, \u201cTwig\u201d, \u201cSocial login\u201d, \u201cCRUD\u201d etc. in one huge package and still call it \u201cMicrus\u201d. But I was developing all of them at once! I had to learn more about the internals of Composer in order to treat local directories as if they were packages, without pushing or tagging them (only later I found out about \u003Ca href=\u0022https:\/\/getcomposer.org\/doc\/05-repositories.md#path\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Repository of type \u201cpath\u201d\u003C\/a\u003E \u2013 really useful!). I had to learn how to organise the code better so that adding or removing entire modules could be as seamless as possible. I had to keep them consistent, simple, powerful, extendable. I spent hours and hours, and days and days, on figuring out their architecture...\u003C\/p\u003E\n\u003Cp\u003EThe second biggest challenge was the forms. They\u2019re just awful. The form abstraction layer has to move data around between the actual object that holds data, a form and it\u2019s HTML representation. It needs to map the data both ways, it needs to validate it, it\u2019s just a mess. At work at \u003Ca href=\u0022https:\/\/www.rocket-internet.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Rocket Internet\u003C\/a\u003E, even though we were using a Phalcon-based framework, many ventures decided to use the standalone \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/components\/form.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony Form\u003C\/a\u003E component instead of Phalcon forms, because that was the least troublesome one.\u003C\/p\u003E\n\u003Cp\u003EStill, they weren\u2019t simple enough for me. Sure, they\u2019re way, way better than handling the forms without any framework, but whenever I needed to do anything even slightly non-standard, I really missed the option of just writing down some HTML. Instead, I had to learn about the internals of the framework. I didn\u2019t like it, so, I\u2019ve spent ages trying to prove to myself, that one can make the best of two worlds.\u003C\/p\u003E\n\u003Cp\u003EThe same with the security layer. I really hate how Symfony implements it. It\u2019s a piece of cake to configure the most simple cases, they hide everything behind a veil of magic. But as soon as you need something non-standard, you need to go through their documentation, get into their way of thinking, understand their ideas... You can\u2019t just write down the simple logic you need, you need wrappers, voters, providers, listeners, etc. etc. I decided to try to implement it my way.\u003C\/p\u003E\n\u003Cp\u003EAnd it worked for me. I\u2019ve released \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus \u2022 Tiny, yet powerful, PHP framework\u003C\/a\u003E that later become  \u003Ca href=\u0022\/projects\/micrus-v4\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus v4 \u2022 Beauty of simplicity\u003C\/a\u003E. I\u2019ve built a couple of projects based on Micrus (listed at \u003Ca href=\u0022https:\/\/micrus.avris.it\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E micrus.avris.it\u003C\/a\u003E). I had fun, seeing how easy it was for me to build apps with Micrus.\u003C\/p\u003E\n\u003Cp\u003EWhenever I would encounter something worth improving, I did so. How exhausting was that! On one hand disappointing (I wasn\u2019t expecting anyone else to use it), on the other really rewarding (it is an accomplishment after all). When I discovered \u003Ca href=\u0022\/blog\/the-non-magic-of-autowiring\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E The non-magic of autowiring\u003C\/a\u003E, I implemented that as well. I covered 100% of my code with unit tests (which was quite a challenging type of code to cover).\u003C\/p\u003E\n\u003Cp\u003EBut then, Symfony has released its version four. And it\u2019s amazing. It has \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/setup\/flex.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Flex\u003C\/a\u003E, it\u2019s flexible, it\u2019s fast... Maybe it\u2019s not as simple as I would wish it to be, but it\u2019s undeniably way better than anything I could ever create myself. Also, I simply got tired of building Micrus already. It grew bigger than I thought it would, it started resembling Symfony more and more, while I understood more and more of Symfony\u2019s design... \u003C\/p\u003E\n\u003Cp\u003ESo there I am: having learned an awful lot about standards, modularisation, architecture, framework internals, autoloading, autowiring, testing, managing dependencies, and much much more. Having created something irrelevant, but quite impressive nevertheless.\u003C\/p\u003E\n\u003Cp\u003EI\u2019m still gonna keep putting Micrus in my CV, I\u2019m still gonna keep most of my Micrus-based-projects running it, but I\u2019m not gonna improve it anymore or start any new projects on it.\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s been a wonderful adventure. Now it\u2019s time to move on \ud83d\ude0a\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["framework","micrus","php","programming"],"hasMore":true,"image":"https:\/\/avris.it\/image\/micrus-rip_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/micrus-rip_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/micrus-rip_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022117.73347324239\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe PHP ecosystem is full of frameworks: \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/laravel.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Laravel\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/www.yiiframework.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Yii\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/framework.zend.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Zend\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/phalconphp.com\/en\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Phalcon\u003C\/a\u003E, and so many, many, many more... All of them built by professionals and supported by big communities. So why on earth would a junior developer, who has just started his first job, try his hand in building yet another one?\u003C\/p\u003E\n\u003Cp\u003EWell, here\u2019s why:\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/micrus-rip_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/micrus-rip_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022117.73347324239\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe PHP ecosystem is full of frameworks: \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/laravel.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Laravel\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/www.yiiframework.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Yii\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/framework.zend.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Zend\u003C\/a\u003E, \u003Ca href=\u0022https:\/\/phalconphp.com\/en\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Phalcon\u003C\/a\u003E, and so many, many, many more... All of them built by professionals and supported by big communities. So why on earth would a junior developer, who has just started his first job, try his hand in building yet another one?\u003C\/p\u003E\n\u003Cp\u003EWell, here\u2019s why:\u003C\/p\u003E\n\u003Cp\u003EWhen I learned PHP, the URLs I knew how to build and use looked like this: \u003Ccode\u003E\/index.php?module=user\u0026amp;action=show\u0026amp;id=123\u003C\/code\u003E. I had no idea, how to make them nice like this: \u003Ccode\u003E\/user\/show\/123\u003C\/code\u003E. Symfony knew though, and I could just use it.\u003C\/p\u003E\n\u003Cp\u003EBut I was used to coding things from scratch and understanding how they work internally, I didn\u2019t like the magic of \u201cit just works\u201d. I know, stupid, if I were still doing that, I\u2019d never finish any project. At the time it did make sense, though.\u003C\/p\u003E\n\u003Cp\u003EI was curious if I can replicate the behaviour. I stole the \u003Ccode\u003E.htaccess\u003C\/code\u003E config from Symfony, I\u2019ve expanded my knowledge about regular expressions, and eventually, I did it! It was buggy and ugly, but it worked and it was mine, and I was so proud of it!\u003C\/p\u003E\n\u003Cp\u003EAnd then I couldn\u2019t stop. Every time I had had to dig into Symfony\u2019s code and had gotten overwhelmed by its complexity, I realised how simple the overall logic actually is, even though it\u2019s overblown by trying to keep it generic and open for modification\/extension. So just like I did with the router, I also rewrote from scratch the event dispatcher, the security layer, the DI container and a couple of other components, eventually ending up with a fully usable framework.\u003C\/p\u003E\n\u003Cp\u003EI don\u2019t think I have access to its source code anymore, but I think it was only 10 files or so. It was crappy, didn\u2019t comply with PSR-4, wasn\u2019t published as a Composer package, and probably was full of bugs that I\u2019ve never found.\u003C\/p\u003E\n\u003Cp\u003EIt didn\u2019t really make much sense to further develop it. Nobody\u2019s gonna use it anyway. It\u2019s not gonna be better than any of the frameworks that have plenty of people working on them. I\u2019ve already learned a lot, isn\u2019t it enough to call it a day?\u003C\/p\u003E\n\u003Cp\u003EBut I took some criticism for the version 0.0 from people who knew better how to code, so I had to address their advice and to make Micrus better. And it turned out to be a great decision because I still had \u003Cem\u003Ea lot\u003C\/em\u003E more to learn.\u003C\/p\u003E\n\u003Cp\u003EThe biggest challenge was managing dependencies. I couldn\u2019t put all the modules like \u201cMailer\u201d, \u201cTwig\u201d, \u201cSocial login\u201d, \u201cCRUD\u201d etc. in one huge package and still call it \u201cMicrus\u201d. But I was developing all of them at once! I had to learn more about the internals of Composer in order to treat local directories as if they were packages, without pushing or tagging them (only later I found out about \u003Ca href=\u0022https:\/\/getcomposer.org\/doc\/05-repositories.md#path\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Repository of type \u201cpath\u201d\u003C\/a\u003E \u2013 really useful!). I had to learn how to organise the code better so that adding or removing entire modules could be as seamless as possible. I had to keep them consistent, simple, powerful, extendable. I spent hours and hours, and days and days, on figuring out their architecture...\u003C\/p\u003E\n\u003Cp\u003EThe second biggest challenge was the forms. They\u2019re just awful. The form abstraction layer has to move data around between the actual object that holds data, a form and it\u2019s HTML representation. It needs to map the data both ways, it needs to validate it, it\u2019s just a mess. At work at \u003Ca href=\u0022https:\/\/www.rocket-internet.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Rocket Internet\u003C\/a\u003E, even though we were using a Phalcon-based framework, many ventures decided to use the standalone \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/components\/form.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony Form\u003C\/a\u003E component instead of Phalcon forms, because that was the least troublesome one.\u003C\/p\u003E\n\u003Cp\u003EStill, they weren\u2019t simple enough for me. Sure, they\u2019re way, way better than handling the forms without any framework, but whenever I needed to do anything even slightly non-standard, I really missed the option of just writing down some HTML. Instead, I had to learn about the internals of the framework. I didn\u2019t like it, so, I\u2019ve spent ages trying to prove to myself, that one can make the best of two worlds.\u003C\/p\u003E\n\u003Cp\u003EThe same with the security layer. I really hate how Symfony implements it. It\u2019s a piece of cake to configure the most simple cases, they hide everything behind a veil of magic. But as soon as you need something non-standard, you need to go through their documentation, get into their way of thinking, understand their ideas... You can\u2019t just write down the simple logic you need, you need wrappers, voters, providers, listeners, etc. etc. I decided to try to implement it my way.\u003C\/p\u003E\n\u003Cp\u003EAnd it worked for me. I\u2019ve released \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework.lite\u0022\u003E Micrus \u2022 Tiny, yet powerful, PHP framework\u003C\/a\u003E that later become  \u003Ca href=\u0022\/projects\/micrus-v4.lite\u0022\u003E Micrus v4 \u2022 Beauty of simplicity\u003C\/a\u003E. I\u2019ve built a couple of projects based on Micrus (listed at \u003Ca href=\u0022https:\/\/micrus.avris.it\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E micrus.avris.it\u003C\/a\u003E). I had fun, seeing how easy it was for me to build apps with Micrus.\u003C\/p\u003E\n\u003Cp\u003EWhenever I would encounter something worth improving, I did so. How exhausting was that! On one hand disappointing (I wasn\u2019t expecting anyone else to use it), on the other really rewarding (it is an accomplishment after all). When I discovered \u003Ca href=\u0022\/blog\/the-non-magic-of-autowiring.lite\u0022\u003E The non-magic of autowiring\u003C\/a\u003E, I implemented that as well. I covered 100% of my code with unit tests (which was quite a challenging type of code to cover).\u003C\/p\u003E\n\u003Cp\u003EBut then, Symfony has released its version four. And it\u2019s amazing. It has \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/setup\/flex.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Flex\u003C\/a\u003E, it\u2019s flexible, it\u2019s fast... Maybe it\u2019s not as simple as I would wish it to be, but it\u2019s undeniably way better than anything I could ever create myself. Also, I simply got tired of building Micrus already. It grew bigger than I thought it would, it started resembling Symfony more and more, while I understood more and more of Symfony\u2019s design... \u003C\/p\u003E\n\u003Cp\u003ESo there I am: having learned an awful lot about standards, modularisation, architecture, framework internals, autoloading, autowiring, testing, managing dependencies, and much much more. Having created something irrelevant, but quite impressive nevertheless.\u003C\/p\u003E\n\u003Cp\u003EI\u2019m still gonna keep putting Micrus in my CV, I\u2019m still gonna keep most of my Micrus-based-projects running it, but I\u2019m not gonna improve it anymore or start any new projects on it.\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s been a wonderful adventure. Now it\u2019s time to move on \ud83d\ude0a\u003C\/p\u003E","words":1080,"readTime":5,"lang":"en"}}},"blog\/technology\/three-countries-three-types-of-design":{"key":"blog\/technology\/three-countries-three-types-of-design","type":"article","published":true,"meta":{"createdAt":"2018-08-29T13:35:55+02:00","publishedAt":"2018-08-29T13:33:00+02:00","group":"three-countries","category":"blog","subcategory":"technology","slug":"three-countries-three-types-of-design"},"content":{"en":{"slug":"three-countries-three-types-of-design","title":"Three countries, three types of design","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022322.47678018576\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHnklEQVRIiU2WTatl13GGn6paa+\/zeW\/f7nulFi21Wi3b+mgU4pkhCcQQQogNMmQQyCCEZOL8hIz8CzzzT7AHHhtPZIMNlhLwwJBAPpzIEgmyaNutvn0\/zj3n7L2qKoN9JHnDYk3Wgtq13vepV37+7k\/yZz\/6IUgSHogEnYAqbAdnPzQyQEXoCphCRBIRfPpFJM2TzCQSWiTNoZTCW2++zG5zQaExjiPX25GnV43wwD2ICFQgSb72139H+fD9\/+a9n\/6YSEcBJagKEY6Q0+EIxrExNqe1IAlMDFNBAchDUcHogUcyeiClxy\/fYPPsCeEDd+6ccu\/Nr3CkO86v9oQEbRzZbbe0ceDq6pJSa2E276nHpzx47h4n\/\/shCPz20Vt4JlWEeVHmKhQSIYmxsdsPwNS5cEcygaBFMLRgl0nTyvWTD9jsgtO793nxj97m9O49Fqs1ZkI1YxwG3BubzYYHX3pESRE8hfuv\/yFfvv+Qe5s9gfJff\/IX0PfMRDguwprEwpFwxEfIICPI1sgIwoMkcW8MEezF2FjhX77\/He6\/8WX+4E\/fxiNprRERmFXQglWwrkNKwWqldEWY9x2l76lqlNffJJ9dMJsviGKIN2qpFAXzQNMhy6GIRpYCHmgE+fg36HaLqhFmjFYpknz1r\/4BrPDkd79luVojoiSQCIgRGWQCCOXWvPLqWc9y1dOLUh8+wN\/\/gNp1fPTRR8xLQfrKTQbaRkoxxmEPEbzw\/HNEBKkBkcjRMdrPGNwZWpCqjA5dv8AzmfUzutqjZogamYmooSm4J6UUSlWhN4UUVqb07\/0zI0YthQevvEKvwlJhFknJBgmZQaZPnREHM9yD\/WpFrJY0T0omtrlB1FisVlxcXBIZNHdwp3Y9VgwSIqHWjgQKmfRFOTk9ZY5SzWhWEVWGYYBMhKB5Y1GmQiOS1kYyk3EcEFFaa\/SzHlOlT6WRyGzBydEMEQGg1J7Vao1HICqTloohIWg\/w9Qog8PlzjmdH4ML9vw9Sq1kgpkxL5VZNuZZ6UgUGL2hHngE89JRSiHqpApECFGSZDavlH7BODZ2uxtKKbg3IpJsiZkhQHgQ7kQGJTIZPaH2aAa6WkPtMCuYGcWUXowunRoBPqJdR99V3J3IZBhGmvukpwTMaBm0Uulmc7QY4cHNdkPX9agaqkrXdQCICOMw7WWMZPBESsWGHaiifY+ocv70CZetsVKh80ZVaLs9JrDb71itjqh9zzBOz6eqeDiZQQjsd4F0y4PNC8vliohgHAdUlTYOn4m7tUZGUvYtuR6gdDPKdsC6GTpfYmasV2tyu6WXZEYFH5mvK9ubLfP5Eo+gEPRdJdzxTNQUVUVqpaixOL5DRBDhbDbXLM6WdF2HiGBWyMnvqOrkskxonlg\/w+QSNUWKYaKsj9bU9Qrbb7FhwAehZFLM6LrC7Tu3GbzhzQ9cgQxAIERoVvjXd9\/hvR98D6Lh7rQxpkMRtJZ4JBGAFv7xW9+miICoMJ\/N6cwmRpRKwgSwaHRdR1eMXTg1k+j7yXnjiImACJlJCoTK4e7krKHBbhTGIVGETMVbsjy6w5fefMTdB29w9wuPOH3xZb748FWKwufYZlJ+FJvcEkE1O\/BGiOaUWc+s78lsWKm0CIJgarwcFhzQy91joWfB7PbrPPfya9x7+BqL0xf57ju\/4Gt\/\/\/UJASJkTnupJsz7Az1bTNFCpxmuMA1OBBFhvVqyubxk1nfUamROw9XUCHfG0bm4uuLk9m2EqWt\/9rf\/xJ0Hb+CZiCjjMJIkx+v\/QLRikkQ6GQctzTrj\/tkxVgwNRwRc9KD86WBkst\/v2Vzf0HUdu93A1fX2UJChKCJGsQIJT58+5ebmBhXj4uIC0UIGmBoigkfwzb\/5S0KmZ07g6uIZ7o5uB+d8UAyI\/R5vjXYIXv5pCDs4wsMRYD6fcevWLczsc4eYYaXQ9d3kIlVEhF\/95799pqftdss4jojKZ+EOgcikzuZEJGU\/jIzakeHooQAXwT1ozSkZjJL0qhyd3EKTKfdkTAnx0GoRaOEsl0sSCDEGdz5+\/9\/ZbW\/Ybrfsd1u0VNbHx\/hBM5FT0uznc0qtk8sW6zWlOW1sqAguQgqcX1wQfY+qIArzqpM24jBc4UDnBAT3CYqI4oyMKOP1J9xcnnN8epdYH4EITiD+uQ1qrb\/HIoX5cgnDnhwGUoThQN2zkxOW1ViQVHeqHUATk30\/ddPEnwArTEQSHFBRtkPj1x\/8kpO794gx2G5vsFIoXZ1QkUlG4O6IKlqLsl6vkbEByTjsaMjhT+WzS2qGiqKHFG2iFDVMDc3Enm2Qx59Qnl6hkVNKEOHWUrn4+H8wVUyN5XJFVzs0hRwb6kk25\/rZM67OzykeQXQzZHuDj3t8aGzdeXZ1jTTnug2sFfoUJEaOFotJbwddhgf++AkmgDt54fiTp4wvnjFiDC15\/H+\/opZKRrK53mCmbK6v2N5cc\/7JUzaba7RUXnrhBcpLX3gE55ec3D6hf\/Uh3pw7z58ymy\/YXm+w6FkW6BD6WiZQRhz4l1PisA4ZR\/LiklgqMZvB2Rmpxh\/\/+TdoWbm1XuHuLLrK737zGN9vmXcdtx48oNQOMeO5szP+Hzp7dXja0YomAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/docs-design_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022322.47678018576\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve lived in three countries so far, and I got some official documents from all of them (Germans definitely spam way more than the others). I think it\u2019s interesting to compare, how different approaches they have to the design of those documents.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022646\u0022 height=\u0022434\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAYCAYAAACSuF9OAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHnklEQVRIiU2WTatl13GGn6paa+\/zeW\/f7nulFi21Wi3b+mgU4pkhCcQQQogNMmQQyCCEZOL8hIz8CzzzT7AHHhtPZIMNlhLwwJBAPpzIEgmyaNutvn0\/zj3n7L2qKoN9JHnDYk3Wgtq13vepV37+7k\/yZz\/6IUgSHogEnYAqbAdnPzQyQEXoCphCRBIRfPpFJM2TzCQSWiTNoZTCW2++zG5zQaExjiPX25GnV43wwD2ICFQgSb72139H+fD9\/+a9n\/6YSEcBJagKEY6Q0+EIxrExNqe1IAlMDFNBAchDUcHogUcyeiClxy\/fYPPsCeEDd+6ccu\/Nr3CkO86v9oQEbRzZbbe0ceDq6pJSa2E276nHpzx47h4n\/\/shCPz20Vt4JlWEeVHmKhQSIYmxsdsPwNS5cEcygaBFMLRgl0nTyvWTD9jsgtO793nxj97m9O49Fqs1ZkI1YxwG3BubzYYHX3pESRE8hfuv\/yFfvv+Qe5s9gfJff\/IX0PfMRDguwprEwpFwxEfIICPI1sgIwoMkcW8MEezF2FjhX77\/He6\/8WX+4E\/fxiNprRERmFXQglWwrkNKwWqldEWY9x2l76lqlNffJJ9dMJsviGKIN2qpFAXzQNMhy6GIRpYCHmgE+fg36HaLqhFmjFYpknz1r\/4BrPDkd79luVojoiSQCIgRGWQCCOXWvPLqWc9y1dOLUh8+wN\/\/gNp1fPTRR8xLQfrKTQbaRkoxxmEPEbzw\/HNEBKkBkcjRMdrPGNwZWpCqjA5dv8AzmfUzutqjZogamYmooSm4J6UUSlWhN4UUVqb07\/0zI0YthQevvEKvwlJhFknJBgmZQaZPnREHM9yD\/WpFrJY0T0omtrlB1FisVlxcXBIZNHdwp3Y9VgwSIqHWjgQKmfRFOTk9ZY5SzWhWEVWGYYBMhKB5Y1GmQiOS1kYyk3EcEFFaa\/SzHlOlT6WRyGzBydEMEQGg1J7Vao1HICqTloohIWg\/w9Qog8PlzjmdH4ML9vw9Sq1kgpkxL5VZNuZZ6UgUGL2hHngE89JRSiHqpApECFGSZDavlH7BODZ2uxtKKbg3IpJsiZkhQHgQ7kQGJTIZPaH2aAa6WkPtMCuYGcWUXowunRoBPqJdR99V3J3IZBhGmvukpwTMaBm0Uulmc7QY4cHNdkPX9agaqkrXdQCICOMw7WWMZPBESsWGHaiifY+ocv70CZetsVKh80ZVaLs9JrDb71itjqh9zzBOz6eqeDiZQQjsd4F0y4PNC8vliohgHAdUlTYOn4m7tUZGUvYtuR6gdDPKdsC6GTpfYmasV2tyu6WXZEYFH5mvK9ubLfP5Eo+gEPRdJdzxTNQUVUVqpaixOL5DRBDhbDbXLM6WdF2HiGBWyMnvqOrkskxonlg\/w+QSNUWKYaKsj9bU9Qrbb7FhwAehZFLM6LrC7Tu3GbzhzQ9cgQxAIERoVvjXd9\/hvR98D6Lh7rQxpkMRtJZ4JBGAFv7xW9+miICoMJ\/N6cwmRpRKwgSwaHRdR1eMXTg1k+j7yXnjiImACJlJCoTK4e7krKHBbhTGIVGETMVbsjy6w5fefMTdB29w9wuPOH3xZb748FWKwufYZlJ+FJvcEkE1O\/BGiOaUWc+s78lsWKm0CIJgarwcFhzQy91joWfB7PbrPPfya9x7+BqL0xf57ju\/4Gt\/\/\/UJASJkTnupJsz7Az1bTNFCpxmuMA1OBBFhvVqyubxk1nfUamROw9XUCHfG0bm4uuLk9m2EqWt\/9rf\/xJ0Hb+CZiCjjMJIkx+v\/QLRikkQ6GQctzTrj\/tkxVgwNRwRc9KD86WBkst\/v2Vzf0HUdu93A1fX2UJChKCJGsQIJT58+5ebmBhXj4uIC0UIGmBoigkfwzb\/5S0KmZ07g6uIZ7o5uB+d8UAyI\/R5vjXYIXv5pCDs4wsMRYD6fcevWLczsc4eYYaXQ9d3kIlVEhF\/95799pqftdss4jojKZ+EOgcikzuZEJGU\/jIzakeHooQAXwT1ozSkZjJL0qhyd3EKTKfdkTAnx0GoRaOEsl0sSCDEGdz5+\/9\/ZbW\/Ybrfsd1u0VNbHx\/hBM5FT0uznc0qtk8sW6zWlOW1sqAguQgqcX1wQfY+qIArzqpM24jBc4UDnBAT3CYqI4oyMKOP1J9xcnnN8epdYH4EITiD+uQ1qrb\/HIoX5cgnDnhwGUoThQN2zkxOW1ViQVHeqHUATk30\/ddPEnwArTEQSHFBRtkPj1x\/8kpO794gx2G5vsFIoXZ1QkUlG4O6IKlqLsl6vkbEByTjsaMjhT+WzS2qGiqKHFG2iFDVMDc3Enm2Qx59Qnl6hkVNKEOHWUrn4+H8wVUyN5XJFVzs0hRwb6kk25\/rZM67OzykeQXQzZHuDj3t8aGzdeXZ1jTTnug2sFfoUJEaOFotJbwddhgf++AkmgDt54fiTp4wvnjFiDC15\/H+\/opZKRrK53mCmbK6v2N5cc\/7JUzaba7RUXnrhBcpLX3gE55ec3D6hf\/Uh3pw7z58ymy\/YXm+w6FkW6BD6WiZQRhz4l1PisA4ZR\/LiklgqMZvB2Rmpxh\/\/+TdoWbm1XuHuLLrK737zGN9vmXcdtx48oNQOMeO5szP+Hzp7dXja0YomAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/docs-design_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022646\u0022 height=\u0022434\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve lived in three countries so far, and I got some official documents from all of them (Germans definitely spam way more than the others). I think it\u2019s interesting to compare, how different approaches they have to the design of those documents.\u003C\/p\u003E\n\u003Ch3\u003E\ud83c\uddf5\ud83c\uddf1 Poland\u003C\/h3\u003E\n\u003Cp\u003ELet\u2019s have a gradient background, microprint, watermarks, shitloads of eagles and other things!\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-pl_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022885\u0022 height=\u0022500\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGBElEQVRIiUWWvY4lSRGFv4jMrN97e6ZnmUFoxWp2tCw+SCw+DgYSOGDxPti8CRLgIN5ihYW0HgjNTk9P7+2+t6oyIwKj7oBRRkn1cyLjxHdCfvvLn4c1I8zQcCIMJSCMTgMI1q3RmrNtRpIgJ5AIEIEIwoPaHHOnGlRz1ut9kIgIqjmbOyCICBB0CodeSCpcahBAHoYJb0Z4I6xRW6MfD0yXR3JSlnmmmJEF+iQoUJtRa2OrRkkJlUACPJzajK05SzNWC9bqVGvUWpkk8XR6oLUGwObB+0ugEmTdheXD1HNZKu5C3eDm9hW\/+PXv+eJvf6VNR\/7xq9\/QJ+VZSdwmKM0QN6QtRDjhjteGmxPhmBuLO0+SuHfhVBuimffv3jLOB\/7yxz\/w9HCPE7jvRYDQAmoL8o+\/P7LWgbvThbvvgjLNlJzpXr9BA+b5gIaTFEpJlOyoNyQ63Ay3DYoRHsTdHX6+kFSpmlktOF0q5Ew\/HsnDyMvbG7rtxLk2VgMiEwQeQeDkQ5+grbycEs\/7AbmdKeGUz35I3D8Q1jg9PCBdRpOS6kZOSl1Xxr7jME94cnCHwxFyYVk3LtW4LAvLsiK58Onnr1meLgyHmfZe6FNmM+dxc5YWJBWUTF5aUJJQRDBNtJI5psL09df48ZbjYWbqOo4l0bfGnJWkAr4PgJuRInB36nzEDgdGElmCv\/\/pz\/zzm2\/I\/cDvvvwRrTfS+IzNIKswdZkhO4sFa3OqB3ltgTehbUHGOR6ec+h7tBvQaSJpguSI7ELMGkpiXRZaq7RW6bueWitdVyg5YyGIwus3b6goeZxIOdOPI8dPvsdbES7NsTCyKknh2CcQyFsLxMEDzhYMaSByR\/7sc\/RwAJS+7xlUmcl0vpu69B0y9JgZIor3A+62j3VSPIKfffUVX\/7kp9B1mDlP54X5+QsQpeuU8MA82MzxcEQg31+MgiHuhDmROjQcUYXSoaLcv7\/Du0wLp3jDtg2rdf9A1xEI58tuZnNHVNiAkwU+jpTSER6UXCjjgeqB7sOFqpIBRAmBvNadGWYNCedl6imipNKTpgO5ZPpSwI1gr6iUgjVDU8IDhqkn54S54x5oUnpNEHAyZ318Io8jfZ\/p5yPNYEdjAL4Dlt3YWXBclGaBAFJ6sghaMlIyWROfvHpJ1zbKuhHbgpqBO\/M80Y09tTa86wDBPUDAVDGHzZwiQnMnAso4Xkc82GEvuDuBIB4o1hCvlCSoQD+M9ElJOSO5EPujpJToh46IIKdEyQU3QzxIshNcJVD9GA174UkEDxBRCDjezPzgWeHYK0kDd8OCXaQo+cWknFdj25wqkPuBFLErT7qbFCAgaaIvHVE3pmkkZUV0zyoQzIzLWpmm8SpIrlfgzWju5H7iZhCOfcY8cd6c0+o8rk65eUY2D26GBINiLhwOM+kagqZKROyxQNCswZU5l8tCLolpmsmSaAIBrMsJs0aZDiDXygFRIZHI44F\/f6gkCYZO6XPwqlNezMJl+0C+f9z2Nij0pdBNM7JWrFUMIYBmBlkRUSx2U+ecKbn8vzUKKkrXdQQQEWhK+zDE7heAbpr33HTnaTUsnJSCqQh9SeSdts7a4Lw0ogzo4wMADaGZkQlaM0KFVDJdzgjQ3P73cwQsgnmeCRFaCBffVchVtYgyzgf6aaCen67vCdXg2y3wqOS5g\/PiNA9UlH6c4T9vsdYwFZZ1pa0rkRNJhako1YzwPd3j2kIAuyY+omwOFWgRNIKUCyqCJUXGZ+hyZkqBhVI8SBgWSh46ZSgd69aoruRhgMsZXze2COZpQrrCTU4MbmSNfZFzIUL3PlxFFQlcdsgR4CLUALmuGuaOhRPDkQ\/Lv0gEORslCWMnREA2d8J3Bs3zRBYlB9cTUtyd\/JEVAeHg5rg19LoxtlqR+xNxWQgHe\/kc6zo2YHU4N8OJfbGzRurHXRywbtcRxhERcm2Owq5cMk9Pj5zffUvbNu4eH3m3VdbvTtxmZQpnTMrtzRHxK26BuD+hj0\/E3Qe8K9i6sH36iosHl4AthGoNKR0toJ\/m3VMEHvvJfWT3fwGDmuzYYzOG2QAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/docs-design-pl_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022885\u0022 height=\u0022500\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003E\ud83c\udde9\ud83c\uddea Germany\u003C\/h3\u003E\n\u003Cp\u003EWe don\u2019t give a fuck, just print it out. Yes, monospace fonts are fine.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-de_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022934\u0022 height=\u0022527\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGLElEQVRIiVWWTW9mRxGFn6ru+2H7tT12PF\/ODCEBpAhlF4kFUlYsQbCDHTs28Cf4aWzYI7GADSGECVLQxLFnbL\/3dtcHi+uMxF1edbdOnapzTskff\/+rTDOIDuHs9yvWV6o6kxjmztoabsHNvfH6prG0IAMyDffELICkKJCJStI8WXowKqgInkEmRAhLBBYQbJ8HeEKPoN7tG+6GZlJwSEdEWBssDmOFg6HSMHZzZS7C233nm7fG0nQDUoWMxCMQhMikSHI8KZEbME9hUKglOdRCyw2URZICKhvw6m6szchMcAMPahpCEiRLSzg65rPf\/IHLH37Csuxxa7g5Zo6QuDm9ryz7hXXdY91Ylj2tLXhv9N7YLyvuwTAUEOEvf\/4TX\/79rzTASJpDZlIJRyUxc3rvhDmSUEgkg9P3nvLBT37OTSssn\/+To90OESXCuXh8gWQS7pgZ7o670drKfr8nYvvfe+fu7p62LhwcHjIdTHz5xRd8\/re\/MhahKhRJWghVxSGCIoEWWD1xD5oZlx99zCef\/YL7pXFyeoKZMY4TxycnmHfWtZERhBsZ+TAPSe\/ONM1EBtoatQ6M40StdTtD8vTZc1SExQIVmAeYMqmVQEpy3w03QwmC4ONPf8pnv\/wtX716xcunl\/TulCqYGdffXuMRRDhnZ2f0TJBEi1IYqOOIWcd7B0BVCQ9ElchAInj0+ClDgaEo+xbcNja23twuVBUmTboG+258\/8ef8rNf\/4672zuePr\/kv19\/jaqgpbKuC713Hp2dcXR0hoigs5AIAngYGkHkpiEphVor1rc5LQLqzsWTS3ooQjBWoaTQLKn7pUMmVWEscDQIT569oDXn0dkFV1evGcYBUeX4+JR5PmBtK0WVZVkQVQTB3SilYOZkGmbbuwiYGWZGZBAeDNPIxZPH9FQkElWhSDINUEnDXXF3WgsGVRClSGGaZjJhf3fH2fkFZp15PmcYRnrvlFJorVFqoZSCqKLqIJXSC6UoHo4gaNnaJ5k0c+owsjs+5fb6Co\/ESUQFPTkUjg8CSSciaR70FE7Pzui9M08HfPSjjzm\/eMzh4TFv3tzwn69esazL5jtF0VJBIDOICG6ub\/j2mysiBUFBBFWlaCFQVIRhGDh57zHB1u5EiBQ0IpkqnB9XdnMhE3bHp5s5riuRwc3NFa9ff427MU0T711cMA4jmYm5A0lEkpkkyeHRjtNH57jZA1CAgohuTIqgWnj5\/nOGkngk8WCoVUi6JbUUDicoquyOd++qBbi+uqLWysG8e3hUtqproURhnme0FFQV6x0RRXIDiGxxEpm4GxmBmVFK5f2XL\/jXodBCeNuC+55Uj9zmBuieqAQHh0dEJAKUUnl++ZLDox3uDkA8aCrNadYpZVORCJt1iG7MyYanlkqkU0slNam1MwwDj1\/8AICDksxHQndF53GzbOuOyFZVGWcyt2za72\/56tW\/WZY9IoL1vnkKbAxGUlQZamUcBlSUUpRpHKlFEQmSLXzNjbWtuBluzqMnl9x32NvW8kGD+ubO2E2VUmHtgVlSxwO6GTfX1+x2R3zw4YeICMuyB4S+rpRSyEzGcaS3RgLh4O701mi9M4ybyoaakIKIMNRhmzWB3dk5CVvyd0EEalXh6rZzNClTFcKDeXdKHQeGYcDD+fb1FSenp6gqpDCOI6qKqjLN84PfbMZYa2W\/7DkcBiKMcZwptZK+rR8poFYwD45PTtHxELE7PJJ00KU7Y1GWltwthhbh6PgYESGBZVnY399zc33DNM5M00gdtkzKTNq6BWlvbTNAd8iNKdVKRrLu96xtZVnvCQ9qLazrSh0qh+fPWHoSsa0g9c2dUcQ4mgtrD3oWxvkA8yQi2O1OOD+\/wH1z29ZWMpxMGKcZ606pA2b2DiQPTAGIlncCQQUPJz0QEYTCyZNLXn3xD6rmti9FJD2SwhYfZT5ku74p6fbtW27f3rCuC5cvvscwTEQ45bt2IdtMPADJTFpr7xRZhC1eRCA31hHQLgA8fnZJJDQHS6jguMN9CoejcHK0A9kON2uEGebB0+fvM88HDNOItS0G3P1hN4r\/A\/Sdf2Umy+3CPM+EbOc9ApF8B\/ji8RNUhUiISP4HRQstgNITI+kAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/docs-design-de_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022934\u0022 height=\u0022527\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003E\ud83c\uddf3\ud83c\uddf1 The Netherlands\u003C\/h3\u003E\n\u003Cp\u003EWe\u2019ll just put a small deep-blue ribbon on a clean design. They\u2019ll know it\u2019s a fucking ROYAL letter!\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-nl_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022885\u0022 height=\u0022499\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGRUlEQVRIiVWWy49dRxGHv6rucx\/jedmeOPJ4jI3HLxJbQB5YgsSIh0BIsERiiYTgL2IFG5ZsEAsk2MCGFRFShImNIY6dOH4747nzvPee091VLPrOOGmppaNzpK5f1\/nVVyW\/\/PFX3Q1ww0rGzBAcLKFkzCDnQs5GSvXZ3VBxgjhugogAjpmRC3TZydloi5OKkQ2Kv9yG4w4ujiAIjs7OiMWEUgq4k7KRuoyb4+bgVSgOUYUQIQZFRbFiuDvZjVSMlB1zAYHBwgKn1y9xcv0yd268z6P\/fUAyI5uQzWkNuuK4CwbYTKgD0d1wZxZAERUARBQrBTOnJCNTb1A1GkFAHEQDr55eY3X9K5w8d5nVi1dYWT1DSgnD0IUVPvnPvwkqSHD6EeYQUhHGyZkUqye7g0A8c6Kh6wpdEqZtZn8amLaFLjspg5mACEEEUI4sLvHq6fPc3sgcWzvHr37+UwZz81gxEECEbAWbXerq29f4028CWgrFAKm\/J6iz2BcWPGBANiMZRBVj0ChRCj1x5ntQitJl6GyOueNnWT55jtOXXmf17EUWjq6gGvjD3\/7JX\/7+Pk1\/DnMhlUKMERxEBFVBBJaOvcLa+cs8vXuLEBU3KO4kE6ZWqMtRgX6AuLVnRIGgjhusrF3k3Jvf5+jaBY6ePAMa6LqOfm9AKYXptMURvnbpDH\/86z\/Y3JmwsrxIE\/uICIaB28zoYGZcfvsdPv3wNl5AcBxHgKCKe7UBKiR3FKArxt7E2W0FG6xw8Zs\/4fjaBUQbzBy8Hh5CxN0xNy58+RTXv36BzZ19CApBcQFHMPtccThcufYtkteA3czUbYFxhqnBpCiT7CQX4t6kmgoHcePhnZuIOyBVvTkiimrA3WsWiuHm\/OJnP8LMqtUFzH32rGyPXnBkfoHh3BFOrJ5m\/cI6j+59RFucYpAd3EFFKO4ISnGIbTasgGBYMWy8xbPH91k5+aVZ2oUYAwApJbquI\/YajCpOpAr\/\/HKEpjckl0Lbtogob75znfzZXYRAdqfLziQZbYFpgVwMc0FVKuSKGbkUcjE++e\/NWenXYGbGeDymlMJgMKhoEA4zdrBEBLf6S5tBn5QyGgIalPU3vs1o7GxPCuPWKMUYROfYENYWhNNLwskF0IppQ9WJoWbiwZ0PcHc2NzaYTibsbG2yt7tN27Ywy8qB2ANRhyb2Csxef8Di8jKqEdHAyqk1Tp1\/jVxgmmC7hY09eLIDj7aNp7vO9lTQhWHkyDAy7AWaCP1GePzRrRkEnf6gj7vTTadsjV4werFB0HAo4KWQlxlTVTQoGiMSlRACMTZcffeHuFTqDyMMG6GnhiqA0GYjTlojADEIsVE8OD7ZYHfzM44eewURITZ9lpaPV\/CpUNwAUNWZkSvFD959Xqy713cIb3znB\/z+t79GS0uoVURUGOjB9UFzqSW4u5\/Y2u\/Y3Ets7iY+vXMbmR2+fPQosRdrSJHaMmYADKrEUHcI4QtbVYkxVkEqzM3Pc\/Xd79EVaE1pi7LTCaMpbLfOTgs66EFUQ8RnTdUwNx7cuYmqgkjtX+7knJnujxnv7+N4Daw18MGOMVYveoXigTiAkgrfuP5dOjvo7qBSL2YzDMQjg0DJYD0oCXKBlIzRwztfMO7WaIt+v0\/TNAyPzKFSO3UtioqH3CVS6hCB2DREjeSuZXtzk63RiOl0wvziIs1gDs9jBMHcMXeQ2jOjW0GlmlLEEXGaRhg9vYe4VXOqsLKycoiAyXTKYDhA3UldJudMTpmFpUV6vYbpeMLGkyeMRi\/Y292lP+gTYqQ3HNLEPuuvXeXujffqaCMHE1H1YDRzUnJySbMxRKqw3DJ6\/oiV1bO1yrqOlBKlFIIo451dHGc4NyDEHqrCw4\/vsTXaZHtn+9BD\/bkBTW9A0+sTQkRi4PW3rnHvxnu11Rygow4CRFUY9IRika4rtNnIxcml8PzBx5xYO4d79cvuzg5N0xCaQK83z9PHj\/jw9i0E2Nvdrd9iZHFpGQmBEBuaXn+GgYAEBYErb13jz7+LiOU6oM34bg5xf1pmvQuiCP2eYAbTFl48vn9YyqrK4tISz5885vmzZ+xsvSClRNM0qAaWlpcJvR5NbJDQVIM3TUXADJwmNc7C0jLrl69w\/\/a\/EOzQMuD8H9lWv8H7GQg4AAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/docs-design-nl_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022885\u0022 height=\u0022499\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThey\u2019re killing it with that modernised coat-of-arms on that blue background notch \ud83d\ude0d They even put it on government buildings and minister\u2019s twitter accounts.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-nl-building_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022499\u0022 height=\u0022885\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAkCAYAAACJ8xqgAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHOklEQVRIiVWWSW9lRxmGn++rOtOd3O2x7Z7SQ9SBRIBIIrpFgA0ghNjxA9jyM1qsyRokEEKwQEiJEEIIiQ0LVp2k6Uw9N6En221f29e+vvfMVcXiOiYsjnSqdPSc96vhe1959w\/vBGstK8sL9LIOIQht8OADjfOUZc7O7gjnA50sI4RA3TQkSYIxhhACIQAERARd3xzSOk8WpwiCiGBRXOupq5qmcbN5hKpqaFtHFEVYa2cANRhVVHU23huNKasa5z2Nc7jg8QJVXeGcQ1VJ05QQoCwbojimk2bHUGMUNV8AdroZu7sjnHOUVUVZVVRlSeNaosgQRRZjDM45Ot2UXqdDCIHIWiLzP3VGFSOKPX9mFRFBjCLAZJpDEAIBVY+1FiTQ63fpd3tAII5jImtxzgGgIeBDIOCxF8+fQVWwkUU0MOj38SHM\/mgM++MxH3x0l29dfYM4ivA+EFtLEGZCRPDeg3MEVWxVVcz1+wigVjFxjIpi1PD8xRbv\/vXv3Lj1kI\/vPuanP\/kxi\/MnAHCuPQZ+rjSEgI72xxwcHiIIVhQjgjXKxnCLP\/75bxhriJOEh082+dnbv+K9D2+jRlBjMHZWhTHmeJM0iiJ6nezoCMw+eLb5gn++f5OF+QErpxYxkcVElrwY8+vfv8Mvf\/cnqromiixRZLHR53BFu1mKUcEHDwRUhUmes76xhU2S2XFQxdgYSU4SjOVftx9x\/ee\/4c79zzBWj8HGKhrHhsa1VHWFGsFYpShLqqohzwuGO\/uzkuJo9mRzxElKXje8\/Yvf8GK4i7UWay1RFGFqV10PQTl\/7hzGKJG1bA6HrG9tczDOOZzmHE5yxMQYa46XxVol6\/R48ytXWFqcR0R4vv4Me+PGDX74vR\/ROk9AMdZycDhlWtSIKgejPUZ728yfugQiqCiqYBQ0OCZFwZ17t3n\/g\/cYbm9j+\/05DvOczeEI0TEvXzhL0zomk5zVtRWi7mUqOTFb43rMEEcpJS91V7iyOs\/dT29STCeUZUWaZNjXX3+TPJ9SlBVg+PeT57P72olZW11gYzghTS1GHF8rd3lQHrCfVKylMN9dmF3DpAOa4poC++DBbVQD\/bmTLC4scWZ1CWMD588uk1RjpG1Js4i2DpQne1xYnFCGVU7NX6TbPcnuJGc83mZjY51JnmOyTnJ9uLvPaFzyg+9+h6WTA7Z3dtkdbpH85bfog08Yn3uFLEtZGpeU9xzerkJ\/wIPPHjKpHnEw3uPs6UsE77En5k7Sm1tmaXGB7Xv30NOrVE1NWdW0X\/8+G5WhqWrSJCI2gh1twtZTtk58k+XlFepnFXMH+xxs3CS9cBnT62fXKWrOXHiJ9a11+vPzTJuW9Z0RHRqe\/2dEdusme\/NztAvzPF1YYZIYmEtp6pq51TWKbp9pnNC0DWZt8cT1k8s9Nh\/f5\/KrX0V7GU\/u3KcRS+0Ntw+VT6Ml5jLo9zIODrZ4sveQfDJkZ+cpReXp9AYsLi2SxDFWRZg2BWINLzaec\/XaNe7evYfF4mzE6eUuEqagEYejXT679w\/yomZHlaJoeNUOCB42N2FzcwO7W+ZcqoTG9Pnk9nscTIeUreX0hS+TGUuWGHpaosEjfsT+OGcyrTFq6PcGNPWsGSdxynQ6Rb\/92huMiwgclPWIjz6+xXBrnUQMdV1DPaWqK0J1wHg8swrvhBAURFhbO01ZOZx37B3sY8ssQkUQa2hLS14UtNvrPLz\/IQsrFzk8GBJcy+7eE\/rdHsYKnSzlG2+8xfhwjIiSJAkvXgxZWzmNHe09xcRClmXsjh3GWMAgEtFWOY8fPyPOBrRNoGkahJQza2dJkpTXzr9EXdV0O13iKOLxk8fYNJpDBillUZKaAVmsOB\/Y390hiWJcPcbGAhJxYrDElcsd0iRh0O9S5ROaumbQ69EaeOXSeeTqtVeDd+2sOaqSRn2KwtM0DWmnQ1PXEAKxFdTEDHopX3r5AiIKBFw78xOCQ9RgV1Y8ddXD+wTXxhyODwlHBlQVU4zokbMJzlXsjSqmecGJXheANI1onUdQvCh2OjlNkRe4tgZfYIxBTYyIHPU\/cM7PxkfO9tHtB1y5eI5TS\/N4D0aFgKAhIG9duxoE\/4XgE1BVwiwB\/d97CAHvPd47QoB+N+PiuTUW5gcIglGwkVVUDBwZtogcQ733x1AIMzVGCQQkBMaTnFt3HtHvZpxanufc2hI2iiJCCMc2+jlERI5Vz8IaIGDUYKylbVo8LeIDeVnx6PEGzzeH2KXFAU0LddPSuJzWOXCGtglHicogAk3THsHliA4SQI2ZiTEzhp2GPQp\/SOkmBHWgHrGKJpa6ESJNUW+ITYxKSlW1+DYgAkmSEIKnaVo8MwF2Z\/wUVSEAvvGoEZCAp0Ei8OJwrsWJJTYWNGAQvDP41iDOECUG5xW8w3bjlNo3xNZixdJ6T+0bDIrDE\/AEgSY0OOcIBCK1OCr8UcDqJh3GxRTnPP8FZ0ywmplbqBMAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/docs-design-nl-building_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022499\u0022 height=\u0022885\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-nl-twitter_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022413\u0022 height=\u0022322\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAcCAYAAAAJKR1YAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAJpUlEQVRIiZ2V229c13XGf\/vcZs5cOBxyeBneRIqkTN1sxTIrWWocxU0cx4gDOI6bh8BJmgJFm0QP7VsLBDDQl\/Rf6EOLPsSAmxRomyJNBcQOakeW3UgWGFqUZEkc8To3zvWcOfez+0BKZBylDrpe9j7nrP3t7\/vW2mcL0XdELn7qFN979UWSd5Z54\/0b5JImC4eP8pN33yLUdI6fe4FyuUK3WWX+5GksyyY9+STZlEm7ssLmrV+zfO0yMyeeYqKvjy\/lQ7RKjfvNFvl0mnMjj5MrFLDtLs1KlVw2z0\/XrxH5IYtDk7inPqBtdblxu42GZtJoNamu\/pp2Y5t3V1ZYGC9ydGKOzUqZvtEpVF3DcmyqlRKF0SKKkcJtbZNUR2hUytTLG6AKilOzdLZLlDplnhmYRO9pXLM2mDcrdLpdVFPDsrqstytUWg2EH9DrG2Y0U2RuPs2xY4MoIuiREAFxy2Y8XSCX0qk0q7x18xrHZw6TTug4XoBmJPCDEKtZJ53J4rTKtJtVAs\/FcW2MRAo1iskOj\/NeqQQo5LMDbFZ32LTKrFrbNK0WPS2i1m1RsVtohs5YrkAPCbqOOdCPJqKIw1NFZgojbN0vkUSSTGpcu7XC0\/NH8XwfEfr4PRu0BAMjk7i9DnEU0Vj7EFOLuPC5L3Bj6RqtVhVdUWg5Dl7goggTOwypO21SWkA77KEFYJomQ24GT\/qUrG3uXF1joqXTczw0KWFoIE9XaKyuVuj5Lm0fTh0+ghNJAhlT2bhLf36IViuPomk8eWqBsXyCyG7Sae7Qsy1OPPcUer5IM4Bfdm6zWi8zPTiN50cMJzIYuo6qZYibAe2+iCF9iJQuCaUgldIxYo9eEKApMiCd1vmo1yYxPkp\/9Q71rkvg+xwqTmHXNulLp4mNJGfPP8MXzx1h9cPrXP6fEkQxiYSBpggcL+BWe5lLdY1nT32GwuPjpN9Z4utPXKAd7nA0P4rnCigIVip3qLWb\/PGT53lzbYVDjxnMzw0QxBItkzZIm2mQgm18bNcjZyaZm5ii0elxanqBjW6D0ZERPn9mhl\/87CeEUUy33YEowDSTJHSDMBbEkURKwc+v3+bKyhp\/\/+rneeLqLd5crtEIXAajLJbX40zhEMaxE8R2wLpV59n5EYQuIIxQsukE7U6bbrdDo96i2nGJZIIwDPnPX73D29ffp7JV4osXHuetS\/9FuVrhvV+9y517N9mqrLO1eZ92t43t2AS+B0IwM5xHypiLP7yE9ewCL333a\/hrTdrbFeLVOrmJYRa\/8QL3Uh0U3SObUfGiiI7toY4XJ1+bnp5CNwzWNzZwuz0+fewEq+V1ur02a5U63\/rTV9kqlWh1u3y4fJ2Tk2N87sghvnxygdnBPm6ur+OHEkvqnDt\/hmdOTvOpuQlqOzuE1Xt89txpJk\/M02h2cDsdjv\/Ntyl9cIP2lXvMFYr0zTuEUhLHoCmaguM4GLrB4cFRiiLJv1z+JUKRmAnB8ECOkwuzXHnnCtVamWxSZ6E\/zfHBHJPjYxzNZkBV+efrt5FqmkLWpJDNUOvaFPM5qpUVLt\/dYqpe4\/Sfv4IMYWd1i\/uXrjKQG6akf8S0kCBBVRXU2ZkjrxWLw\/i+x9Wl6xwbmyKIHBrtNqmkyvMvfgnftunZFmubG6R1hWLWZHowj2FoJJNJVEVwbb2CRYLlrsrVUpmNeou761vMmT5eKNlcusNY1qS9WaF88x5a3WFnq86h2WFSY00MM0UUS9TCYOG1MPBot1oMFQrUXYvZjMLRTIJatcEzzz1HpVIjCEMs22IwlUACPccjS8ybSzcYzqVZ6\/RwIkHTDlA8i9Buk1MlY0notFocKo7TWFrixq2PcDcajCX6ubW8wtShBYLBKlILUXUNzTASpFNpQt9HCIVUOs35ySKy0WCj0WRouMDa+gZRHDMyOEhGOuRVwc3tCmcX5vijsTFyuQwvujGv3y4zavhouo6qaYg4JpQaMpL0Gxk+eP0KgfB4+aWvkO\/rx9rp8vrlS5w20iSGXIbHC2hh4CGJkQK6dhff90geKZIY0NC1BIqiEMcRqBqqkcAIQggcVKHSbFgMJE0iL6DtR2iGgWoY6IaBqgBhiCJUfBExI\/sw5QhVabF0a5l6x2bE0\/jh7WVWrTxbdo\/8sZNo3\/z2txjI94OURHEMwGMjeZQg5KtHjnP4sSMsLa8QxhIPgS9DNENjSGoIVO63OxT1Pt6vd0EooKoIVQMBQgUhBZoumPjDU2T\/WqeITw+PJAYKKn8mKhSH++h6PkEqi3bx4ndACJCSj8cJQErJmz\/\/Ba12F2kYuLFJN7bQFJAyIJvNsbVTZ7vroCYSqFISSwlIiGMiCVPT04w8v8jI84u\/tceTiN1cwHFdFAABCCFgbzw4V4TC4pk\/QFFBUQQgaDkerSim7Aest1pI2yOZSBAHAaHnErgugecRBSG+63H26bMPcQ9i74775Na2y7uE2HPikSHg0xc+Qy6bIw5D4iggCiW+7+K7NqplM3zms0wffwLXdfFcl57j0HMcHNdhoDDI0+effjT0ATZeGLGy3dondPDjx8M0Tb76tVcIA5\/Q95BmBulHmGaWuZf\/hMHFC9R2mqzVmjS7FlbPxrIdIin5i+99B1VVH4n7myZIigNZNMvu\/U4iB2NscpKvf+NVfvCDv8PXDJxuiBGaLCQylO6X+O933iaMIlbLO+iKYHqiyMW\/+kvyhQKftEe902W70UZKEOu15u+o1W+HIgTV7U3+9d\/+nbfffo+XXn6F4kiBH\/\/4Da4v3yAMQwgCXnjhC1y8+F3MTB+\/D7iqKOiaQCAQ67WGFELsLpRyt8mkQLI350Ep5e5BFAJDVej1bDzHx+n1eONHPyKVSjF7eIbFxafo6+8niCV7VxQIidjDkey+FAh2EwRmQiefSQEg1usN+TBZyoe9JB+Sg324\/ZB7eLsnB2Ipd0XIfQGwKwwhDsp6JKFcKsE\/\/OM\/fbJDG6W7\/MdPL3H27Fm0hE6lXCNnGlSbbWZnp7n+wTLzczPUJ06z5Uu+eUjdoy\/3cH5\/hyzLQntAff\/3JA4+kEplWVh4DKvTZnBsHNNMUJyYJJNrstPsMDE+iud7DCUhVpSHZdo\/tPJA2R8dUkriOCadTn+yQ57ns1WtYag6STOB4\/pkMylSZhJN1fYkPGjdPSXi\/+eQ7\/soBx16ODsgKAwDbMfH0ASRlOT7sziOSxBG+wuFACGQQiL5+C30yQ4BBEHA337\/+2gP8vcxdlk\/iHQ6zYn5md0N95o+bSYfuvhxOfCb18F+\/f9vUvfu3qWxscr\/Av1E3T4B3kEKAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/docs-design-nl-twitter_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022413\u0022 height=\u0022322\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["design","document","government","official","template"],"hasMore":true,"image":"https:\/\/avris.it\/image\/docs-design_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/docs-design_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022161.23839009288\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve lived in three countries so far, and I got some official documents from all of them (Germans definitely spam way more than the others). I think it\u2019s interesting to compare, how different approaches they have to the design of those documents.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/docs-design_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022161.23839009288\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve lived in three countries so far, and I got some official documents from all of them (Germans definitely spam way more than the others). I think it\u2019s interesting to compare, how different approaches they have to the design of those documents.\u003C\/p\u003E\n\u003Ch3\u003E\ud83c\uddf5\ud83c\uddf1 Poland\u003C\/h3\u003E\n\u003Cp\u003ELet\u2019s have a gradient background, microprint, watermarks, shitloads of eagles and other things!\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/docs-design-pl_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-pl_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135.59322033898\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003E\ud83c\udde9\ud83c\uddea Germany\u003C\/h3\u003E\n\u003Cp\u003EWe don\u2019t give a fuck, just print it out. Yes, monospace fonts are fine.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/docs-design-de_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-de_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135.41755888651\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch3\u003E\ud83c\uddf3\ud83c\uddf1 The Netherlands\u003C\/h3\u003E\n\u003Cp\u003EWe\u2019ll just put a small deep-blue ribbon on a clean design. They\u2019ll know it\u2019s a fucking ROYAL letter!\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/docs-design-nl_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-nl_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135.32203389831\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThey\u2019re killing it with that modernised coat-of-arms on that blue background notch \ud83d\ude0d They even put it on government buildings and minister\u2019s twitter accounts.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/docs-design-nl-building_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-nl-building_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022425.65130260521\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/docs-design-nl-twitter_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/docs-design-nl-twitter_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022187.1186440678\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E","words":123,"readTime":null,"lang":"en"}}},"blog\/technology\/redesigning-a-website-stos\u0142owia":{"key":"blog\/technology\/redesigning-a-website-stos\u0142owia","type":"article","published":true,"meta":{"createdAt":"2018-08-24T15:23:40+02:00","publishedAt":"2018-08-24T15:22:00+02:00","group":"redesign","category":"blog","subcategory":"technology","slug":"redesigning-a-website-stos\u0142owia"},"content":{"en":{"slug":"redesigning-a-website-stos\u0142owia","title":"Redesigning  a website: Stos\u0142owia","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-redesign_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022299.375\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAWCAYAAACosj4+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFPElEQVRIiX2Wy28cxxHGf1Xd89ql+RTNWJYjSrIs2TBiGHAeOgQ555\/KNfApyF+US2zlZOQSCApgPSgnlB0RJJfk7s6ju3KY2eGMKLqAvUx11X791VdVLTFGo7PnL5\/x3XffEhaQe8\/N2\/vs3b1DM1\/w34MDZifHzMOcqql59Ovfs3\/7DgBN01BVFd57zPp0qCp1XXN2cUFV1WRJgqrinOPvjx\/zzbePyYqCIi+Yz8+5u7+PF5E+wZOn\/+Lrv37NJC3YTTe4tX+P\/U8fUs2XvHj5bw6PnnHRnHP4wwl\/\/tNfuLN\/FwAR6X8AZsarV6\/Y2dnh6dOniAgbG5tcOAcGm5vrfP7ZZ7x4+ZLlcs4nH9\/l0e8ekaUpfnijvV\/s8dVXv8F5xWfCrc0Pufn+B5T1ET81KfduPiDWxsP7gb3dvREbQ2uahtlsxtbWFr+8fRsQpANa1RXHx6c4ifz2y19x\/8GnZFlGjJGyLJFhyaoQWdaRECOpgmp762iQKoQQCCgiQuodTltGQgijkq1+IQRCCCRJMgIcY6Cqao6Oj1lfew91StLF+uFBiQFtShSwCDiHqEIIlGZ453ASwQATwPWxQ7ZW5VNVkiQZ+VZAi6LgVlHQNA0xGs4pIGMNmSg1nsILdTQaA4lGFXV1gBANMUMd+EFsmqY9E2ZGHYzEXfpHF\/cZP1Xn\/GP2gj\/uPmDDZ5c+G8CvqpL5fHGlU1qa4+jbZDLpATRNg5mNAL348ZAb023yNMFhNM4IZmgIeC80qmSaYmYMSRkBKptI3QSK1BMGeq0jTDw0BjGCCHgF7RK9C9A8BFKEaIKzgBMDFdCRSvoSr2zUZRIbQrngvGwPmRnOOWKMnDHWyWQyQfw4ee834+L1a9KtLVLvMaD6\/jkne9uEGNje3gbgoD7kA7\/Lmk4uAY001AluCMbMrgy8lWCHscObGlACP56crDy89+FNXFVRLSveHL5BVdnJ1lnbmlxlaAVAfIKfbuClY7dr6zoKmXbtLIoBKFfqP2RpUkxQ105lDLI8Q1rUiEjP\/CpmhWHMeWgI8wvCW7cWEaoY+0QArijAuVH4Ckw0gzxBnMPakcjfTv\/DH9JdinyC0zbOXs8wXyJrWR87FnVZUlVV\/werDptOp\/ycvUvUBwcH7Ny40RWsHQvHxycg4Dvt5VlOUeTXixrnCV4ofDudzdqOmi1rcgfRIEQQMVLv+0n9NkNtKs\/pySlI+31jY4M8z6jqGosG0o6ZoshHcVdKZss588GnFUsXgzkkIvjJBKfjlTC06WSKOu0KBlmasgwleZ73eZ8vXuGiZ00vKzACpKp470fUiwghBGKnoRXd7i39DC1ahBTEda8A4J+LJ3w0fx\/nPd55ROBOdotCi1HsqO0DQoVDDZq2NqgYlSkeQwzqYEQznDfcNW2vKGdHMxBhe2sLEeGL\/CHzuKCqKqrY6lRUKYpirKERQxbRpqQO3QEzojo81tVZiKHpfNeXC0CdQ1WZnZ1hZkynU9I0Jc9zRFqGq6q+MjrG2x5G29l737\/wVoHeXx3977I8yxEV0q78SZIwOz1HRNlYX8cCzP4X0BuBYk0vAY2eBuqoJSHRiDqH0ZZxWdbte8ggli3dRZbir51DkWSakKYphiEIT8pnfOT3WCwWlEdLwCjWC\/Lp2rjLRqsjNFDNqYfUd122fKvLLPFXdtlQQ0evj9jc3Ox9n6\/d56K6IE0TMEjTpGf72tXhvSfPc1xX\/5U1TdPvr1UCVf3Z1ZFlGYvFEhEQUSZFwBJHmraL1DnHs7M33CtSpi7tMfwfMXi5tPgkQxcAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/stoslowia-redesign_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022299.375\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThere is a website I\u2019ve created many years ago, \u003Ca href=\u0022https:\/\/stoslowia.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Stos\u0142owia\u003C\/a\u003E (Polish only), which collects stories of up to a hundred words. It never got any users, but I didn\u2019t really care to promote it in any way either.\u003C\/p\u003E\n\u003Cp\u003ELast week I\u2019ve decided to rewrite it from scratch, because so many things were wrong about it \u2013 from an ancient backend in plain PHP with hardcoded credentials and no separation of concerns, to login with Facebook (and only Facebook) that stopped working... Now it\u2019s a fresh \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony 4.1\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/frontend\/encore\/installation.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Encore\u003C\/a\u003E with some new features (like automatic screenshot generation, seen for instance on \u003Ca href=\u0022https:\/\/twitter.com\/Stoslowia\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Twitter\u003C\/a\u003E).\u003C\/p\u003E\n\u003Cp\u003EBut what I\u2019d like to show you, is how a couple of pretty small design changes have made the whole website way nicer visually (IMHO).\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-redesign_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022598.75\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAWCAYAAACosj4+AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFPElEQVRIiX2Wy28cxxHGf1Xd89ql+RTNWJYjSrIs2TBiGHAeOgQ555\/KNfApyF+US2zlZOQSCApgPSgnlB0RJJfk7s6ju3KY2eGMKLqAvUx11X791VdVLTFGo7PnL5\/x3XffEhaQe8\/N2\/vs3b1DM1\/w34MDZifHzMOcqql59Ovfs3\/7DgBN01BVFd57zPp0qCp1XXN2cUFV1WRJgqrinOPvjx\/zzbePyYqCIi+Yz8+5u7+PF5E+wZOn\/+Lrv37NJC3YTTe4tX+P\/U8fUs2XvHj5bw6PnnHRnHP4wwl\/\/tNfuLN\/FwAR6X8AZsarV6\/Y2dnh6dOniAgbG5tcOAcGm5vrfP7ZZ7x4+ZLlcs4nH9\/l0e8ekaUpfnijvV\/s8dVXv8F5xWfCrc0Pufn+B5T1ET81KfduPiDWxsP7gb3dvREbQ2uahtlsxtbWFr+8fRsQpANa1RXHx6c4ifz2y19x\/8GnZFlGjJGyLJFhyaoQWdaRECOpgmp762iQKoQQCCgiQuodTltGQgijkq1+IQRCCCRJMgIcY6Cqao6Oj1lfew91StLF+uFBiQFtShSwCDiHqEIIlGZ453ASwQATwPWxQ7ZW5VNVkiQZ+VZAi6LgVlHQNA0xGs4pIGMNmSg1nsILdTQaA4lGFXV1gBANMUMd+EFsmqY9E2ZGHYzEXfpHF\/cZP1Xn\/GP2gj\/uPmDDZ5c+G8CvqpL5fHGlU1qa4+jbZDLpATRNg5mNAL348ZAb023yNMFhNM4IZmgIeC80qmSaYmYMSRkBKptI3QSK1BMGeq0jTDw0BjGCCHgF7RK9C9A8BFKEaIKzgBMDFdCRSvoSr2zUZRIbQrngvGwPmRnOOWKMnDHWyWQyQfw4ee834+L1a9KtLVLvMaD6\/jkne9uEGNje3gbgoD7kA7\/Lmk4uAY001AluCMbMrgy8lWCHscObGlACP56crDy89+FNXFVRLSveHL5BVdnJ1lnbmlxlaAVAfIKfbuClY7dr6zoKmXbtLIoBKFfqP2RpUkxQ105lDLI8Q1rUiEjP\/CpmhWHMeWgI8wvCW7cWEaoY+0QArijAuVH4Ckw0gzxBnMPakcjfTv\/DH9JdinyC0zbOXs8wXyJrWR87FnVZUlVV\/werDptOp\/ycvUvUBwcH7Ny40RWsHQvHxycg4Dvt5VlOUeTXixrnCV4ofDudzdqOmi1rcgfRIEQQMVLv+0n9NkNtKs\/pySlI+31jY4M8z6jqGosG0o6ZoshHcVdKZss588GnFUsXgzkkIvjJBKfjlTC06WSKOu0KBlmasgwleZ73eZ8vXuGiZ00vKzACpKp470fUiwghBGKnoRXd7i39DC1ahBTEda8A4J+LJ3w0fx\/nPd55ROBOdotCi1HsqO0DQoVDDZq2NqgYlSkeQwzqYEQznDfcNW2vKGdHMxBhe2sLEeGL\/CHzuKCqKqrY6lRUKYpirKERQxbRpqQO3QEzojo81tVZiKHpfNeXC0CdQ1WZnZ1hZkynU9I0Jc9zRFqGq6q+MjrG2x5G29l737\/wVoHeXx3977I8yxEV0q78SZIwOz1HRNlYX8cCzP4X0BuBYk0vAY2eBuqoJSHRiDqH0ZZxWdbte8ggli3dRZbir51DkWSakKYphiEIT8pnfOT3WCwWlEdLwCjWC\/Lp2rjLRqsjNFDNqYfUd122fKvLLPFXdtlQQ0evj9jc3Ox9n6\/d56K6IE0TMEjTpGf72tXhvSfPc1xX\/5U1TdPvr1UCVf3Z1ZFlGYvFEhEQUSZFwBJHmraL1DnHs7M33CtSpi7tMfwfMXi5tPgkQxcAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/stoslowia-redesign_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022598.75\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThere is a website I\u2019ve created many years ago, \u003Ca href=\u0022https:\/\/stoslowia.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Stos\u0142owia\u003C\/a\u003E (Polish only), which collects stories of up to a hundred words. It never got any users, but I didn\u2019t really care to promote it in any way either.\u003C\/p\u003E\n\u003Cp\u003ELast week I\u2019ve decided to rewrite it from scratch, because so many things were wrong about it \u2013 from an ancient backend in plain PHP with hardcoded credentials and no separation of concerns, to login with Facebook (and only Facebook) that stopped working... Now it\u2019s a fresh \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony 4.1\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/frontend\/encore\/installation.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Encore\u003C\/a\u003E with some new features (like automatic screenshot generation, seen for instance on \u003Ca href=\u0022https:\/\/twitter.com\/Stoslowia\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Twitter\u003C\/a\u003E).\u003C\/p\u003E\n\u003Cp\u003EBut what I\u2019d like to show you, is how a couple of pretty small design changes have made the whole website way nicer visually (IMHO).\u003C\/p\u003E\n\u003Ch1\u003ELogo\u003C\/h1\u003E\n\u003Cp\u003ELet\u2019s start with the logo. The old one was the laziest option possible: just an icon of a pencil from \u003Ca href=\u0022https:\/\/fontawesome.com\/v4.7.0\/icons\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Font Awesome v4\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-old-logo_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022128\u0022 height=\u0022128\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABz0lEQVRYhe3WzWpTQQCG4afqQkS6FJEiIYSsRMSFEt24EHfeh5siIsWr8Aq0igvvQUqoGvwB8aeK1I24kOIF+EcopbqYOfQ0nJycTE5ThbybGSbnkJdvvpmEGTP+bRq4vN8SGW08xSdcw4EqLx3cI5kW7uI45nAem3izH0LtnEzGHC6gjzX8mZZQE8sDMnk6+I130xBq4V6JDDtJ\/cIHBUnVJdSsIJOX6uAH3hd9OCkt3MGJMd\/bwlV8yS9WOoolNBNloIuNwcVJhLICp8g8wi3hKthF6pZNIrOCm0UypCXUkL5NK1gaJsP4CWWdWUiQ6eJGmcy4QidxfwKZJeFSLKWqUEPozJ4lM47QAh4kyqwKBR6ZTMaoUjekb9OqkExlGcoTOoaHQndSZMZKJqMsoSvTlhkl1InjZxULiScStqmK0BGcjvNl4ZrvV5QZ9Vwph4ast4QObeI1vsb5bRwueL6H65PKMDyhc3HcwLc47wrdGPzSnhqSyRiW0MU4vsK28Lt1RuhV305KPSzWJUPxsT+Kx5jHW6FPDbu3ahvPhGR+1iVDcUKnogycza1\/xzpe4kWcb9UpM0yoHce+8PfyeRT4GKWmzjwuCadsxoz\/jr\/bT2F\/bPwgOgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/stoslowia-old-logo_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022128\u0022 height=\u0022128\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe new one is a modification of free vector icons \u003Ca href=\u0022https:\/\/thenounproject.com\/iconka\/collection\/sketchy-icons\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E created by Denis Sazhin from the Noun Project\u003C\/a\u003E (CC-BY), that looks way more individual. Its elements form a \u201c100\u201d, which relates to the name and the purpose of the website.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-new-logo_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022128\u0022 height=\u0022128\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAI1UlEQVRYhb2Yf2wT5xnHv2f7\/ONydmwnRI7TJIYlGCIISQ2ENjQYd8WDjM2AmGBDQpP4ZxJC+2NC+6MFoSmVEG2llXXtJk2dtElFaqNurSqBSEKBKI5p6jo\/+JE4AeIljnyJHcf23Tn2nd\/90dmLk8DWEfZIpzvd8\/74vN\/3eR69d0r892YG0AqABRD5Dv2+k1H\/wa8GsFOhULxYWlrqtlgsDdFoNGO1WnuDweDdTCajqqys\/H0oFEo9L8Dl9sMdO3Z8MzAwMDk1NSWeO3eODA0Nkb6+PvLBBx+QCxcukPr6+s6+vj7F\/wvodEdHx3AkEiEffvgh2b17N8lkMoQQQnK5HLlz5w7xeDyy3W7\/DYA1gXrqIDRNNzc0NNhSqRR8Ph\/27t0LmqYBABRFYXBwEM3NzYq2trZfa7Vaz\/MGYquqqnY1NTWxDMMgEAjA4\/GAEFK4wuEweJ7Ha6+9pqqurv6Tw+F44XkC7XK73eWiKMLv90MQBDQ1NQH4Vh1JktDT04P169dDFEUcO3ZMGhgYeObgVj3F96rT6dSazWb09\/fD7XaDor5NSkIIIpEIOI5DS0sLPv\/8c1y9evVBOp2OPyvQkxRSsCzb6HQ6tclkEv39\/fB4PAUgiqLQ39+PLVu24PHjx\/D5fJicnPRfunTpWXmeCGR2uVw2lUql1mq1mJ6exrZt2wowANDd3Y09e\/aAYRgsLCwgmUzOPjPNU4Aa3W63QqFQgOd5aDQaMAwDAIWA\/vrrr1FVVYVoNIpQKASKorqeG5BSqXzR7XarZFnG\/fv34XQ6i7ZrenoaLMuivLwcyWQS2Wx2TBCE\/ucGVFdXV6nX662JRALXrl2Dy+UqSne\/34+XXnoJJpMJ09PTyGQyfWsBA6yeZYb9+\/fbMpkMk8vlMDMzg4aGhoJCAODz+XDo0CEsLi5iZGQENE3\/fa2AVlNo5759+5h0Oo1oNIr6+npQFFWkUCwWA03TYFkWyWRSKCsru7NWQCsUoijK1tDQsJFhGPh8PuzevTv\/HgDA8zwAIBKJQBAE3Lt3LxQOh7m1AlqukMrhcGzW6XQv0DSN0dFRtLa2FqkzNjaGXbt2obq6GiUlJUin01cBSM8LyHLgwIEamqbV6XQauVwOZWVlRRkWCARQW1uL2dlZDA4OgmXZ7rWCWQ3o5UOHDrGCICAej8NqtRbBAADHcaioqADLspiZmZH0en3vWgIVxRDLstYNGzZs1Ol06OrqglarLfgIIUilUqAoChRFQZZlzMzMDIVCobTRaGzQarW7UqmUhef5ACHkSwDCswIxW7durY7H47ZwOIxoNAqDwVBwUhSFgYEBOByOAuj8\/Lz59ddfD1osFkt7e7uKoijcunUr19XVNXX79u2Lw8PDfySE5OOrHIARQPhpsEuBmo4ePVrDsqxCrVbjq6++wqZNmwpOjuNw\/vx5XLx4EbFYDPfv38fhw4dtHo8HZrMZhBAolUp4PB5Fe3t7jdfrvXz69OnWysrK8aqqKte+fftsiUSi3Ov1zg0NDf0tGAz+NplMjj8NqI0Q0pRIJKBWq1FVVQWTyQRRFEHTNC5dugS9Xg+KoiCKIubn57F9+3asW7du5SpVKnAcpzhz5sxPXS4XTCYTlEolDAYDTp069cLU1NTpK1eunHjrrbd+MTs7e2VpX+WS55\/p9XrX0aNHFd3d3Th58iQaGxvx2Wef4ebNm3C5XNDr9WhsbATDMLhx4wY8Hk9RnOW3tre3F4QQOJ1OWK1W6HQ6aDSagt9oNGLLli1aq9Xq6evrmxQEYXC17Xu5tbV1fmJigiwuLhYO8nnLZrOko6ODeL1eEgqFyNmzZ4v8efP7\/eTjjz8m6XR6VX\/eEokECQaD5M033xQBfD8PsTTtR8bGxnLl5eWgaRqEEAD\/Pm4olUrY7XZ0dnYinU7DbDYX+QkhkCQJPp8Pe\/bsgVqtXuFfesmyDKVSiYMHD2rb2touUBSlWA6UmJube9Db21uQNn+nKAo8z6OlpQVmsxlvvPEGtm3btqLN3bt3wfM8WJZdUb\/ybfKQHMdBkiQYDAYcOXJkJ4CNy4EAoKenp6doEEmSEAwGMTIygkAgALvdjpqaGjgcjqIJAWB8fBzNzc3Q6XQrYJbGWCwWA8MwEEURALB3716VTqc7DCwrjISQ66Ojo79aWFjQZrNZaLVaLCwsQKFQwGAwIBaL4YsvvsDbb7+N0tLSwmrzE2azWajV6sK75fd8+5KSEnAcB5vNhpKSknx4fG8FEICB8fFx7sSJEzX5Fdvtdhw\/fhyCIOQ6Ojoet7e3lxuNxkLFXDqRJEkQBGHV7VqyaAiCALVajVwuB4qiMDo6isXFRQDFaQ8AWVEUWywWS4PdbqdEUYRCoUA4HMa1a9fuDg8Pn3r06BG1c+fO7SaTqRC42WwWHMdBlmV4vV688sorBWWWgicSCczOzoLneZSWlhYK6nvvvQev1\/s7AN+sOKDxPN8NIDM7++1HRDwex6effvrQ5\/OdBNCbSqXOnzt37sHU1BSi0Sji8TgikQhKS0uxefNmPHz4EI8ePUI6nS4K5GQyiWQyCVmWYTQaQdM0KIrKL3YMwF9XUwgAEiaT6RRN05q6ujqEw+HAxMTEjwDc\/Zca\/MzMzHVZll8tKytbV1JSAoPBgIWFBZjNZtTX1+Pdd99FY2MjVCoVZFlGNBqFJEmQJAlarRZGoxEMw2BxcRGXL1+WOjs7fwkg8CSgOM\/zP5EkycJx3Jd+v\/\/HhJB\/LG0gy3L0wYMHV3t7e2uDwWCNIAh0MpnE8PAwAoEAbt++Hcpms5ra2lqVLMuFKm2xWKDRaEDTNFKpFN55553M+++\/\/xee5y8CyAFP+GHFsuzZ9evX75iYmPi5IAhP+15XaDSaCrvdvjESiRjVajU2bdr0cGJiYsxgMPygrq7uD\/v377c4nc5CzRFFEZOTk\/joo49GPvnkk8uxWOzPADL5AZ\/0B43B\/3ieWWoqlcpmNpsP2Gw2R0VFRYUoipibm3sYjUavV1RUdPn9\/vTyPv8EVEBqalCJz50AAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/stoslowia-new-logo_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022128\u0022 height=\u0022128\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch1\u003EOld design\u003C\/h1\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-old-home_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221197.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAkCAYAAACaJFpUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFCElEQVRIiaWWzY4kRxHHfxGZWdXTPbNe42UFyLKQWVnmERBHy+LIkQsvgMQFiTvPwI0LDwAvgLiCQOKCOHNDNrINi7We6Z3q+sgIDllVru6qgUHkYaqnKjMjM\/4fEZJzdi5G27YcXx+pUsLNEVVSDMRUISKIapnXNJg7ApRNyl9zZ3+1J4RwuTVRRFYv\/\/in3\/HTn\/2Yt5+8wacf3ZNb48Xzp3z7O9\/la8+\/wrvf\/wH+8h\/8\/le\/JlSR288+4w9\/+TPP3r7mNh\/55G+v+MXPf8mHH3xvHXD1ZjyhdcLLo3H4+jVvVE\/Zkfji9khU5+63vyG\/esW9GdGP\/IuXPH1RY3FAvwiIK2HMwn+8obsjIsQqkG4CXdswnBSvW+5RYnPN9ZNrnqlgu8hf\/SP+\/vHHdNajAs1tpjmduH4roVICisi8L0B0P4fQ3Xnxzff40Q9\/ggYh1YGhy2glkJV3nr\/Dm289o3n9OV99\/xv0bUYV8uDESlER7v7Z8q13X8z7LZ\/ilxGBZnDuB0eBwaEOcJPOsb7tnH0Skgpt2+ISMFFUIDvUQYi65oeY2SrgMPQ0zWk+Wdd1ECsGc4JAiJGEYWbnm4lgZqgqV1d7UopzSmcMt4B1L4FUBRBSVaEiXF\/VqAgiwjAMMzYpJS7ZriNpLhO4Ig0AIdFVkeskXEXhvreiMAHz8jxpJDskhaBCHhM1pxQhsCbNJoZ915WUSjnpZepUFXfHzOaNphvlnAFhv78ipbTK3llKp5OYO0Mezt6bGTFGzIwQAkLR6\/K803p3w323+P+\/yGKyr2rEZrrlnBYRBMjjzZebujt1Xa8w3JTFtKjLTjM4hyQFEwMr0M2jzU5Q4SoUXAcv3ydfDQq6heGWLPp+4Ng0ZQFgCCKjNbsTQphxVZzJ\/s0cFUCVw25HSmsRbJo3OFG+\/K3uiAMiIBCkHGCMT9Siv5QCPuIagq6kAg+Ztxlt25YULBZNv5cEKkEdQcg5z5g\/NDZTamazsOcNRaiqavPU\/8tYkQagzXDXFzwqhSCFNBOmCDRDIcZBjZwzHhLZyxyAGIQoG9XiLPrEpNzC8ZbszmkhhWloCKgIQx74PBfvvPTMm5sbpK5Xa1c6nCbsdrvFrZ3Z9UIAhKpKZwEmT12Orb0fJE3XddR1PS4SVGWRHjZt6zFj00uLZRUV6IWLzEwdm6fpdstvyxs+SvhNn7k79Zg5b+6UUwZwzEplEBFacxTnEIXBoLNyAMUxhMOuIoW1PDaFH2wgdK8JwOtjcRh3R0Xo3EkpEUdDv2tsrh4+pkVF8KRIrNcBN\/OsOhdV5zytk+iBWejAbO6qio8VZWs8yNKJ6lVVnWFRvittezoLVNf1GYYhhIdZOk2cJmSJdOlAHQQN0GfHoBTk8dmlAwDX0pe1ITEshD84m8LfZGnXdTRNMzdElxYXQkBE6Pt+0+pEhP1+v13xt67t7sWuxnTlnGezXmJZTs+icvhZmh8tfFUlxQjjogmPEMJcCUpNzIDiXogUY\/yyY3jA5Ddb\/TEvKzFPdqcji5dr\/i\/hd1Y6axV4UsmiGBdNCvCqc55UMpOkGQqx4qLzDhuXfLhNPJ3IOWNmGIov2vgQ9KLzHjuZBaCHw4GqqtYpXZ+h+OQk6hACYgZiCKWdUPGxO5\/uPOlTwB1H2OBLCfiQ8EtvWUrOdNJprqrS9\/3ctyyxmhos1W2Wipn5JYUfA\/4wDJiVZmli8WPW\/Rv9jECHOmzNXwAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/stoslowia-old-home_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221197.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-old-add_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022442.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAQCAYAAAB+690jAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABF0lEQVRIie2TwU7DMBBE39oOSnug\/3\/jGzjyA3wNB6RIBNvr5dDaFNomaRCIQ+c0kWazs7tjKaUYgIgAYGaND8OAquK9p+s6VBXnXPv+rs85E1NCoOlijIQQMDPMjBA6QvAntWYGgKjqnp1BjLEV1AbXYEhGMXD7X1AOne7v5GJNcM6dOK18HMc2mfeB7XaD9x4ROauv3MzIObNxLNIf8zA14W63u1g8B1VFRHDONZNL4BapVsDMeHl\/xbnPFunhEX16nqwT22PxSn\/CrRSYOd\/kyapwLT+Z\/pDXKcye7DiQ1\/I1mN1QSgkDaosa0hrUt3EkeE\/OGRGh7\/tmSFW\/bKSGfAp\/mqEl\/Nde2VrcDM3hZmgO\/87QB+2b5hKTe+QzAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/stoslowia-old-add_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022442.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMaybe I shouldn\u2019t judge the design, if it\u2019s me who created the website, but since it\u2019s mostly a \u003Ca href=\u0022https:\/\/bootswatch.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Bootswatch\u003C\/a\u003E theme anyway, I\u2019ll dare to say: it\u2019s not bad. I like it. It\u2019s clean and minimalist.\u003C\/p\u003E\n\u003Cp\u003EWhat I don\u2019t like is my own choices: like the jumbotron with random background images, which made the text not-so-readable, even with the addition of a text shadow, or the lack of a footer, which makes the website look somehow... \u003Cem\u003Eincomplete\u003C\/em\u003E...\u003C\/p\u003E\n\u003Cp\u003ESo what I did to polish it up:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EI rebuilt it in \u003Ca href=\u0022https:\/\/getbootstrap.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Bootstrap 4\u003C\/a\u003E using a different \u003Ca href=\u0022https:\/\/bootswatch.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Bootswatch\u003C\/a\u003E theme (slightly modified).\u003C\/li\u003E\n\u003Cli\u003EI switched the \u003Ca href=\u0022https:\/\/fontawesome.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Font Awesome\u003C\/a\u003E icons to version 5, the light version.\u003C\/li\u003E\n\u003Cli\u003EI switched the font to something more distinctive.\u003C\/li\u003E\n\u003Cli\u003EMade the jumbotron bigger, with a non-random background image that matches the subject matter and is subdued, so that the text is better visible.\u003C\/li\u003E\n\u003Cli\u003EEven though the random jumbotrons in the old website were meant to add some colour to an otherwise dull website, it still looked pretty monotonous. That\u2019s why I decided to assign colours to the categories and display them as small bars on top of the story-card.\u003C\/li\u003E\n\u003Cli\u003EAlso to break the monotony, I decided to align the cards in a \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Masonry\u003C\/a\u003E manner, instead of just rows.\u003C\/li\u003E\n\u003Cli\u003EWithin the card, I separated the important info (title, author, category) on the top, from the less important (number of words, date of submission, comments, votes and social buttons) on the bottom.\u003C\/li\u003E\n\u003Cli\u003ECategories are pretty important, yet in the old design they weren\u2019t emphasised at all. With the addition of colours they are way more visible, yet to make them even more distinctive and useful, I added icons and a list of all categories on the top.\u003C\/li\u003E\n\u003Cli\u003EI added a footer.\u003C\/li\u003E\n\u003Cli\u003EI reorganised the submission form so that it has a simple up-to-down flow, instead of the previous two columns that made it easy to overlook some fields.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003ECheck out the end effect below. What do you think? \ud83d\ude09\u003C\/p\u003E\n\u003Ch1\u003ENew design\u003C\/h1\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-new-home_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221605.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAkCAYAAABmMXGeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEvUlEQVRIiZ2WT28byRHFf1XdPTOkJFIyLdKxAiyyh00+wO4hgD9DgBzyOfMVFsbuYYPkkkRADhsgudiWRNqkKJOcf105DDniaOQ9pHngYKb7VVe9eq9b8jw3M8PMOB6qSllV3K\/XlGVFlqbUVUWSBESEn\/76N75\/+xYzOD09I8sy5vNbfv36V3gAEQHAzCjLku12i6pyfX2Ncw6A2esr6qrifDwmCYHfffMNf\/\/nNScnJ9x8eMfrVy\/50x\/\/wMXFBZLnuR0AARaLBavViqurK3a7HQYIQow1ZVVzO18QLXL1asaPP7zFEN68ecPobERd15Rl1QU1M+7u7jAzkiRhl+ekaYqqtplgEJLAYn6HU+HF5BIR3WdkFEXRBz2Mw\/PTWgOUZU6MwmL5kSzJcM7hvcc7xcyQ3S5vwrdg7VMPzAxirKjrmhCSNmhV1cQYCcE3oNYMRAQzIxrUERL\/SN7hm4gQzdgWxn2948\/zf\/Dt6Irvxlct2UAfdLPdsvj0idnLKSF4wBCgbiYj+26JAsoR0FHgHmhpkVVZclJ5TMBZJFjFLtSoOYIo4oRSIZWkB\/rsTus8x2JERTADAWy1Ig5TimGCOm2BNnFHbTVTP+mAPs7YjyJGPq7XkCS4QYYOMiRLAWU9v2fz8TMDyRhIRiYpTlyP0H5NNxs+LZfNR4RokRACLycT3r1\/37wVwTnFe8\/kxQtUtbPTjkxFmgXee0QElSYRdYoBaZp2WFZVjtu4xYkxdhqyLEvyPH8EVqUsS7w64rZoZCuCc45isyWII5mOO+n741YwMz4XOZsyZzzM2kl\/2S75yg8Z7DbMZq9akwnBY8ttZ5fP1nS73bJcrghJ2AdTnFNGZ2e8\/3CDyGP7eB+YTS97oP6pxlUV592j9mMEp4jA2ekpIo1cD+BVXeOd63iEHpMEUNf1nvf9b1\/XKtZUviImQCbo0POBOf\/a\/fv59J8SVVVVO+lAlHOO29s7prNpsxAwDB88Xn2HqF5NP62XrDdrAC6nUwT4ufgvF4xwy0btts8\/y1LGo1Hbip0+PR6DkFG5GgEeFg34K5lwPh4zZ0FIEgTBnrHGlqjOtvfRiqJoiWjfRzgZnLUseecoipJ8V5INkk5de+w75zgZDhBVQggI4H1jgQ8PK4YnJ4zORg2ppbB4n3P1ddJhv1fTh91nSqtQERBQdfy8+Q+XyYTkwSE075t\/4cXFeav9Z9MH0Cjk99vmqN2n\/dvsa7xz3BZ3zeJGq50SdWr6NH0RQVRZrlaYgVNlMBzgQ8rp6Wnrs2mWHh9onfR72geoqhpV2R90EV+WlGlCqeD26irEuF69A+f4\/eSrvvMfb32321HvnT\/G2CpKVbm5uWE0GpFlWdtQwfvWYL5IVLH5DLFRlACiSrW8QV3gtgqdK5KIMJte4pz75eYvDeooZFlGPOxm9ptm8nyOihLt8EWelUDf+VVZr1bcrx9aR\/Lec\/lygnceBJy4Vq6NizmOcfyTkqIipGlKrGOb0mA4QFU5Px93FptZ9571JfZVlSQECAfba\/5jjHtl9cdh\/ReJ+n9HB\/TpwbcrKvIiMhgkxGg4bZTjezeEXwjQu6HUNbUdzG0f3eKR2eneoSOIw4l1WsrM+B+FtOglJDiiGQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/stoslowia-new-home_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00221605.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-new-login_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022733\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEjUlEQVRIic2WWW8cRRDHf9Xdc+3h9YHXCfHBJYXE4sXiOQgeonwAkADxQeCr8B14QjwhcclvHCJSwEQIWUkcXwmJZ+09Zne6m4ex12uzXu8iJKiH6eqZ7qp\/V\/2rayTLMu+9B+BkPC8igogAYK2lcdik2W4RhyFJHJN1uwB0sy5RFBKGAd57vIfNBw\/46tvvSNMD2u0OzjmCICROEkqlhCiKaLXaPNj8gziJMCcOvff98SJwIoLWmulalWqlRNo45PHeHnEYMjNdw2iNc448zzEmQMSz+OJVBE+n0yGOIkqVKuVyCWMMaZqy8es96vMv8NGHH3Dj+utIlmV9z8PAPH\/+nFKpRBRF7OzscP\/+farVKmmaUqvVyLKM6zdu8nh3j9Bori4s4L0nCAxaKfI85+69X\/j+x5+oVqtEUcTW1iN2t7d46aUV7ty+w8ryMlprnPPDAQ3qGxsbtNtt1tbWSNOU7Z0dvPdopRARer0ey8srWGc5PGqy++QpWinq83MkcUwpjmkcHvLl19+QHhzw6OEmb6ze5Natt1mo1xFReO+w1uG9L1I2mJITICJCq9XCOcfMzAzNZpMkSVhcXDyTRiUK5xxKhOmpKuVSQrPVZmt7F+cs9blZlq5dZSYW5hav8P5771Kbmupz0nmPd57c5vjLItRut1lfX2d1dZU4jtHGHIP0KCX90xXGBecc4LHWUa\/P02y1eLq\/R97LqJQrzM1fQQSUUmht0Lo4jPceay3dbu9yDp1syLKMIAjodDp4D9Vq5UykzhdF8c4hokjTBkdHDUrlCsYYojDEOY8HjNYoJcfFYE8BDePPeYej5oPvRATnLNZarHVY59h7sk8QhExPTdHpZCitKCel\/j6ljqPdarUKQMUX+oOczi8C4s8++mLzHs2jFBXEJHGCUqr\/rdPJyG2OUYZ21iEIAuI4wlqLAJLn+fDb8D8S8YX0WX9eb3WLG7ccK+QSY4N7D1oWD\/QsfJH+zOf7vyECn7zyFm\/WFof6EpEC0Ljom80mHnDWobQqUipSZEwAP3h1eOT4rkri+MIDn9fNUM8jw0BR8pwyR+SEWwWYSqU8NGrF2tG6mSBAbGwdsf30AOccURiBFM1Wa8Py4rXThY1uXy1HipVZPbaPiSL0e6PMfjcpJnkxTMWCy+HxZkbuIDtXI\/WKYmW2zLhyKakHL7s\/nz3jIG0QGMPy0tkWcpCmNNJGQScRlpcWx+bNoN7\/\/egjHKKfjEmSMDc7O\/RkcRxjtB5olhatx0\/ViUyUsjAILjakNXEUTQzgb3YmIbUbsfYyOxe1pvP6RBH67G6X\/cM2WgmlUDjKHN7Da\/MB77wqGGPOpPyfiJnEwNpSyFHmCY2gT9sT04kijtVQMCeNc1wZq8rGkU\/XD\/nhYUaghNAIPevpWs\/Lc4aPb9fGrrKJWsckMkmpnwHknPtfdfuRHOrmjk6v4Eyn54mD09E60Aqch1I4Pkcuk5ERarfbNDs5zVbOwlyCVwEOhXJdUKZo9q572mQBrwLwxc+WFwOuCyoABHFdwihCjyD5v0bqUXvH1fM85y\/9B+hVIrL\/rAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/stoslowia-new-login_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022733\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-new-add_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022713.5\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAaCAYAAADfcP5FAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEQklEQVRIicWXXW9bRRCGn9k9Xz5OnDRtSFNahNSqohJQFFGJC6BXqD8CxB0X\/BB+EhJCtBR6hQRXKBSBaJWoSvOB2yS2j8\/X7nDh2HXa2E0CFSNZOzpnduY9M+\/MrqUoClVVAIbr8yIiiAgAzjn2uz16WUYcRaRJQlGWAJRFSRxHRFGIqqIKD9fXuHP3R\/b2dun3c9R7gjCi0WjQSBvEcUyWZaw9fEAjTQiGAVV1tE4CJyJYa5lvzTLbTNnvdNnY2iYKAxbOzBNYi\/eeunYEQYCIcnF5GREo8pwkSWjOzNBMU6wN2N19yoO\/\/mR5aYnPP\/uUt65eRYqiGEU+Cky73abZbJIkCZubm6yurtJqtdjd3WVubo6iKHj7nXd59HiTwBqWl5YACIMAaw11XfPr6m\/89PMvtFotoihkfX2N7a3HXLl8mVuf3OLSxYsYY\/BeDwM6CtT9+\/fp9\/usrKywt7fP9s423nsCGyBGqMqKC69fwDlHL+uzubMDCufOnWEmbZImCZ1ul29v3+HpkzYbG49YuX6dDz+6ydmFBYwxOO\/xzqHKZEAA3W6XtbU10jRlcXGRMIwoy2Jgd2Az+DKPeo8YQ13VZHnOxtYWRVGyuDDPm29c5O533xDEKe\/f+IBmsznipFfFO0dZVnj1R5dsqBdFwb1797h27RpxHBNFEVnWH2wUQcSgQx3BeQ8oznmWXluknxe029tknQ6tVouzi+cRARGDtZYgGHBOVfHeU5Tlyzk01IuiwFpLnucoMDszc2RWD2fbI2LodnvstLeZn1vAWkMcxQddqARBgDEyaoYRoKNATAs47ZmI4F1NVdc4Pwi8t7+P85652RZlUSJGaDQSjBhUFWMOOr3Xy3TIiOMAgQPrIwEN3jpXkXU7BHGDJE5GfAEoy4qqqgiMJa9KrLU0khjn\/OBjnHNHR\/2XogpOQYBCK7pu0AwLYUogZuK+wJjJL1WVrFQUaMYGmWj5zH6YjdopeaUEFr5u\/8EPTx4iwBeXbvBea\/kF+6Eu3vsTZUhV2d75m36\/TxxH1LVjdnaW+bnWSdxMlGD82JiEelyvPHz1PYS2QRhYuoXny48T4lSp3YBfItAIBSs8I+sx\/YtOYu6UDHWynDiOR8+MAM8VVABrDp+TxwJ00pK9ajHDq8Vxf6pKp9PFOTfV8fhMGq7H0k+ToaIoDpXsv5RTARqv\/UsDnJBDwXEdj4OZNrvG7U4jpyZ17mucepo2OlXgSXLsOTQU55Xbv\/dY7+9Riedqeg57MGs8jC5KxsDNK8mJ59DoTj2USfq47BfCnMwD8DTzJKEgAv2DY2awlzH95f5HnfZ\/zKFTk7qsPXmlxKGhXw4ykVdKEgrODyaxV0ijF0k+rTRTwU47OrIso5fXdLOa82cbYEIcButL1ASDS7kf\/CdTQBDUBKBuoIsFXyImRBHEl0RxTGDtdEAnId2r1Ou65h8cjuXlSrdDwgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/stoslowia-new-add_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022713.5\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["bootstrap","colour","design","redesign","refactoring","stos\u0142owia","webdevelopment","website"],"hasMore":true,"image":"https:\/\/avris.it\/image\/stoslowia-redesign_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/stoslowia-redesign_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-redesign_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022149.6875\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThere is a website I\u2019ve created many years ago, \u003Ca href=\u0022https:\/\/stoslowia.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Stos\u0142owia\u003C\/a\u003E (Polish only), which collects stories of up to a hundred words. It never got any users, but I didn\u2019t really care to promote it in any way either.\u003C\/p\u003E\n\u003Cp\u003ELast week I\u2019ve decided to rewrite it from scratch, because so many things were wrong about it \u2013 from an ancient backend in plain PHP with hardcoded credentials and no separation of concerns, to login with Facebook (and only Facebook) that stopped working... Now it\u2019s a fresh \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony 4.1\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/frontend\/encore\/installation.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Encore\u003C\/a\u003E with some new features (like automatic screenshot generation, seen for instance on \u003Ca href=\u0022https:\/\/twitter.com\/Stoslowia\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Twitter\u003C\/a\u003E).\u003C\/p\u003E\n\u003Cp\u003EBut what I\u2019d like to show you, is how a couple of pretty small design changes have made the whole website way nicer visually (IMHO).\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/stoslowia-redesign_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-redesign_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022149.6875\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThere is a website I\u2019ve created many years ago, \u003Ca href=\u0022https:\/\/stoslowia.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Stos\u0142owia\u003C\/a\u003E (Polish only), which collects stories of up to a hundred words. It never got any users, but I didn\u2019t really care to promote it in any way either.\u003C\/p\u003E\n\u003Cp\u003ELast week I\u2019ve decided to rewrite it from scratch, because so many things were wrong about it \u2013 from an ancient backend in plain PHP with hardcoded credentials and no separation of concerns, to login with Facebook (and only Facebook) that stopped working... Now it\u2019s a fresh \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony 4.1\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/frontend\/encore\/installation.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Encore\u003C\/a\u003E with some new features (like automatic screenshot generation, seen for instance on \u003Ca href=\u0022https:\/\/twitter.com\/Stoslowia\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Twitter\u003C\/a\u003E).\u003C\/p\u003E\n\u003Cp\u003EBut what I\u2019d like to show you, is how a couple of pretty small design changes have made the whole website way nicer visually (IMHO).\u003C\/p\u003E\n\u003Ch1\u003ELogo\u003C\/h1\u003E\n\u003Cp\u003ELet\u2019s start with the logo. The old one was the laziest option possible: just an icon of a pencil from \u003Ca href=\u0022https:\/\/fontawesome.com\/v4.7.0\/icons\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Font Awesome v4\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/stoslowia-old-logo_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-old-logo_mini.png\u0022 alt=\u0022\u0022 width=\u0022128\u0022 height=\u0022128\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe new one is a modification of free vector icons \u003Ca href=\u0022https:\/\/thenounproject.com\/iconka\/collection\/sketchy-icons\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E created by Denis Sazhin from the Noun Project\u003C\/a\u003E (CC-BY), that looks way more individual. Its elements form a \u201c100\u201d, which relates to the name and the purpose of the website.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/stoslowia-new-logo_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-new-logo_mini.png\u0022 alt=\u0022\u0022 width=\u0022128\u0022 height=\u0022128\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Ch1\u003EOld design\u003C\/h1\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/stoslowia-old-home_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-old-home_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022299.375\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/stoslowia-old-add_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-old-add_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022110.625\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMaybe I shouldn\u2019t judge the design, if it\u2019s me who created the website, but since it\u2019s mostly a \u003Ca href=\u0022https:\/\/bootswatch.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Bootswatch\u003C\/a\u003E theme anyway, I\u2019ll dare to say: it\u2019s not bad. I like it. It\u2019s clean and minimalist.\u003C\/p\u003E\n\u003Cp\u003EWhat I don\u2019t like is my own choices: like the jumbotron with random background images, which made the text not-so-readable, even with the addition of a text shadow, or the lack of a footer, which makes the website look somehow... \u003Cem\u003Eincomplete\u003C\/em\u003E...\u003C\/p\u003E\n\u003Cp\u003ESo what I did to polish it up:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EI rebuilt it in \u003Ca href=\u0022https:\/\/getbootstrap.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Bootstrap 4\u003C\/a\u003E using a different \u003Ca href=\u0022https:\/\/bootswatch.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Bootswatch\u003C\/a\u003E theme (slightly modified).\u003C\/li\u003E\n\u003Cli\u003EI switched the \u003Ca href=\u0022https:\/\/fontawesome.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Font Awesome\u003C\/a\u003E icons to version 5, the light version.\u003C\/li\u003E\n\u003Cli\u003EI switched the font to something more distinctive.\u003C\/li\u003E\n\u003Cli\u003EMade the jumbotron bigger, with a non-random background image that matches the subject matter and is subdued, so that the text is better visible.\u003C\/li\u003E\n\u003Cli\u003EEven though the random jumbotrons in the old website were meant to add some colour to an otherwise dull website, it still looked pretty monotonous. That\u2019s why I decided to assign colours to the categories and display them as small bars on top of the story-card.\u003C\/li\u003E\n\u003Cli\u003EAlso to break the monotony, I decided to align the cards in a \u003Ca href=\u0022https:\/\/masonry.desandro.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Masonry\u003C\/a\u003E manner, instead of just rows.\u003C\/li\u003E\n\u003Cli\u003EWithin the card, I separated the important info (title, author, category) on the top, from the less important (number of words, date of submission, comments, votes and social buttons) on the bottom.\u003C\/li\u003E\n\u003Cli\u003ECategories are pretty important, yet in the old design they weren\u2019t emphasised at all. With the addition of colours they are way more visible, yet to make them even more distinctive and useful, I added icons and a list of all categories on the top.\u003C\/li\u003E\n\u003Cli\u003EI added a footer.\u003C\/li\u003E\n\u003Cli\u003EI reorganised the submission form so that it has a simple up-to-down flow, instead of the previous two columns that made it easy to overlook some fields.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003ECheck out the end effect below. What do you think? \ud83d\ude09\u003C\/p\u003E\n\u003Ch1\u003ENew design\u003C\/h1\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/stoslowia-new-home_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-new-home_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022401.375\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/stoslowia-new-login_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-new-login_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022183.25\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/stoslowia-new-add_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/stoslowia-new-add_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022178.375\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E","words":530,"readTime":3,"lang":"en"}}},"blog\/technology\/it-s-way-too-easy-to-do-webdevelopment-wrong":{"key":"blog\/technology\/it-s-way-too-easy-to-do-webdevelopment-wrong","type":"article","published":true,"meta":{"createdAt":"2018-08-04T01:12:15+02:00","publishedAt":"2018-08-05T11:30:00+02:00","group":"redesign","category":"blog","subcategory":"technology","slug":"it-s-way-too-easy-to-do-webdevelopment-wrong"},"content":{"en":{"slug":"it-s-way-too-easy-to-do-webdevelopment-wrong","title":"It\u0027s way too easy to do webdevelopment wrong","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/wnbr-avris-it-header_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022234.32475039411\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFTUlEQVRIiT2WT48dRxXFf\/fe6n\/vz9gztrGxY4iIsk6+BFkksIrEx0DwZUB8FVgENlkhsidBXrBAZjS2Z97M61ddVfey6Bdq01KrdPucU6fOaZmmKQCWZcFMMTNSSoQ7lhKEo6aYGiaCmBIBqkpKxlIr+3GgH0be3X5ARUAhvGGW8OZc7XccHmZUlc00csqViKDvjFIrtTaG5NyfGmm72VBqxb0hoqgayQxXxd0RESKCx\/sd82lBVLjY7ZiP9ySFEtD3A8O0pZ+PiDvhwTSNnJbCnBeu62ElpkKpjSElcinc3lfSmeBShOZBOs4zIkLf93TJaB6rAgiWErU1CCEvhbFLIEKpFesGSi2ICrU1eq+UUuhUyaWgqtTS6NQopbAZB2pzWqtEMrZjx5CUu2OmeVAAFSGpKusKPALCaeEQIC5EgAs0d3IEItCbcn+8B+DFi1dcXDxGgFwWjqcjXjJLyfSpw6NhJiy1QvD\/1aWOZamoCMUbOa+WSc0rRIAIooImw8Lw1nB3TBURp+GIJojg7uFAlzou9nse7S5Y0SuXl8\/g9oYln6i1QauMW2XT77k7nMinjEewlMZSjlR3qjtCoLr6Uja7bfyokiZDhNU3tSLrdxinEe16vFYC4fLxJUvOjNNIMkNFeHTxiG7oybUg0Tg+3NN1PbVWQg08SCLcvf\/A3cMDpsrDshAiuDutVlQUjebUUqlLpubMcpqZNhOajFAoZeGrX\/2a3hJLzkx9z+9\/+zsuLy7o1RjUGFNiMw7sx2n14VLI5cTxeOA0zxxvP1CXQqvBuNmymyZcgAj8dGI53FHnGS+VFOGA4x5AIKrc390T3hAJ1ITD7S2fffY5X\/zyC\/b7Cx5f7PnFxz\/nzZs3zKeZ7WbDkgvX1zfM+cRmu8NbsCyZPC8gws37O8IdEQV3VIT+fNtS6oGgT4aqGYIiIoCSNBG1EK1CC3764jVff\/0bvvvHd3zzzV\/ZbDb84Y9\/ItnA8eFEqY3\/vL3m+uYGMWM7jsz5SJcGhmni8uljri6veP3yJR+\/\/hnPnjwlEEqrlLxgovRdR9\/3lNaQYRhCVTFVkio1Z9yUy6srXjx\/Rs6ZTz75lJ88f84PP\/wLVeWrL7\/k799+y7\/fvqUz4e31fwl1zJUlV7QzSllQ1fUpcHe4ZztuWFrDW1tND5gCXgkxmkNCgHBqdcJg3G7IJUNUSm0kM77\/\/p\/U5uy3G27ef+Bvf\/kzuTXy8YHN0ycsOdMi8BJU65E883C8A4JxGOlSh4pxe\/+AahARtBqkZHgoiCGiRFRkHMdQlbOHnK7rmKaJZT4ilgig6zo+evmKU17Y77acDve8O9zSmiMBpVWeP3rCOI68mw\/UUig1c9IrthwIAiI4zjNd16Gq5LwgEpgapTnKGrjSdV2ICH3XEQTeKtvdjnk+AoIlZeh7CDAzBkuUWmkRiAi1NjpVBoRGUAGvFTUhDQNzLudeNCIAhFoLokZ4XYP3HMQBJDPFfU1pEUEtUUrBNGHJMDNM7XzmQnFHzQgPamuoKZ2DmEKtIOv7CMjeCBfUFBVZlSLON22dJ4AE+AqGJBJspmlFyQrKmyMKSZVwpwFdZ7TWUDVaOK2t+1sNlmSQMxnHzAgTPIJoazmrGHlZWK3hIBAEXeqo1dfiCqcUR6apj64bVm9HrHVhSrI1tVWV8MBSQmXtoVIbuqqPILRoCCuI5kGXEqaCCLhDqfWsDiRb66eF420VQM5zPUB2u02YCJwHqgrJEqpyZifIj8oFtLYCFkBUzqIHpuuxVHci1jKOOAdhBE4grL8ycSYfKyc81nJ\/9eoj\/gca1kJk61I0igAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/wnbr-avris-it-header_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022234.32475039411\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s honestly diffucult being a webdeveloper in the world of shitty websites. I guess that\u2019s how hairdressers feel when they see my pathetic hair after it\u2019s been a while since my last visit...\u003C\/p\u003E\n\u003Cp\u003EBut the thing is, even though it\u2019s \u003Cem\u003Etechnically\u003C\/em\u003E easy to use scissors and clippers, I don\u2019t do that on my own hair, I leave that to the professionals.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/wnbr-avris-it-header_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022468.64950078823\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFTUlEQVRIiT2WT48dRxXFf\/fe6n\/vz9gztrGxY4iIsk6+BFkksIrEx0DwZUB8FVgENlkhsidBXrBAZjS2Z97M61ddVfey6Bdq01KrdPucU6fOaZmmKQCWZcFMMTNSSoQ7lhKEo6aYGiaCmBIBqkpKxlIr+3GgH0be3X5ARUAhvGGW8OZc7XccHmZUlc00csqViKDvjFIrtTaG5NyfGmm72VBqxb0hoqgayQxXxd0RESKCx\/sd82lBVLjY7ZiP9ySFEtD3A8O0pZ+PiDvhwTSNnJbCnBeu62ElpkKpjSElcinc3lfSmeBShOZBOs4zIkLf93TJaB6rAgiWErU1CCEvhbFLIEKpFesGSi2ICrU1eq+UUuhUyaWgqtTS6NQopbAZB2pzWqtEMrZjx5CUu2OmeVAAFSGpKusKPALCaeEQIC5EgAs0d3IEItCbcn+8B+DFi1dcXDxGgFwWjqcjXjJLyfSpw6NhJiy1QvD\/1aWOZamoCMUbOa+WSc0rRIAIooImw8Lw1nB3TBURp+GIJojg7uFAlzou9nse7S5Y0SuXl8\/g9oYln6i1QauMW2XT77k7nMinjEewlMZSjlR3qjtCoLr6Uja7bfyokiZDhNU3tSLrdxinEe16vFYC4fLxJUvOjNNIMkNFeHTxiG7oybUg0Tg+3NN1PbVWQg08SCLcvf\/A3cMDpsrDshAiuDutVlQUjebUUqlLpubMcpqZNhOajFAoZeGrX\/2a3hJLzkx9z+9\/+zsuLy7o1RjUGFNiMw7sx2n14VLI5cTxeOA0zxxvP1CXQqvBuNmymyZcgAj8dGI53FHnGS+VFOGA4x5AIKrc390T3hAJ1ITD7S2fffY5X\/zyC\/b7Cx5f7PnFxz\/nzZs3zKeZ7WbDkgvX1zfM+cRmu8NbsCyZPC8gws37O8IdEQV3VIT+fNtS6oGgT4aqGYIiIoCSNBG1EK1CC3764jVff\/0bvvvHd3zzzV\/ZbDb84Y9\/ItnA8eFEqY3\/vL3m+uYGMWM7jsz5SJcGhmni8uljri6veP3yJR+\/\/hnPnjwlEEqrlLxgovRdR9\/3lNaQYRhCVTFVkio1Z9yUy6srXjx\/Rs6ZTz75lJ88f84PP\/wLVeWrL7\/k799+y7\/fvqUz4e31fwl1zJUlV7QzSllQ1fUpcHe4ZztuWFrDW1tND5gCXgkxmkNCgHBqdcJg3G7IJUNUSm0kM77\/\/p\/U5uy3G27ef+Bvf\/kzuTXy8YHN0ycsOdMi8BJU65E883C8A4JxGOlSh4pxe\/+AahARtBqkZHgoiCGiRFRkHMdQlbOHnK7rmKaJZT4ilgig6zo+evmKU17Y77acDve8O9zSmiMBpVWeP3rCOI68mw\/UUig1c9IrthwIAiI4zjNd16Gq5LwgEpgapTnKGrjSdV2ICH3XEQTeKtvdjnk+AoIlZeh7CDAzBkuUWmkRiAi1NjpVBoRGUAGvFTUhDQNzLudeNCIAhFoLokZ4XYP3HMQBJDPFfU1pEUEtUUrBNGHJMDNM7XzmQnFHzQgPamuoKZ2DmEKtIOv7CMjeCBfUFBVZlSLON22dJ4AE+AqGJBJspmlFyQrKmyMKSZVwpwFdZ7TWUDVaOK2t+1sNlmSQMxnHzAgTPIJoazmrGHlZWK3hIBAEXeqo1dfiCqcUR6apj64bVm9HrHVhSrI1tVWV8MBSQmXtoVIbuqqPILRoCCuI5kGXEqaCCLhDqfWsDiRb66eF420VQM5zPUB2u02YCJwHqgrJEqpyZifIj8oFtLYCFkBUzqIHpuuxVHci1jKOOAdhBE4grL8ycSYfKyc81nJ\/9eoj\/gca1kJk61I0igAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/wnbr-avris-it-header_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022468.64950078823\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s honestly diffucult being a webdeveloper in the world of shitty websites. I guess that\u2019s how hairdressers feel when they see my pathetic hair after it\u2019s been a while since my last visit...\u003C\/p\u003E\n\u003Cp\u003EBut the thing is, even though it\u2019s \u003Cem\u003Etechnically\u003C\/em\u003E easy to use scissors and clippers, I don\u2019t do that on my own hair, I leave that to the professionals.\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s great that HTML is so easy to learn and that many schools teach it to children. But its simplicity is also a curse, leaving some people convinced that \u201cthey can now do programming\u201d (HTML is a markup language, not a programming language) and that the whole thing is easy.\u003C\/p\u003E\n\u003Cp\u003EAnd, admittedly, writing code that \u003Cem\u003Edoes stuff\u003C\/em\u003E and solves problems isn\u2019t that hard either, especially if you have Google and StackOverflow on your side. The hard part is to write this code is such a way, that another person can understand it, maintain it and modify it, so that groups of programmers can colaborate on it together, so that it can easily be kept up to date... I\u2019ve learned how to write code when I was twelve. But learning, how to write \u003Cem\u003Egood, maintainable code\u003C\/em\u003E, took me years of professional work, and I still have a lot to learn.\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s also difficult for the professionals to keep up to date with technology, it changes so rapidly. For example, a teacher of webdevelopment at a university (!) was teaching my class how to use HTML4 and how to deal with the ISO-8859-1 encoding, even though both HTML5 and UTF-8 have been standards \u003Cem\u003Efor years\u003C\/em\u003E!\u003C\/p\u003E\n\u003Cp\u003EThe same goes, I guess, for the author of \u003Ca href=\u0022http:\/\/wnbr.nl\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E wnbr.nl\u003C\/a\u003E:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/wnbr-nl_big.png\u0022 alt=\u0022Screenshot of wnbr.nl\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022459.81538461538\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAARCAYAAAC1tw6GAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFo0lEQVRIiY2Vy2+dSRHFf1Xd3\/s+4hvHsh1lsJQHMDzEjEZiidiwQGxA\/I2wB3bDZtDsgmCQQE4YSMhjxkl84+vr+\/pe3cXiczJiR0sltdQ61VVd55yWGKPFaDxfrDl0il9scCe3EBEAlruW5a7leNMgZYq7OQbAzHi52LCXefKvLnD3DhFVAJo+8PXllmOLuLrD39l\/jzlf1zgRpq+X6PEeWqTvz57OV3gz4\/T1BZ89fcUvHv6H\/fsz3NEE5z0hBH73tydMJDL+9B\/kv\/oEN84QEZbbmt\/+5Ut+9vqKu21DclDhqhIz4\/N\/n\/Fstebnn54y+el9wsEY5xxd3\/ObPz\/moy7wo7+\/IP31j\/FH+3jveXax4g+PniMhBHuyXLLYtnx4ueSLOjDvDUEIFlk3Hbl3pLsGqhxUEaALkau2Y08VCQHKHAEM2HU9wYyq7ZEiBecQhD5GrpqWSeJwuwZGJZMi4zsHI7qq5OVygwcYBWVjxrqLPFrUnC5qRBUzI8QIBs4Mm7eIHwoyM3ozrl48oVlf4bIcUSHJC8aHH3yDkQZRuc4X6aOhBophbztObo44ynr205JCBb853xJebSgPU2xU8WDXcOA8iJH4jL4PqFdS5wjBQBjCBBOQ2z9ABUI0xA3FxhAxAa9K6AOiiqhAhGAR5xyx2\/Hls1Nmm312l7dpmjXVrQQ\/ulXhM8fxNGddrplsV+zvjXDOYWZDiCOiKIZYAIzQR5xXnHO0bUviE5I0QVVJkgRViNFwqojIkOddL8DjL\/7K7vSUcPsOxbfvMTuacTzJ8PXjr3Ai2OQIAFVH3XQ4F4h1QxBw3pEkKRGo2xZCIPcJQRxd2xEt0rQdWiupKAeHB7TWUFUlkhV4gVQFDRESR4iR73\/8MXe\/+yFthM3jJzgqbHyMdr9\/iPiAmQ2SbWreXLzl4s05Gg2LgRgjdb2jbhr6aIySnCxNKYqSoiwZjUakRUWW5aQo3jku52dsdztCvaULAboeYkQA7xzBhLSaUo0ndJ+fItJhZvjqlz\/EDm\/ybmV5ztRgXBTEKIxSj8hAYtTRdR2I0IQe3wl5nlNWIyaqeBEkGpoo3zp5wHz+lhB6wnrFsu9x6ogizPZu4BNPRFARip\/cRW4fAOC76Ng+X5Ad7kECqUvZao9PMqo8pzFPlgqjsiBGI2J4G3iADOrBjN4i0cBhxD5S5BnHx0eDfVxjhIH8OKFpdteNQjBl9WJBcrCH2nRMcJ56WQ8j64yelFVrRFHKRPAi9F0P0VARuHZxs2Fr0ZAICiAKCJfzS16\/OWc+f4sYg+wBEUFFrzE24KuSXjz1ZY3EGAfyGKw3a74+e81oMsOpQ2SYt4ig19\/C\/7NUIfFwsViQ+ISu71AZ1JZmKaOqYr1pUPWICK\/OnvHg\/gMMG4xxtWv5079e8b22RnPPZtei1iMi+CTB+YRKPeIEvHt\/cdMHPIL2Acn8+5eLZgTxHMz2UUDS6zMzmj7QxYjVHeQO04Gfu67jj4++Hv6ys9WGzgf04VPCRyekE2U2vXl9acQJSNNDmrwvxoBoIDEOpnddDEAfjLbt0T6gmYf2HcZYNT0SIVH9H8x8U9NqGF5IU+HkxojJJ3e4CCm0DW2XYyjBbOhYQfqIWSDxCaKCd4LqN0nfmR4ILkBrAp1BHwYHBySCRyBJQAbMIC\/4YFbhYx8pLns2WYSsQheXXJ0Fmt2KZtuz7Tp85im7jrYDn3uKcUFzWbPNhKlzaNtSd0o5KwhtYLttiaVj3EX6LmLek48z6lXDhkCRePK2pe6VYloyvTFB5g0uM3yzatF1z+G0JE1L7iQZu8a4dW+fxctL6l1Ltl9QxcjmqsfnCdV+xZvmnL29lL08g7pmszFuHE9p1g3r+QZ3VDKO0Kxaggmzkxlv\/nnOJIXppCCzwPKio5yVZEXKcnHFYZXxX4jA\/RIiweP1AAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/wnbr-nl_big.png\u0022 alt=\u0022Screenshot of wnbr.nl\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022459.81538461538\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022http:\/\/wnbr.nl\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        wnbr.nl\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s not a bad website. It gives you the information you need, it doesn\u2019t hurt your eyes, it even uses HTML5 and UTF-8 (so much better than my uni...). On the other hand there\u2019s plenty one could do to make it better:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Eit looks like from two decades ago, could use a new design (the design hasn\u2019t been changed since the beginning of the website in \u003Ca href=\u0022https:\/\/web.archive.org\/web\/20110823123529\/http:\/\/wnbr.nl\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E 2011\u003C\/a\u003E),\u003C\/li\u003E\n\u003Cli\u003Eit doesn\u2019t use HTTPS, which is not understandable in the times of \u003Ca href=\u0022https:\/\/letsencrypt.org\/getting-started\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E free and easy SSL certificates\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Ethe route is described in plain text (in a separate file!), even though it could easily (and conveniently for the visitors who don\u2019t know the city) be a map,\u003C\/li\u003E\n\u003Cli\u003Eit uses an external website, \u003Ca href=\u0022http:\/\/www.ipernity.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Ipernity\u003C\/a\u003E, as a photo galery \u2013 that website\u2019s UX is \u003Cem\u003Ehorrible\u003C\/em\u003E (it took me ages to simply upload some pictures), and its functionality could be easily integrated into the main website,\u003C\/li\u003E\n\u003Cli\u003Eit only provides a Dutch version, which is strange, since the event itself is pretty much English-speaking, with many international participants,\u003C\/li\u003E\n\u003Cli\u003Eit\u2019s not responsive, instead offers a separate version for mobile.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAnd while it\u2019s completely fine if a personal website or a side project looks like that, I feel really \u003Cem\u003Esad\u003C\/em\u003E when I see a website of a doctor, a business, or a big event, that is so far away in the past... Plenty of people are working on constant improvements of the standards, on new technologies, new approaches, new APIs \u2013 and yet, as a user, I\u2019m still left with not being able to make a doctor\u2019s appointment online, as if it was so damn hard to implement... Spending your whole life on digitalising the world bit by bit, but not being able to fully enojoy that digitalisation as a user really sucks...\u003C\/p\u003E\n\u003Cp\u003EAnyways... As a person, who wants to make the world (also the cyber-world) a better place, who really \u003Ca href=\u0022\/blog\/my-first-world-naked-bike-ride-and-i-absolutelly-loved-it\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-heartbeat\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E enjoyed the WNBR this year\u003C\/a\u003E and who happened to have some free time on my hands, I contacted the organisers and offered them my help in bringing their website to the 21st century.\u003C\/p\u003E\n\u003Cp\u003EI assumed they wouldn\u2019t want it, actually. Somebody created the current website (\u003Ca href=\u0022http:\/\/www.nsesoftware.nl\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E nsesoftware.nl\u003C\/a\u003E), somebody is proud of it, and obviously nobody likes criticism... So I tried to be nice, not to criticise, but to offer some ideas and help.\u003C\/p\u003E\n\u003Cp\u003EI got no answer though, and I really needed to start right away, as long as I had free time and the motivation to work on it. I ended up with something like this:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/wnbr-avris-it_big.png\u0022 alt=\u0022My proposal of the refreshed version of wnbr.nl\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00222295\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAkCAYAAABWvWC\/AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEDUlEQVRIia2VzW4cVRCFv6p7b3fPrx3biRNFSDGBxAghBIkS1rwBOyS2bBCvwY4H4BUQQiRL1uyygUQmEkJRgADBMYk9sWfGPd19b7Foe+JJYINypZZa1X3qVJ2uOi39ft+apiELAVHodzr44MGMTrfLeDJGBZomEpxDRGlixCyhlhJZ5gHDUiKmRBMb1DuWV9bwWaCuawSjLCsEYzarGB1M8SaQgKzIcEBvacDa6mnK6ZTMOzY2XmX\/6S5NTCiOvd1dklOcd3hLkRgjlSU2Ni5w9co1Ni9vcuPrrxgfHGAiNNYQq4a6TpRlhTMDVbwZeFWKLCc1iV\/u3+fh73+AKIdlSRNhPBnj1CgPSwxDEBBB8jw37x3eO0SEPMvwojSWyJLRmBEtklBUlSYlLEZiMnwILUigVdOMxlo1K4Noifa0YooBIqgYcvPmDQNQUURARDCzeUIAA8zAsHnAzBAzMwCzRDmrcD5wDHMqyHGGE0eOgv44YAYCxLpGBFSVaMLeaESKiV6\/R\/CePM\/nSfT4pmkaJtMpdV1TVRXjyQSAfr9PyAIpxraVE6XMmUUEVcUwUkw45\/DeE0Kg2+m8WDs86\/n\/nDlz3dSUZclsVoMGJk3FsMi4NxHWXYUko9KM80sdiswvgjEYH1ZkEnmwCyk13J81rK6UPJWAljVol3pQUDzP3MRIMhhXY2ax4OxyTj4VQh2YyS7rvSEpJXJJc7652qqOJ+lvDsxxKkBBzVq\/QiRx1g9ICAklnpBoDgbjXLZOVx2DXoZpjuJpRBiNlQePtxEV0GfgudoxJqqqwnuHwXw0o4FK+9xI5FmGU7fY8+jpHnfu\/MCVq9dRdfy4dZu11VXKw4qllQ4xGsOlVbBEt9NbBO9sP+SLzz9j853r5P0hj+7e4pU33mLweEx+6RwpJh7d+4sPP\/mUi5c3n\/tUGN2VU7z52iWC97z\/3lWK3pCdx0\/Y2rqDYfx6MGE6m704JGvDPtc2N1gfdOiEgj+375IX57m99ROD4ZCqqkDg5Di+nPGcTg\/ZG43IQpiv32Qy5nBWsX7mDHpkEim1S7PAPK0S+6Wx1BGSQTe0Ne6O9gje471HRPHeEUIATgxJazVtB90gcztqmnaPnXOIMGddAGOgIjgRmnQcMhJQ+YISh\/fh33turae9vB55mHN8+82XhF5GcBWUygcffUx2ZEULs60YKS0kZzlkTLd3WC1Oc3r9HCcd8Zlgs5r9ScXyoEsR2hfG0wmY0O0UqCopWUuiulg2ZjiryH13Hup3e9z6\/juK4FEVnBNev\/guqtkiOMsCISwvuGMy4+ffdsjLMU9GJZXbZ+PC2xx9qZdlgDHR1A2iDucUr\/8NOq5uzpxSIqaTNnD0KyW1yyAKZninc\/A\/I277Xjf7CncAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/wnbr-avris-it_big.png\u0022 alt=\u0022My proposal of the refreshed version of wnbr.nl\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u00222295\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI got nothing but positive feedback from all the friends whom I\u2019ve shown the end result. Still, I got no response from the WNBR people on wheather or not they actually want it. But since it\u2019s almost done already, I\u2019ve sent them a demo, saying that if they do, it\u2019s free for them to use.\u003C\/p\u003E\n\u003Cp\u003EAfter a while I kind of got an answer \u2013 not a \u201cno, thanks\u201d, or even \u201cfuck off\u201d... instead, I just got blocked on Twitter. So childish... Well, that\u2019s how you lose like a 1000\u20ac worth of free service, too bad for them.\u003C\/p\u003E\n\u003Cp\u003EAnyways... a couple of days ago I stumbled upon the website \u003Ca href=\u0022https:\/\/www.polyamorynetwork.com\/private\/signup\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E polyamorynetwork.com\u003C\/a\u003E. I totally fell in love with their logo \ud83d\ude0d And even though I\u2019m not a polyamorist myself (yet?), I decided to check it out anyway.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/polyamorynetwork-com_big.png\u0022 alt=\u0022Screenshot of the registration form at polyamorynetwork.com\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022755.98971722365\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAcCAYAAAAJKR1YAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADZ0lEQVRIic2XSW8kRRCFv4jM2u32MHAYLCMkDogD4gBc+PlckPgTCKE5jWwsL92urqrMmEMtU73YhqEMhNTq6FZF5MuXLyKj5OrqyviPLIZAiBEAVcU5hzcz4s+\/Ql1z+\/WXvGsfEBHW6zVFXuC8o65r8iyn7VrOzy84O3u1CCBRxatOv83AiwiEAFVJef6G87YhhoBhOOep6wdUldB1iCplWSEimNnOd5\/wn\/ogl5eX\/ZGFgHh\/sIsQOsyYFnfOTUlewlREUFV8liHSI028J4RImqaoKlVVAUJZFpgZaZoSY0RVURFA8EOMyOgHQgjTBsa4EAJ5nlMUxc4nyzJgYKjrOpw6GAABxBhxzhFjnBgREdq2RURI03RxdszAA1xfX+OcA8A5pWm7gaUwPGj44ThFBHWOJEleQEPSM1RVFdumwakO1GZ47xZn4CkLIXB\/f98zpKpYjNhMuIhij3QoEXC6HCujTUc2ggohUFUVzil1ExBVBNjHJSKo2CzRMr7IAChN0wORZl7YNtsJzLgb5xyJT16s9D1A0zRsNhvyoiAbgYlMpbhv4672G+T8v2P+fGPHnpkAJUnC2dnZwaJN09K3GWFXUEaW5VOipY5s0lDbtmw2G1QElySURUEP9LBzQ6+3fYbmu\/8YH57REEAXwsSMATJIPMuynWb5IeHH+6P1GtpuWW8eEIHVaoWq9t04SY4ytHQzPACUpCmvZgyZGV3XcXd31weIYMPcYhZRdZycnJAMgBfX0DHqnHOUZXkwZowJxotzvHKWsElDo6jzPJ+01F+kDUbPTg+6V5Kqkuc5zrlny35k4amyn5sfuRIR6rqmrh84PV1hFvE+ORoE4L1\/ubJP0hSffFjczIixX5SHup8o0xQEaDsQoa234BxS5DtaWqTs91kQkX4OenfJ7R9v4aSCbUMn0N2twfUj7SdlSfb9dzyW4+\/4ox3vfAP6enVC8u03jFOliNBtNmxv7wjbhvqz11hdT7pbrOzn5zgHNI6pdQPRfD+u3txy89vvbOs1fnvBpxdf\/Dtlr6p0XUeMETPDbA2qhNWK1Y8\/AJA45bQsFrv5Jw0dY+jPuuOXtzdgxk9ffc6bVTkL3O1Lf+WVaB63n2O0nQFt3zKvvK5yAPK9cfapcn\/sOJ57fgI6vZf9D0xEeA8eTKpuIuGc+gAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/polyamorynetwork-com_big.png\u0022 alt=\u0022Screenshot of the registration form at polyamorynetwork.com\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022755.98971722365\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/www.polyamorynetwork.com\/private\/signup\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        polyamorynetwork.com\/private\/signup\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI couldn\u2019t, though. Setting aside that the SSL certificate was expired since a month, which makes browsers give the user a scary red security warning... The registration form still uses reCAPTCHA v1, which got shutdown in March 2018 (and deprecated way earlier). That means nobody was able to join their network for the last half a year, and apparently nobody noticed!\u003C\/p\u003E\n\u003Cp\u003EIs the website abandoned? Why can\u2019t it just say so? Or maybe there\u2019s a big, active community there, but it\u2019s closed for new members, because the admin doesn\u2019t give a damn anymore? I guess I\u2019ll never know.\u003C\/p\u003E\n\u003Ch3\u003ESumming up\u003C\/h3\u003E\n\u003Cp\u003EOn one hand it\u2019s great that anyone can build their own website \u2013 that\u2019s what makes the web thrive, that\u2019s what makes it open and equal!\u003C\/p\u003E\n\u003Cp\u003EOn the other hand though \u2013 it requires way more skill and knowledge to do it \u003Cem\u003Eright\u003C\/em\u003E. If you want to look professional, keep that in mind.\u003C\/p\u003E\n\u003Cp\u003ESo what\u2019s my point? I guess I don\u2019t have any, just wanted to complain a bit.\u003C\/p\u003E\n\u003Cp\u003EExcept maybe for one thing:\u003C\/p\u003E\n\u003Ch3\u003EFree website, anyone?\u003C\/h3\u003E\n\u003Cp\u003EIf you have (or want to start) a project, event or a non-profit organisation that I could stand behind (LGBTQ rights, human rights, naturism, non-monogamy, education...) that I could support from the IT side, feel free to \u003Ca href=\u0022mailto:andre@avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E contact me\u003C\/a\u003E \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["botch","design","maintainability","programming","progress","security","shit","up-to-date","volunteering","redesign","web","webdevelopment"],"hasMore":true,"image":"https:\/\/avris.it\/image\/wnbr-avris-it-header_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/wnbr-avris-it-header_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/wnbr-avris-it-header_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022117.16237519706\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s honestly diffucult being a webdeveloper in the world of shitty websites. I guess that\u2019s how hairdressers feel when they see my pathetic hair after it\u2019s been a while since my last visit...\u003C\/p\u003E\n\u003Cp\u003EBut the thing is, even though it\u2019s \u003Cem\u003Etechnically\u003C\/em\u003E easy to use scissors and clippers, I don\u2019t do that on my own hair, I leave that to the professionals.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/wnbr-avris-it-header_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/wnbr-avris-it-header_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022117.16237519706\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s honestly diffucult being a webdeveloper in the world of shitty websites. I guess that\u2019s how hairdressers feel when they see my pathetic hair after it\u2019s been a while since my last visit...\u003C\/p\u003E\n\u003Cp\u003EBut the thing is, even though it\u2019s \u003Cem\u003Etechnically\u003C\/em\u003E easy to use scissors and clippers, I don\u2019t do that on my own hair, I leave that to the professionals.\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s great that HTML is so easy to learn and that many schools teach it to children. But its simplicity is also a curse, leaving some people convinced that \u201cthey can now do programming\u201d (HTML is a markup language, not a programming language) and that the whole thing is easy.\u003C\/p\u003E\n\u003Cp\u003EAnd, admittedly, writing code that \u003Cem\u003Edoes stuff\u003C\/em\u003E and solves problems isn\u2019t that hard either, especially if you have Google and StackOverflow on your side. The hard part is to write this code is such a way, that another person can understand it, maintain it and modify it, so that groups of programmers can colaborate on it together, so that it can easily be kept up to date... I\u2019ve learned how to write code when I was twelve. But learning, how to write \u003Cem\u003Egood, maintainable code\u003C\/em\u003E, took me years of professional work, and I still have a lot to learn.\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s also difficult for the professionals to keep up to date with technology, it changes so rapidly. For example, a teacher of webdevelopment at a university (!) was teaching my class how to use HTML4 and how to deal with the ISO-8859-1 encoding, even though both HTML5 and UTF-8 have been standards \u003Cem\u003Efor years\u003C\/em\u003E!\u003C\/p\u003E\n\u003Cp\u003EThe same goes, I guess, for the author of \u003Ca href=\u0022http:\/\/wnbr.nl\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E wnbr.nl\u003C\/a\u003E:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/wnbr-nl_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/wnbr-nl_mini.png\u0022 alt=\u0022Screenshot of wnbr.nl\u0022 width=\u0022240\u0022 height=\u0022114.95384615385\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022http:\/\/wnbr.nl\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Ewnbr.nl\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s not a bad website. It gives you the information you need, it doesn\u2019t hurt your eyes, it even uses HTML5 and UTF-8 (so much better than my uni...). On the other hand there\u2019s plenty one could do to make it better:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Eit looks like from two decades ago, could use a new design (the design hasn\u2019t been changed since the beginning of the website in \u003Ca href=\u0022https:\/\/web.archive.org\/web\/20110823123529\/http:\/\/wnbr.nl\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E 2011\u003C\/a\u003E),\u003C\/li\u003E\n\u003Cli\u003Eit doesn\u2019t use HTTPS, which is not understandable in the times of \u003Ca href=\u0022https:\/\/letsencrypt.org\/getting-started\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E free and easy SSL certificates\u003C\/a\u003E,\u003C\/li\u003E\n\u003Cli\u003Ethe route is described in plain text (in a separate file!), even though it could easily (and conveniently for the visitors who don\u2019t know the city) be a map,\u003C\/li\u003E\n\u003Cli\u003Eit uses an external website, \u003Ca href=\u0022http:\/\/www.ipernity.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Ipernity\u003C\/a\u003E, as a photo galery \u2013 that website\u2019s UX is \u003Cem\u003Ehorrible\u003C\/em\u003E (it took me ages to simply upload some pictures), and its functionality could be easily integrated into the main website,\u003C\/li\u003E\n\u003Cli\u003Eit only provides a Dutch version, which is strange, since the event itself is pretty much English-speaking, with many international participants,\u003C\/li\u003E\n\u003Cli\u003Eit\u2019s not responsive, instead offers a separate version for mobile.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EAnd while it\u2019s completely fine if a personal website or a side project looks like that, I feel really \u003Cem\u003Esad\u003C\/em\u003E when I see a website of a doctor, a business, or a big event, that is so far away in the past... Plenty of people are working on constant improvements of the standards, on new technologies, new approaches, new APIs \u2013 and yet, as a user, I\u2019m still left with not being able to make a doctor\u2019s appointment online, as if it was so damn hard to implement... Spending your whole life on digitalising the world bit by bit, but not being able to fully enojoy that digitalisation as a user really sucks...\u003C\/p\u003E\n\u003Cp\u003EAnyways... As a person, who wants to make the world (also the cyber-world) a better place, who really \u003Ca href=\u0022\/blog\/my-first-world-naked-bike-ride-and-i-absolutelly-loved-it.lite\u0022\u003E enjoyed the WNBR this year\u003C\/a\u003E and who happened to have some free time on my hands, I contacted the organisers and offered them my help in bringing their website to the 21st century.\u003C\/p\u003E\n\u003Cp\u003EI assumed they wouldn\u2019t want it, actually. Somebody created the current website (\u003Ca href=\u0022http:\/\/www.nsesoftware.nl\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E nsesoftware.nl\u003C\/a\u003E), somebody is proud of it, and obviously nobody likes criticism... So I tried to be nice, not to criticise, but to offer some ideas and help.\u003C\/p\u003E\n\u003Cp\u003EI got no answer though, and I really needed to start right away, as long as I had free time and the motivation to work on it. I ended up with something like this:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/wnbr-avris-it_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/wnbr-avris-it_mini.png\u0022 alt=\u0022My proposal of the refreshed version of wnbr.nl\u0022 width=\u0022240\u0022 height=\u0022573.75\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI got nothing but positive feedback from all the friends whom I\u2019ve shown the end result. Still, I got no response from the WNBR people on wheather or not they actually want it. But since it\u2019s almost done already, I\u2019ve sent them a demo, saying that if they do, it\u2019s free for them to use.\u003C\/p\u003E\n\u003Cp\u003EAfter a while I kind of got an answer \u2013 not a \u201cno, thanks\u201d, or even \u201cfuck off\u201d... instead, I just got blocked on Twitter. So childish... Well, that\u2019s how you lose like a 1000\u20ac worth of free service, too bad for them.\u003C\/p\u003E\n\u003Cp\u003EAnyways... a couple of days ago I stumbled upon the website \u003Ca href=\u0022https:\/\/www.polyamorynetwork.com\/private\/signup\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E polyamorynetwork.com\u003C\/a\u003E. I totally fell in love with their logo \ud83d\ude0d And even though I\u2019m not a polyamorist myself (yet?), I decided to check it out anyway.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/polyamorynetwork-com_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/polyamorynetwork-com_mini.png\u0022 alt=\u0022Screenshot of the registration form at polyamorynetwork.com\u0022 width=\u0022240\u0022 height=\u0022188.99742930591\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/www.polyamorynetwork.com\/private\/signup\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Epolyamorynetwork.com\/private\/signup\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI couldn\u2019t, though. Setting aside that the SSL certificate was expired since a month, which makes browsers give the user a scary red security warning... The registration form still uses reCAPTCHA v1, which got shutdown in March 2018 (and deprecated way earlier). That means nobody was able to join their network for the last half a year, and apparently nobody noticed!\u003C\/p\u003E\n\u003Cp\u003EIs the website abandoned? Why can\u2019t it just say so? Or maybe there\u2019s a big, active community there, but it\u2019s closed for new members, because the admin doesn\u2019t give a damn anymore? I guess I\u2019ll never know.\u003C\/p\u003E\n\u003Ch3\u003ESumming up\u003C\/h3\u003E\n\u003Cp\u003EOn one hand it\u2019s great that anyone can build their own website \u2013 that\u2019s what makes the web thrive, that\u2019s what makes it open and equal!\u003C\/p\u003E\n\u003Cp\u003EOn the other hand though \u2013 it requires way more skill and knowledge to do it \u003Cem\u003Eright\u003C\/em\u003E. If you want to look professional, keep that in mind.\u003C\/p\u003E\n\u003Cp\u003ESo what\u2019s my point? I guess I don\u2019t have any, just wanted to complain a bit.\u003C\/p\u003E\n\u003Cp\u003EExcept maybe for one thing:\u003C\/p\u003E\n\u003Ch3\u003EFree website, anyone?\u003C\/h3\u003E\n\u003Cp\u003EIf you have (or want to start) a project, event or a non-profit organisation that I could stand behind (LGBTQ rights, human rights, naturism, non-monogamy, education...) that I could support from the IT side, feel free to \u003Ca href=\u0022mailto:andre@avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E contact me\u003C\/a\u003E \ud83d\ude09\u003C\/p\u003E","words":1080,"readTime":5,"lang":"en"}}},"blog\/technology\/git-is-not-just-for-programmers-here-s-why-you-should-learn-it-too":{"key":"blog\/technology\/git-is-not-just-for-programmers-here-s-why-you-should-learn-it-too","type":"article","published":true,"meta":{"createdAt":"2018-06-25T15:31:05+02:00","publishedAt":"2018-06-27T16:30:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"git-is-not-just-for-programmers-here-s-why-you-should-learn-it-too"},"content":{"en":{"slug":"git-is-not-just-for-programmers-here-s-why-you-should-learn-it-too","title":"Git is not just for programmers! Here\u0027s why you should learn it too.","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/photoshop-final_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022465\u0022 height=\u0022261\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAIhklEQVRIiQXByW+cZwHA4d+3z+ZZPPaMtzje0sRJ4yxt4jRp06alq6LCoYdCoVKRWC5cEOLEIX8BBziCkKjEgRZKW+gidVFoUZckbhzH8R473mc8+\/It820vzyN9+cmbQpYTTB4\/ie+Z7Gw8oFipM3RoGMdy2C3scuXpZ9AiCRAhrusgqxq6qiB8DzeQ+eztN7k7cxOzI6ibJs9dfQkhwdzsHO1GlXrDItudJNeboWNZ+IFPGAo83ycMfFw\/wO4EjJ6aQG07IYZi44ceLV9nrZ3ky3XYWpJwbIHrdHO9scNvX8igy1BvNgnQGOjNIMkK87du8sn77\/LKMxdJpnv50zsfUl9fZfzSk8SSm2xtPsCIJDj76GmOjA9T2t8nCAW+UPC8ABH6BKGPZXV45\/rnKJcvX7w2N3uHtaUFbuzH+d0HTV59+iEIfc5OZHl3psqN5X2U0UFG5QOG83kiqozrudTKFVaXFhCNEjghcihxaeoICIXskaPomoYemJgdh9NnznJ4aADXsVA0nd2axUHLoml7NGyXpuWwsbWJKiRwnQ7Njs2BvULKCnn7PyVisSjFHR27sImvxvnj799nbSrBn3\/dRyKdolGtISGRSqTpnzhJ1jHpS3exWypRMh0Obt3iYH+TGC7JmIGp5\/lkI8789mEKzYDjmRoDsS0wIqgSeH6ArMgo2cHctYyh051J8uSFKX7z6mNsWFH+Pq+yWIniRXMIPYWnZajVbX74SIJEqhfbNglDmXrTw8MgUDUqO1vstdp4w5cZPf04ld01Yl1RfCGzZvVwfaFOxAiZXavwTQG2Zr9Cb95Hciqceux5bsx8g6yoKqEQeCGoqgZI4HUwEjInXppk4vwQstRBpoPdbnHn2y\/w\/YBWu83+\/h4LS4vs7m3T1CI0jSgrVhcnnrhC1VI59tTr5EZOoRsRfnV1kl8+d5y37sfZ1ofYbSVZtvvxmi2OH53g3PQljFgUNfB8AkkiRKDqBiEh1cID5DBHp20R7Y4y9YPzbH89h7fosLN1wN7WHporyBkpXph+DCMSJRA+tckpagsV5u4sUmuFqMLkxNRZBkMNLRpFKC16hruIRDRCkaL5rzaV4j73\/vshxYpLo1JFVWSZIAzwfYXyQYVsMs7q7G3C9EUcEbLx3iekjx1BP9yHPVNnbWWNx2tl\/vCXv5HJZ9GjCbJ9eVYXV3B9ha6Rafywg0ChUdpEBD7pbB7b9pBdm8b6LvvbO6RPTaK4DWIJnV6\/g7V5DxEKVEOWEIFHt1vCLW5QlB0a5QKutcXeRyX8ag0zIuPfnsHotFi+t0i9vMsbL76A5DkMfu8q+6vLhA2bgqlTq1cYGOzDMBJMjFzgi88\/5vS5JNsFk05pncz8+xxKZplqmTz60xfJKOdo3PsawoB0VEf5+Wvfv2a3TF5+appHn3iGpRv\/46vbK4QEjGkmh2Id8l6VmFNCc0p0WXvkYwFPPPUcSjbDTtWmY7WoOD5re01Mq8n45HmWV1bpyuax6nt0Oi6G5JJJSMQ7FdKGz4+fHCcb9UkOHCMxMYqdUBk4chj10sXLFDPfYbke+7bBQRDl\/NFeWm6b6TGDeCpLNGZQb8X54OMZ8lOP4CWHiZ++gF+pYM3Ocmb6ERqBw+z9Mgcbm5RLBfLpKD2pCPbIJLVKBeHaPDzWx0d\/vcPkuWcZVNuodFgvhkTOXyHW4zGGQK0XCshhSC0+TDwMGLVtVNsmfmYMybPpiskohsxYT57TP3udgy9u0l2oEFgWsa4uJkfyRA0doWVpmy7lwh6+XSc3MM72g13sVp3d3W2SYYzwRIznX\/kRLRHHd7cIREhRSRGrtGlKFny3hHLh4dFrO6bEyeMnGP3sK8ZmljjRdMjU26TRyAqdPhf6KyZDc+scqzgMBRru3gPCiWES+X4kLcLt2WUs0wbJY2PpLs7Kp\/zkpErCa1CPDKBqCsdSDtX8NM1KhX6vTLllU+w5hWbIRPsU6vd3UU00rjz7LNXFW+S3FugOfFRNJV\/tEN99QFTdRtF0VE0n1DUkVSVs12gPaUgHW6jZHCrQMDvslmo02oLi3iZXL4+j6DoLOztstyXSmkulP0HRLqOaFXxcqh0ZWdGIhAqHWsPcVpaQ69UmH733b3aX5ylKDgQ+kqKh6jqpWAIhySi6BpqOrOngh5jZKB1Nprm9hm50ISkG9+bmyKbixHQYGRtnIJOgXmtiRjL059LodpGVxXl0I0JcFXi+R5kYlllHBIKoajD80DHkkazERCYk6Fjs1CsEvgeShNA0JF0jEo8DMqgqyDKBa1Pr1unYbcpbq4jARwKSPYOsL9+jbbsYkW4MVaZQqrDd1Cg3bCLxLs6+\/BqReJRBtYPZauKkhhGhQJIhnemlJ59DHjl6jEJhExG4dMIANBlkQAiQAElG0nWQZZAUlFgcz3bwPR\/XahH6HcrVOvfuztCTyzF15iw9CQlVVlk6MNF1DVk4qJrCwNGTJOqbSGaZ+5ZGND+Mqht0xaIYhky+bxD5u5UC\/7y+RKtt0gkDiqUyZrmKZ7bxbQff6RDYNqHZJmw3cBwb3ROIUKBIEpKicXd+BbNtEqhJbDsgF1MQAtbtBNn8ITI9\/WR6+ohE4mjbdyg22lij06S6c6h6hFRcxaxuI6kK6utv\/ILDo2Moy9\/irG6wUCnQK+vEdA1VkpElGRlQFBlJgE1AOdlDwvNQYkkkWeatt97h8PAQRybHub+8giHZbFQF1baPXCygqQbRTBd7Czcxq0U2Y2N0H5nCiEfp8pMM5HMYiqBuNlErdpWRExM82PiGdkzBSym0TJOkUIkIGSSJUAhCXyAksESArafJBy2kZJ6lrTXackgyk+XOyjz9A3kSVpF4tpecGpLqjROPJaFLMPPpP1gPNET\/GNsLs5w5fwYjbdCWfJSIgRuG\/B85c1HN1kY6CQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/photoshop-final_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022465\u0022 height=\u0022261\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI had to learn \u003Ca href=\u0022https:\/\/git-scm.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Git\u003C\/a\u003E as a programmer. If you want to easily collaborate on a codebase, you really need either Git or something similar. But as a non-programmer, you\u2019ve probably never even heard that name, have you? Then why would you ever need it?\u003C\/p\u003E\n\u003Cp\u003EWell, for exactly the same reasons!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/photoshop-final_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022465\u0022 height=\u0022261\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAIhklEQVRIiQXByW+cZwHA4d+3z+ZZPPaMtzje0sRJ4yxt4jRp06alq6LCoYdCoVKRWC5cEOLEIX8BBziCkKjEgRZKW+gidVFoUZckbhzH8R473mc8+\/It820vzyN9+cmbQpYTTB4\/ie+Z7Gw8oFipM3RoGMdy2C3scuXpZ9AiCRAhrusgqxq6qiB8DzeQ+eztN7k7cxOzI6ibJs9dfQkhwdzsHO1GlXrDItudJNeboWNZ+IFPGAo83ycMfFw\/wO4EjJ6aQG07IYZi44ceLV9nrZ3ky3XYWpJwbIHrdHO9scNvX8igy1BvNgnQGOjNIMkK87du8sn77\/LKMxdJpnv50zsfUl9fZfzSk8SSm2xtPsCIJDj76GmOjA9T2t8nCAW+UPC8ABH6BKGPZXV45\/rnKJcvX7w2N3uHtaUFbuzH+d0HTV59+iEIfc5OZHl3psqN5X2U0UFG5QOG83kiqozrudTKFVaXFhCNEjghcihxaeoICIXskaPomoYemJgdh9NnznJ4aADXsVA0nd2axUHLoml7NGyXpuWwsbWJKiRwnQ7Njs2BvULKCnn7PyVisSjFHR27sImvxvnj799nbSrBn3\/dRyKdolGtISGRSqTpnzhJ1jHpS3exWypRMh0Obt3iYH+TGC7JmIGp5\/lkI8789mEKzYDjmRoDsS0wIqgSeH6ArMgo2cHctYyh051J8uSFKX7z6mNsWFH+Pq+yWIniRXMIPYWnZajVbX74SIJEqhfbNglDmXrTw8MgUDUqO1vstdp4w5cZPf04ld01Yl1RfCGzZvVwfaFOxAiZXavwTQG2Zr9Cb95Hciqceux5bsx8g6yoKqEQeCGoqgZI4HUwEjInXppk4vwQstRBpoPdbnHn2y\/w\/YBWu83+\/h4LS4vs7m3T1CI0jSgrVhcnnrhC1VI59tTr5EZOoRsRfnV1kl8+d5y37sfZ1ofYbSVZtvvxmi2OH53g3PQljFgUNfB8AkkiRKDqBiEh1cID5DBHp20R7Y4y9YPzbH89h7fosLN1wN7WHporyBkpXph+DCMSJRA+tckpagsV5u4sUmuFqMLkxNRZBkMNLRpFKC16hruIRDRCkaL5rzaV4j73\/vshxYpLo1JFVWSZIAzwfYXyQYVsMs7q7G3C9EUcEbLx3iekjx1BP9yHPVNnbWWNx2tl\/vCXv5HJZ9GjCbJ9eVYXV3B9ha6Rafywg0ChUdpEBD7pbB7b9pBdm8b6LvvbO6RPTaK4DWIJnV6\/g7V5DxEKVEOWEIFHt1vCLW5QlB0a5QKutcXeRyX8ag0zIuPfnsHotFi+t0i9vMsbL76A5DkMfu8q+6vLhA2bgqlTq1cYGOzDMBJMjFzgi88\/5vS5JNsFk05pncz8+xxKZplqmTz60xfJKOdo3PsawoB0VEf5+Wvfv2a3TF5+appHn3iGpRv\/46vbK4QEjGkmh2Id8l6VmFNCc0p0WXvkYwFPPPUcSjbDTtWmY7WoOD5re01Mq8n45HmWV1bpyuax6nt0Oi6G5JJJSMQ7FdKGz4+fHCcb9UkOHCMxMYqdUBk4chj10sXLFDPfYbke+7bBQRDl\/NFeWm6b6TGDeCpLNGZQb8X54OMZ8lOP4CWHiZ++gF+pYM3Ocmb6ERqBw+z9Mgcbm5RLBfLpKD2pCPbIJLVKBeHaPDzWx0d\/vcPkuWcZVNuodFgvhkTOXyHW4zGGQK0XCshhSC0+TDwMGLVtVNsmfmYMybPpiskohsxYT57TP3udgy9u0l2oEFgWsa4uJkfyRA0doWVpmy7lwh6+XSc3MM72g13sVp3d3W2SYYzwRIznX\/kRLRHHd7cIREhRSRGrtGlKFny3hHLh4dFrO6bEyeMnGP3sK8ZmljjRdMjU26TRyAqdPhf6KyZDc+scqzgMBRru3gPCiWES+X4kLcLt2WUs0wbJY2PpLs7Kp\/zkpErCa1CPDKBqCsdSDtX8NM1KhX6vTLllU+w5hWbIRPsU6vd3UU00rjz7LNXFW+S3FugOfFRNJV\/tEN99QFTdRtF0VE0n1DUkVSVs12gPaUgHW6jZHCrQMDvslmo02oLi3iZXL4+j6DoLOztstyXSmkulP0HRLqOaFXxcqh0ZWdGIhAqHWsPcVpaQ69UmH733b3aX5ylKDgQ+kqKh6jqpWAIhySi6BpqOrOngh5jZKB1Nprm9hm50ISkG9+bmyKbixHQYGRtnIJOgXmtiRjL059LodpGVxXl0I0JcFXi+R5kYlllHBIKoajD80DHkkazERCYk6Fjs1CsEvgeShNA0JF0jEo8DMqgqyDKBa1Pr1unYbcpbq4jARwKSPYOsL9+jbbsYkW4MVaZQqrDd1Cg3bCLxLs6+\/BqReJRBtYPZauKkhhGhQJIhnemlJ59DHjl6jEJhExG4dMIANBlkQAiQAElG0nWQZZAUlFgcz3bwPR\/XahH6HcrVOvfuztCTyzF15iw9CQlVVlk6MNF1DVk4qJrCwNGTJOqbSGaZ+5ZGND+Mqht0xaIYhky+bxD5u5UC\/7y+RKtt0gkDiqUyZrmKZ7bxbQff6RDYNqHZJmw3cBwb3ROIUKBIEpKicXd+BbNtEqhJbDsgF1MQAtbtBNn8ITI9\/WR6+ohE4mjbdyg22lij06S6c6h6hFRcxaxuI6kK6utv\/ILDo2Moy9\/irG6wUCnQK+vEdA1VkpElGRlQFBlJgE1AOdlDwvNQYkkkWeatt97h8PAQRybHub+8giHZbFQF1baPXCygqQbRTBd7Czcxq0U2Y2N0H5nCiEfp8pMM5HMYiqBuNlErdpWRExM82PiGdkzBSym0TJOkUIkIGSSJUAhCXyAksESArafJBy2kZJ6lrTXackgyk+XOyjz9A3kSVpF4tpecGpLqjROPJaFLMPPpP1gPNET\/GNsLs5w5fwYjbdCWfJSIgRuG\/B85c1HN1kY6CQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/photoshop-final_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022465\u0022 height=\u0022261\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/twitter.com\/PicturesFoIder\/status\/1011236244796342274\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        twitter.com\/PicturesFoIder\/status\/1011236244796342274\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI had to learn \u003Ca href=\u0022https:\/\/git-scm.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Git\u003C\/a\u003E as a programmer. If you want to easily collaborate on a codebase, you really need either Git or something similar. But as a non-programmer, you\u2019ve probably never even heard that name, have you? Then why would you ever need it?\u003C\/p\u003E\n\u003Cp\u003EWell, for exactly the same reasons!\u003C\/p\u003E\n\u003Ch3\u003EWhat is Git?\u003C\/h3\u003E\n\u003Cp\u003EIt\u2019s a version control system, which means it remembers how the content of a directory (called \u201crepository\u201d) changed over time. You can decide, wich moments in time are saved \u2013 those snapshots of the repository are called \u201ccommits\u201d. You can send those commits to a server (it\u2019s called \u201cpushing\u201d), so that other people can download them (\u201dpull\u201d) and collaborate and your project (plus the server works as a backup of your data). If you ever want to revert your repository to how it looked like some time ago, or to see how it changed over time, or who wrote a particular line in a file, etc. etc., Git offers you all of that.\u003C\/p\u003E\n\u003Ch3\u003EWhy should I care?\u003C\/h3\u003E\n\u003Cp\u003EDid you notice, how I didn\u2019t use the word \u201ccode\u201d anywhere in the above definition? That\u2019s because Git isn\u2019t about code or programming. Yes, it was created to help with development of the Linux Kernel, but it really doesn\u2019t care what kind of files it handles.\u003C\/p\u003E\n\u003Cp\u003EAre you a graphic designer, tired of keeping all those files like \u003Ccode\u003Eproject.psd\u003C\/code\u003E, \u003Ccode\u003Efinal.psd\u003C\/code\u003E, \u003Ccode\u003Efinal2.psd\u003C\/code\u003E, \u003Ccode\u003Efinal2-FINAL.psd\u003C\/code\u003E, because the client might change their opinion one more time and basically ask you to redo your first project once again? Then Git will help you!\u003C\/p\u003E\n\u003Cp\u003EAre you a writer, wanting to make a major change in your book, but afraid it will not work out fine, so you\u2019d like to be able to quickly revert that change? Yup, Git is for you!\u003C\/p\u003E\n\u003Cp\u003EAre you a person, who wants to track how their CV changed over time, without keeping all the versions as separate files? Just use Git!\u003C\/p\u003E\n\u003Cp\u003EDo you want to collaborate on \u003Cem\u003Esomething\u003C\/em\u003E with your friends, without sending email attachments back and forth or worrying if everyone has the newest version? Git might be exactly what you need!\u003C\/p\u003E\n\u003Ch3\u003EHow do I learn it?\u003C\/h3\u003E\n\u003Cp\u003EWell, not here, this is not a tutorial. The Internet \u003Ca href=\u0022https:\/\/www.google.nl\/search?q=git+tutorial\u0026oq=git+tutorial\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E already has plenty of those\u003C\/a\u003E. Pick some and spend some time with it \u2013 you won\u2019t regret it!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["designer","git","programming","version control","writer"],"hasMore":true,"image":"https:\/\/avris.it\/image\/photoshop-final_small.jpg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/photoshop-final_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/photoshop-final_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022134.70967741935\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI had to learn \u003Ca href=\u0022https:\/\/git-scm.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Git\u003C\/a\u003E as a programmer. If you want to easily collaborate on a codebase, you really need either Git or something similar. But as a non-programmer, you\u2019ve probably never even heard that name, have you? Then why would you ever need it?\u003C\/p\u003E\n\u003Cp\u003EWell, for exactly the same reasons!\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/photoshop-final_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/photoshop-final_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022134.70967741935\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/twitter.com\/PicturesFoIder\/status\/1011236244796342274\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Etwitter.com\/PicturesFoIder\/status\/1011236244796342274\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI had to learn \u003Ca href=\u0022https:\/\/git-scm.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Git\u003C\/a\u003E as a programmer. If you want to easily collaborate on a codebase, you really need either Git or something similar. But as a non-programmer, you\u2019ve probably never even heard that name, have you? Then why would you ever need it?\u003C\/p\u003E\n\u003Cp\u003EWell, for exactly the same reasons!\u003C\/p\u003E\n\u003Ch3\u003EWhat is Git?\u003C\/h3\u003E\n\u003Cp\u003EIt\u2019s a version control system, which means it remembers how the content of a directory (called \u201crepository\u201d) changed over time. You can decide, wich moments in time are saved \u2013 those snapshots of the repository are called \u201ccommits\u201d. You can send those commits to a server (it\u2019s called \u201cpushing\u201d), so that other people can download them (\u201dpull\u201d) and collaborate and your project (plus the server works as a backup of your data). If you ever want to revert your repository to how it looked like some time ago, or to see how it changed over time, or who wrote a particular line in a file, etc. etc., Git offers you all of that.\u003C\/p\u003E\n\u003Ch3\u003EWhy should I care?\u003C\/h3\u003E\n\u003Cp\u003EDid you notice, how I didn\u2019t use the word \u201ccode\u201d anywhere in the above definition? That\u2019s because Git isn\u2019t about code or programming. Yes, it was created to help with development of the Linux Kernel, but it really doesn\u2019t care what kind of files it handles.\u003C\/p\u003E\n\u003Cp\u003EAre you a graphic designer, tired of keeping all those files like \u003Ccode\u003Eproject.psd\u003C\/code\u003E, \u003Ccode\u003Efinal.psd\u003C\/code\u003E, \u003Ccode\u003Efinal2.psd\u003C\/code\u003E, \u003Ccode\u003Efinal2-FINAL.psd\u003C\/code\u003E, because the client might change their opinion one more time and basically ask you to redo your first project once again? Then Git will help you!\u003C\/p\u003E\n\u003Cp\u003EAre you a writer, wanting to make a major change in your book, but afraid it will not work out fine, so you\u2019d like to be able to quickly revert that change? Yup, Git is for you!\u003C\/p\u003E\n\u003Cp\u003EAre you a person, who wants to track how their CV changed over time, without keeping all the versions as separate files? Just use Git!\u003C\/p\u003E\n\u003Cp\u003EDo you want to collaborate on \u003Cem\u003Esomething\u003C\/em\u003E with your friends, without sending email attachments back and forth or worrying if everyone has the newest version? Git might be exactly what you need!\u003C\/p\u003E\n\u003Ch3\u003EHow do I learn it?\u003C\/h3\u003E\n\u003Cp\u003EWell, not here, this is not a tutorial. The Internet \u003Ca href=\u0022https:\/\/www.google.nl\/search?q=git+tutorial\u0026oq=git+tutorial\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E already has plenty of those\u003C\/a\u003E. Pick some and spend some time with it \u2013 you won\u2019t regret it!\u003C\/p\u003E","words":402,"readTime":2,"lang":"en"}}},"blog\/technology\/jak-odmienia\u0107-hashtagi":{"key":"blog\/technology\/jak-odmienia\u0107-hashtagi","type":"article","published":true,"meta":{"createdAt":"2018-06-14T21:57:31+02:00","publishedAt":"2018-06-14T21:55:00+02:00","group":null,"links":[{"icon":"brands twitter-square","colour":"primary","url":"https:\/\/twitter.com\/AvrisIT\/status\/1002220484098969601","displayUrl":"Przyk\u0142ad u\u017cycia"},{"icon":"globe-europe","colour":"secondary","url":"https:\/\/unicode-table.com\/en\/200B\/","displayUrl":"U+200B"}],"category":"blog","subcategory":"technology","slug":"jak-odmienia\u0107-hashtagi"},"content":{"pl":{"slug":"jak-odmienia\u0107-hashtagi","title":"Jak odmienia\u0107 #hashtagi","intro":"\u003Cp\u003EJakby kto\u015b mia\u0142 problem z deklinacj\u0105 \u003Cspan class=\u0022text-info\u0022\u003E#hashtag\u003C\/span\u003E\u200b\u00f3w i \u003Cspan class=\u0022text-info\u0022\u003E@mentions\u003C\/span\u003E\u200b\u00f3w,\nalbo tym, \u017ce Twitter traktuje skr\u00f3t \u201em.in.\u201d jako link,\npolecam wklejenie znaku \u201c\u003Ca href=\u0022https:\/\/unicode-table.com\/en\/200B\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Zero Width Space\u003C\/a\u003E\u201d \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cp\u003EJakby kto\u015b mia\u0142 problem z deklinacj\u0105 \u003Cspan class=\u0022text-info\u0022\u003E#hashtag\u003C\/span\u003E\u200b\u00f3w i \u003Cspan class=\u0022text-info\u0022\u003E@mentions\u003C\/span\u003E\u200b\u00f3w,\nalbo tym, \u017ce Twitter traktuje skr\u00f3t \u201em.in.\u201d jako link,\npolecam wklejenie znaku \u201c\u003Ca href=\u0022https:\/\/unicode-table.com\/en\/200B\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Zero Width Space\u003C\/a\u003E\u201d \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["facebook","hashtag","j\u0119zyk","odmiana","social media","twitter"],"hasMore":false,"image":null,"introLite":"\u003Cp\u003EJakby kto\u015b mia\u0142 problem z deklinacj\u0105 \u003Cspan class=\u0022text-info\u0022\u003E#hashtag\u003C\/span\u003E\u200b\u00f3w i \u003Cspan class=\u0022text-info\u0022\u003E@mentions\u003C\/span\u003E\u200b\u00f3w,\nalbo tym, \u017ce Twitter traktuje skr\u00f3t \u201em.in.\u201d jako link,\npolecam wklejenie znaku \u201c\u003Ca href=\u0022https:\/\/unicode-table.com\/en\/200B\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Zero Width Space\u003C\/a\u003E\u201d \ud83d\ude09\u003C\/p\u003E","contentLite":"\u003Cp\u003EJakby kto\u015b mia\u0142 problem z deklinacj\u0105 \u003Cspan class=\u0022text-info\u0022\u003E#hashtag\u003C\/span\u003E\u200b\u00f3w i \u003Cspan class=\u0022text-info\u0022\u003E@mentions\u003C\/span\u003E\u200b\u00f3w,\nalbo tym, \u017ce Twitter traktuje skr\u00f3t \u201em.in.\u201d jako link,\npolecam wklejenie znaku \u201c\u003Ca href=\u0022https:\/\/unicode-table.com\/en\/200B\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Zero Width Space\u003C\/a\u003E\u201d \ud83d\ude09\u003C\/p\u003E","words":28,"readTime":null,"lang":"pl"}}},"blog\/technology\/mysn-de-schenker-a-bittersweet-ending-of-a-horrible-customer-service":{"key":"blog\/technology\/mysn-de-schenker-a-bittersweet-ending-of-a-horrible-customer-service","type":"article","published":true,"meta":{"createdAt":"2018-04-07T11:54:39+02:00","publishedAt":"2018-04-07T11:51:00+02:00","group":"customer-rants","links":[{"icon":"pencil","colour":"info","url":"https:\/\/avris.it\/blog\/mysn-schenker-kurwa-ma%C4%87-en","displayUrl":"Part 1"}],"category":"blog","subcategory":"technology","slug":"mysn-de-schenker-a-bittersweet-ending-of-a-horrible-customer-service"},"content":{"en":{"slug":"mysn-de-schenker-a-bittersweet-ending-of-a-horrible-customer-service","title":"mySN.de \/ Schenker \u2013 a bittersweet ending of a horrible customer service","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-4_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022271.2\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFdElEQVRIiWWWzZLkSg2FP0mZ\/qnpnm6GuSx4AnY8BSuCd78rItiyAoKharq6qmxnKsUiXdUd4IgMh9N25NHRkY7kz3\/5U8zTTGuNYRiYxpEAaqkMw4CIYKZM08SyrLy+fMUs0ZqTkyEBLQIiuN5uQHBdVhCo1XEvqCpB4GXjuqy4N5blRnVHVbm8X1GFP\/7h96RanBgaABGBe6O1xvntndeXV56fnxmngWTGb3\/znWHIzPNMzgkBVBUzI6XE9bbgXrleb5zfz5xOJ0pRlmXh\/XJBJAjATDFLlFLx5gxDpnrlr3\/7Owng59uZeZoAoZQKwPHHD9bLldM4MKTEMGSGcWTIAzknUk6YGaYKQGuBe6XWyloK27axrhvbtrGVSqmFWio1nMPTAXfHzBjHzO22EhGspaGtNUSEWiu1Fg7zSLSGIKjKzgKIANGIcCIa0fpqrdG8790vBUTkg737SoaE0LwxTiMA7g0RBYSUMymiYZZ5en7CVDmd3liWtYMRwVQRkcdhEUFr7XH\/fEVAAOxgUrLHXkQAgrdAVRmHcQ+kyyQiKKWScs64B+e3MykZ7II2VUx1Z6cf8L\/A+gJBaRE0IFBEDbP+zgMsgsgBAi0S67LhrSEKzfe\/RLoUaq0QQphSiiMilG1jmKYHS5+X7prpkSshez5D0M5PBy5CiJLv76XvB1C9de0JjPNAa43qhW0tpPtHKso0j7g72ewBgE93RGj7t4gid3GponT2RAOJQKIhXgmpuwg7c4hS3EkpIRqs60YthdYaYkIKglp7PyilsK0brbXOxB3M\/WCRLtlPYH753Xeenl84PD2xLgs\/f574z\/FEtIa1hKReeapK0f7f4M66LbTmqCmWElEr0YLUvFGrI1KI1li3FVXt6w5oT4OIPd6JGWrG91++8\/T1hafnF56fn\/n1118ZLksXa3PUnZQq1RKWE2UrtNjPMaO5oyqoKbVWkteKaG9W67axritzHvc09YjuYESlP6shaqRh4MfxxNtlYTq+8fXllXUrDNO0C77h7nit1JTRsqFqBMFyW9jqgiUjwruOaiNZNqaUcW\/kbHgxVO1TVSmqdzCGWUKSYSkhalyuG7kEy1p4O19AhGmaP7UIp9aKeyVtmc0Sqr173443tm3F3VGT3quWZeXWlu43EYQ3ZPjoLSI8tKQqiH1YRUqZnDMpD6ScexCqqBm6p9pr7dGXre+bgcB8OHA+v9GaIyqs6wbUXvYqPX8Awv+XuajCniq1zo7tYPIwMgwdkKVuJ3ed9U7suDu1ZCxlLC2ICtu2MR8O3G5XgiBnY1srqZRCSolo\/ed5nD\/KXXtLEJE9ciWlRM6ZYRgYp4lxmhiGgTx2YDlnUkqPlHdt1N3bVpZlJOUMEZzPb5xOR2rZSMmo5qScjIgg54RZHzXU9CFg9mWWOuXJyHlknCameWKeD0zzzDTPzIdDf57GfXTpQZatcL1euVwuXK9XrteJnDO35cr5\/Ma\/\/vkP1m3rdtMi8Np2fxIOU8JSAruzpB8meWdmHBmnkXk+8PT0hS9PTzx\/feH19ZVv377x9eUrYx6otXK5Xjkej6zryu22cDweOZ1OvL+f+fn2zrJ2G9n2TCV3fxjitqys48JWVkAgPkxRtIs0pbSLvTMJsC4rpVbcG6X2gex2Wx5VpqY0d3LO+1QguDvDODCNvYJUBK+VpHd\/KY43598\/flCrY5aAbqDTND0mx7QPZrU6IERASoaZMoyGt4JK8OUwUd2J1kg54bWLu4UwTiPbVmjurOv2qOBSKmldN8zs7uG7MINt2xjHkVqdeR653dY+4e2DFcguLyWiUUrDWsOrI6k3PwE0WZ8eku0tpAeakhKhuDe8VdZl4\/J+4b+3JV+iZKIhxgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-4_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022271.2\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe story I described \u003Ca href=\u0022\/blog\/mysn-schenker-kurwa-ma%C4%87-de\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E in here\u003C\/a\u003E finally has a bittersweet ending \u2013 I finally got my computer back! After over two months, after lots of stress and fighting, and after having paid them 130\u20ac (only 25% of what they first requested, but still 100% more than I should have paid)...\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-4_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022542.4\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFdElEQVRIiWWWzZLkSg2FP0mZ\/qnpnm6GuSx4AnY8BSuCd78rItiyAoKharq6qmxnKsUiXdUd4IgMh9N25NHRkY7kz3\/5U8zTTGuNYRiYxpEAaqkMw4CIYKZM08SyrLy+fMUs0ZqTkyEBLQIiuN5uQHBdVhCo1XEvqCpB4GXjuqy4N5blRnVHVbm8X1GFP\/7h96RanBgaABGBe6O1xvntndeXV56fnxmngWTGb3\/znWHIzPNMzgkBVBUzI6XE9bbgXrleb5zfz5xOJ0pRlmXh\/XJBJAjATDFLlFLx5gxDpnrlr3\/7Owng59uZeZoAoZQKwPHHD9bLldM4MKTEMGSGcWTIAzknUk6YGaYKQGuBe6XWyloK27axrhvbtrGVSqmFWio1nMPTAXfHzBjHzO22EhGspaGtNUSEWiu1Fg7zSLSGIKjKzgKIANGIcCIa0fpqrdG8790vBUTkg737SoaE0LwxTiMA7g0RBYSUMymiYZZ5en7CVDmd3liWtYMRwVQRkcdhEUFr7XH\/fEVAAOxgUrLHXkQAgrdAVRmHcQ+kyyQiKKWScs64B+e3MykZ7II2VUx1Z6cf8L\/A+gJBaRE0IFBEDbP+zgMsgsgBAi0S67LhrSEKzfe\/RLoUaq0QQphSiiMilG1jmKYHS5+X7prpkSshez5D0M5PBy5CiJLv76XvB1C9de0JjPNAa43qhW0tpPtHKso0j7g72ewBgE93RGj7t4gid3GponT2RAOJQKIhXgmpuwg7c4hS3EkpIRqs60YthdYaYkIKglp7PyilsK0brbXOxB3M\/WCRLtlPYH753Xeenl84PD2xLgs\/f574z\/FEtIa1hKReeapK0f7f4M66LbTmqCmWElEr0YLUvFGrI1KI1li3FVXt6w5oT4OIPd6JGWrG91++8\/T1hafnF56fn\/n1118ZLksXa3PUnZQq1RKWE2UrtNjPMaO5oyqoKbVWkteKaG9W67axritzHvc09YjuYESlP6shaqRh4MfxxNtlYTq+8fXllXUrDNO0C77h7nit1JTRsqFqBMFyW9jqgiUjwruOaiNZNqaUcW\/kbHgxVO1TVSmqdzCGWUKSYSkhalyuG7kEy1p4O19AhGmaP7UIp9aKeyVtmc0Sqr173443tm3F3VGT3quWZeXWlu43EYQ3ZPjoLSI8tKQqiH1YRUqZnDMpD6ScexCqqBm6p9pr7dGXre+bgcB8OHA+v9GaIyqs6wbUXvYqPX8Awv+XuajCniq1zo7tYPIwMgwdkKVuJ3ed9U7suDu1ZCxlLC2ICtu2MR8O3G5XgiBnY1srqZRCSolo\/ed5nD\/KXXtLEJE9ciWlRM6ZYRgYp4lxmhiGgTx2YDlnUkqPlHdt1N3bVpZlJOUMEZzPb5xOR2rZSMmo5qScjIgg54RZHzXU9CFg9mWWOuXJyHlknCameWKeD0zzzDTPzIdDf57GfXTpQZatcL1euVwuXK9XrteJnDO35cr5\/Ma\/\/vkP1m3rdtMi8Np2fxIOU8JSAruzpB8meWdmHBmnkXk+8PT0hS9PTzx\/feH19ZVv377x9eUrYx6otXK5Xjkej6zryu22cDweOZ1OvL+f+fn2zrJ2G9n2TCV3fxjitqys48JWVkAgPkxRtIs0pbSLvTMJsC4rpVbcG6X2gex2Wx5VpqY0d3LO+1QguDvDODCNvYJUBK+VpHd\/KY43598\/flCrY5aAbqDTND0mx7QPZrU6IERASoaZMoyGt4JK8OUwUd2J1kg54bWLu4UwTiPbVmjurOv2qOBSKmldN8zs7uG7MINt2xjHkVqdeR653dY+4e2DFcguLyWiUUrDWsOrI6k3PwE0WZ8eku0tpAeakhKhuDe8VdZl4\/J+4b+3JV+iZKIhxgAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-4_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022542.4\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe story I described \u003Ca href=\u0022\/blog\/mysn-schenker-kurwa-ma%C4%87-de\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E in here\u003C\/a\u003E finally has a bittersweet ending \u2013 I finally got my computer back! After over two months, after lots of stress and fighting, and after having paid them 130\u20ac (only 25% of what they first requested, but still 100% more than I should have paid)...\u003C\/p\u003E\n\u003Cp\u003EYup, I filed the complaint on February the 4th, and got the computer back on April the 6th \u2013 and in the meanwhile they where late for every single deadline they had set for themselves. Every email I got sounded like they knew they\u2019re wrong, but they are desperately trying to save their faces and their money.\u003C\/p\u003E\n\u003Cp\u003EThey were obviously quite worried about me telling my story online and posting it all over the social media (and rightly so, they are a small company, and my husband has a \u201cLocal Guide\u201d status on Google Maps, so his review single-handedly lowered their score by half a star!).\u003C\/p\u003E\n\u003Cp\u003ESo I guess it\u2019s only fair to present on the same blog the rest of the story, how they handled the situation and how they found a \u201ccommon solution\u201d. Here we go:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-5_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022495.95907928389\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADE0lEQVRIibWWYW7bRhCFv5nZpUSKttFaBnqI\/u2xe4CeohfozyIJHMBtZUQWpd2Z\/liSieukRVBnAEJckVy+mffmDeX+\/R9Rf\/uV8cefOBwOmCXcKwCqCsAwDJgZfd\/z2hHhHI9P5Jxxd\/T05wO\/\/\/IzEY67czmfAaGUwjRNjOPIMAxsNhtE5BscSt\/3pJTa+v7hMe6+GzmdThwOB4hAVKnumCr7\/R4AESEiXvV8WbdKBdM0kZaFipC7Dp2RuzsiwuFwQESotXJzc\/Niw\/9z\/rl1WlCKKNvNhlIKOWdKKZgZAB6BmeHuQNPWstHyu+gtIp4lJEA8q4ygIiwwVOUlIICn45l3bx6Yn2E3JrZDE5pZAoLjhw90mw2Xy4WIIKJt6N70l3NuFESACLVUgiAisJQwMfDN+vJua+zG7lliK2V5I9z+sKOWQkTg7oQHOWem0wlRRUQ5nU6klOZKQK0VM8PUKJdCzLm3RKyBMcNLwamILskE02NwfDLGcWS73baKLZRFwOV8xswQkbn9vb1w7oBaG421ViKCcimoGl4r0\/mMmq4AUsqklFA1SimknCm1tNZeqQy+v72l7\/tV3CtltVbK5UKZK9SqFHOWjoiSc+Lx8RFVXY8loZQMIlA1anUac4KpAE1\/NmsvADWjuvP+\/p67u7t1r5WylBLX1zcggmoT4Pl8nrNU3J2u69jtdtRaAWEcd6vwXyvWLjsej7x98xYE9vs9qoqZMU0TtVY2XcdfT0+kZISDh1PrJ3pbOzFQofmYNV2lZPh8X0ppFfEwDOx2u5eAAPq+Z3+3R+Zyxqyf6+vr1aW\/hTEu8aLLUkoMw7A+0ITdBFlKWX1l8aBwn+lVaq0fHReaYCMopSAi5Jyf+dY4XjHf\/mVjBNZ5spji8v9ybQG3gF2ut8HYbGCZURHNMgBUlOp17WYIRPTLGgIId47H4zpGQHCvrRtqnUFlIAgPzlyAoOs6rq6uvpqyT9efpUy0TV13X2n5p+D+K151lhHRvKgUxnGk67qvAvNasVKmZpjZR9HOwn7tzvq3zw+AvwGhEVMYJV0frAAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-5_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022495.95907928389\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIs it just me, or does it sound really insolent and passive-aggressive? Anyways, here\u2019s my response:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-6_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022296.19611158073\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAALCAYAAAAX+i97AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACV0lEQVQ4jbWUUVIcOQyGP8l2N9PDABuWYh6oPUbukXvkPjlHjpGTUMUOFbaWBQZb0j64exISqpIX\/GS71dLvX\/8vubn9J\/Z+w+XpXzw97QEQEUSUlBQRoZSCiPAWy92ptZJL4Xm\/J5sHn7984sP7j9ztnhBARIlwzs\/PWR8fU0p5EzAAqto3EZ2I67\/vYvvnKdaM+\/t\/EVXcHREhIgBIKR1eExFEBKqdPVWltUZKCXMHdzQlRARrDY8gqRIszAvugYoQBAIcn5ygIjw+PpIXpObG17s7ckpEQLNGzhkQiOD5ec\/RatXpzRl3pzUj50StlXE8wt0g4lDczCilkFLGrGFm\/TEipJwxM3IubE5ODowdAIkIm81mLtQYxqGzZdZ1NBRKKQzD0PUUQTOfATVSUlRHVqsV6\/WamFvQu\/H6\/vvz0o28XFozrq+vaa0xjiNmBgGiwn6\/Z5omrBkeTkoJN6e2xlAyZ3+8Q6Tr4eHhgf\/u7zFzNCkR0ePd0dkstdXe8rn25Xb7M0NlKFxdXaGzhhagadbDop1FP2bWv9G10M8ZESAgiDlX4G4v8g7j0AGqMo5HB3ZeAHIzdre3jMMSnGi1IiqzEwQRaLUdXu7uDMtIEKXWZ5ImmjVUtQNvRmuN9XrCZosvJrHWGIaRy+2WlPQbIBFBVJlWE9N64uz09Hcc+ybroCEiyLmzstvtuoXDiYCcu0siIKdMs4pIQlUOo2ARaimFWmufK6qklAgPmMeAuTHMXVjWxcXFS0BLsiXI3dlsNkzT9Eun\/Lhf8v3ontdivv9\/uf8fr1p9E4KA2YIAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-6_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022296.19611158073\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAnd their response:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-7_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022373.0612244898\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAANCAYAAADBo8xmAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACFUlEQVQ4jbWTyW4bQQxEH9mLtY0seIn\/JPd8e465JV+hxJaAGDAkTTeZwyweWz4kiF0nNgc9VV0syvbnzk\/fv7L5\/IXdfk8MEccpbSGmCEDTNKgqy+WS94aZ8fT0RM4ZM0PL8cDuxzcUZzabEUJgdjFjuVwQY+T6+pqmaT5EDICqslqtyDkjIsj24bd\/umo4HA48Pj7i7qgGzGpfK7e3tx8i5jUOhwMRwN3HZghhPMcYqbVy\/+seDYqZUUohpYSZISKYO26GqpJzZr1e\/5eoOBQiwiDOzAghUEtBgxJCoJSCiBBCGIXFEFBVNCXatuV0PLHdbsccmjsClFLJOaGqlFJQERxQUdyNq5sbtOcfBZ1OR\/b7PSC4GY6PTpS2dKJVSClxub7sxANW6+iqYaQYccDNu28aiDEgIrRti7vjPTkKgmC1ojE+CxIRLi5m3N3djW6JCLUnG5wbeikllrocxyYixBhR1dFpAazPoIhgZi9GM\/RSSiNHr\/EZQfsRaDcm7c9h0kspda+cCHR3tCcQEUqptKUATq0V1W7kA2xyfxqXswwdj0c0KJvN5ixsIvIi\/NPMTX8IMJ+fXSfndN58A+OW1VpxnLYtPDzsEOnygQi444CIAg4OGhT3jqhpmr8i+2tBw\/bM5\/Pxxe7OarV6N6J\/EjSMotZKrZXFYkHO+cWIPhryeu0Hl4YVHlx6KyvvVQ\/nKf4AOggu7y+9CjIAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-7_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022373.0612244898\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ENote, how they completely ignored my request for Gew\u00e4hrleistung. So I asked again:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-8_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022163.52542372881\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAGCAYAAACrZDylAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA4ElEQVQokbWSTWrDMBCFvxkJHFCIwYsse5KepFfpGXqS3qNnKU1\/IDh17Gg0WaRW6SoNJG8jMTyJj\/dGNp9bn8qGdXvHNE0AiAgigqoCEGNERLiFSimYGSEExnEk7g8jzy9PPNw\/8vH2BQ6OEILSdR0pJWKMFRTA3f99d\/ezb80MVT0F8fq+9XW3xMzo+\/5kFoGfj9q2vRjiUqD5HIaBOEcnIjRN88cUQsDd6yznXOt091rpNVWBSinsdt+U8hsfgGVDdN4nJ2dDREgpkVK6LVDOB1QVM2O1alksmrPVXFtHfeeRXJU4AVsAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-8_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022163.52542372881\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ENo response for whopping eight days. And then just:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-9_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022296.19611158073\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAALCAYAAAAX+i97AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABhklEQVQ4jb2UTW4UMRCFvyq7u0ejkZJFI0FYsCLibJwBcQbuxhkQIgNS0owyqP1TLLrteAILiEapjatdtvvVe8+Wmx93Nkzf2L5+Q4gJABGpYwiBYRgAcM7V2rnCciamhHOOeZ7xKRufP33g3fuPfPmVcM5jljEzzIyLy0tejCOI4L0\/KxgARIgxPpDwdX9rL8cLUkocDgdUFTOro5khIogIu93u\/ICaOB6PnLRcGIgxoLrkaaXTzADIOa+NnUr3VClLwxVDW5imCVUHGPf3R8yMvu9XMMI8z4QQyTkhIuS8SDuOY11XDv+X\/DGwCsjMiDHyfb8HEZwqOWd814FBiKH+2KninFvq3iPANP3ELBNDRJ1b9ltG13NSSpV9yxlbGRVZmnx1dUWBWBnq+56319cnnikeKp7CwFg6UdUqVdd1T5Lrb\/HHtWnBtDmAOEXWvDB77mfAFxBFtvZ7u91WJp4rqodaQMMwsNlsKLVnByQiqOqD8RoQ\/3NrqrSN5O3c4zXt\/jL\/G65D+gPcn4HRAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-9_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022296.19611158073\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-10_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022158.78481012658\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAFCAYAAAAt8E4LAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA\/klEQVQokbWQwUoDQRBEX\/cMk2SySVBBD579\/x\/xBzx5EiFBMAiLyWx3e0iyrDcR0pfqOnTzqmT7sY\/99yuPt0\/sP79QFSIC1UStC9ydWiuqyjUmIuj7ntlsRmuNbB68vD1zs7xHRHF3UkqEO8MwsFqtrgYDICLUWgForSHvu894uFtjZuy2W9pg5JxQVVprlFIwsxHqeDxSSiGlhA12TumYOyCUklFNp1ARv5oQkVEFwcLYrDfknBER+r4nXygBNCXmORPuiCY2m4qboekEGMAyAjnDudnpNgLOP0SUrlv+u7E8icDhcBjhFvNM13Wjv6Sb7lOdtvDX\/eKnpfwAlVOEWj0PQ0gAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-10_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022158.78481012658\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-11_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022273.93939393939\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAKCAYAAADcpvzeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABaklEQVQ4jb2UQW4UMRBFn8vVbgmjhojFkCyz4kgcgWtxAk7ECikBgUZRayatadtVLEyPgC3D\/JUty67n\/+0K3348uX79zMv7d8zHZ0QEdwdARGitkXOGEBhTIoTAJWVmnE4nhmFgXVe0OXz59JH79x+YJREQCAHcMTemaUJVAQghXBxIRBiGARHp5z98f\/K3bybMjP1+jwNuhqpizSBALZU0jtSyIjHi3plLqcQo5Jy7i\/+oZVnQbdJaY55nWmvEGBEJqCbKuiKxxyhRunNmqA64O1GVZVk4HA4EAhIFM8fdSClhZr2AO0GEUsovZyLTq4kxpT+gFHoUqsput0OkFyUERIRaKwApJdJvm9394vGdgbpDlceHR0QCEhXcqa2iOlBrIYrw+uYGHRQcYlRyfvH\/gGJUbu9uezQimBk55+7YFaXA+Zv3MYzjSIyRv9euofP13Z1SCu7G8Xi8Osim86Pe+sHWa64d1aaf81SiNqrIaxQAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-11_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022273.93939393939\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFinally, after 3,5 weeks (2 was promissed), they presented me an offer:\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-12_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022237.76838546069\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAICAYAAACRbl3VAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABwUlEQVQ4ja2TTW8TQQyGH3s+tk2zm5UaCXrhhMSN380f4K9w50IjhQQRiWazM57hsOmqoSB6qKWRPJLH8+j1a9nuD5WvX1h++MivhwfmqCAqlFJYLBaUUlBVYow453itMDNOpxMxRsZxxOeU+Pb5E+\/v3vEw5jOIUmullkK36ogxUkpBRGYYEaHWOufAxb3W+t8aAOccTdMgItPZfP9Z39x2jOPI4XCYH8UQ6VbdRaM\/89cAelp3PB7xj9KllNjtdoynkWW7ZBgGNpt7rBRCCKSU8d5hOSOq9H0PgJ7VDCFgZqgqqkrOmVorORt3d29fPMIZqImR9XpNTgnnPG3boiKYGYjMHxYzagUEYoyklHBPAERkzq+urmjb9sUwF0A5Z7bbLWcdub6+ZnFzAyKklM+ygg+BlNLlOFTRc49ihvNT2+PxyDAMOOfwzjOcBrz3s9q1wnp9+3cgdY6+74khgCgpjagqZkYIHmFSJedM8J5S66yOZQOZxicIzntWXffMQytW\/\/TUMyBqxXuPlYIqeO\/nVTczxLlpCxBSnhSb\/APqppGF4DErpHHkx37PMAyEGGeAR78JQqmFpmlYLpcXQL8BXdcRuJzrGN8AAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-12_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022237.76838546069\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ESo, let me get this straight: they claim it\u2019s all absolutelly, totally my fault, and that\u2019s why they will do everything they possibly can to make me pay as little as possible (yet not nothing)? Yeah, right, it makes so much sense...\u003C\/p\u003E\n\u003Cp\u003EThey made the Vorlieferant replace the motherboard for half the price, they covered a half of the rest themselves and also the delivery costs \u2013 all because I \u201cmechanically\u201d broke my laptop and they are not responsible at all. Ha. Ha. Ha.\u003C\/p\u003E\n\u003Cp\u003EBut anyways, I obviously had enough at that point. The stress of losing your computer when you\u2019re a software developer, and also of being charged 520\u20ac for the crappiness of their product, especially now of all times when I also got a back payment for rent, some medical bills and was preparing a wedding \u2013 the stress was just too huge. That\u2019s why 130\u20ac was an amount that I was willing to pay for the fix, even though I still didn\u2019t agree with their version.\u003C\/p\u003E\n\u003Cp\u003ESo there we were \u2013 the transfer was made right away, received the next day, and they promissed to process everything within two weeks.\u003C\/p\u003E\n\u003Cp\u003EIt took them three (March 15th \u2013 April 5th). Late again.\u003C\/p\u003E\n\u003Cp\u003EBut the next day my computer was back home. I\u2019m like after a really bad dream \u2013 not happy, just glad it\u2019s finally over.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["computer","customer service","guarantee","insolent","schenker","schenker technologies","service"],"hasMore":true,"image":"https:\/\/avris.it\/image\/mysn-4_small.jpg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-4_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-4_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135.6\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe story I described \u003Ca href=\u0022\/blog\/mysn-schenker-kurwa-ma%C4%87-de.lite\u0022\u003E in here\u003C\/a\u003E finally has a bittersweet ending \u2013 I finally got my computer back! After over two months, after lots of stress and fighting, and after having paid them 130\u20ac (only 25% of what they first requested, but still 100% more than I should have paid)...\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-4_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-4_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135.6\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EThe story I described \u003Ca href=\u0022\/blog\/mysn-schenker-kurwa-ma%C4%87-de.lite\u0022\u003E in here\u003C\/a\u003E finally has a bittersweet ending \u2013 I finally got my computer back! After over two months, after lots of stress and fighting, and after having paid them 130\u20ac (only 25% of what they first requested, but still 100% more than I should have paid)...\u003C\/p\u003E\n\u003Cp\u003EYup, I filed the complaint on February the 4th, and got the computer back on April the 6th \u2013 and in the meanwhile they where late for every single deadline they had set for themselves. Every email I got sounded like they knew they\u2019re wrong, but they are desperately trying to save their faces and their money.\u003C\/p\u003E\n\u003Cp\u003EThey were obviously quite worried about me telling my story online and posting it all over the social media (and rightly so, they are a small company, and my husband has a \u201cLocal Guide\u201d status on Google Maps, so his review single-handedly lowered their score by half a star!).\u003C\/p\u003E\n\u003Cp\u003ESo I guess it\u2019s only fair to present on the same blog the rest of the story, how they handled the situation and how they found a \u201ccommon solution\u201d. Here we go:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-5_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-5_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022123.98976982097\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EIs it just me, or does it sound really insolent and passive-aggressive? Anyways, here\u2019s my response:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-6_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-6_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002274.049027895182\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EAnd their response:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-7_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-7_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002293.265306122449\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ENote, how they completely ignored my request for Gew\u00e4hrleistung. So I asked again:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-8_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-8_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002240.881355932203\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ENo response for whopping eight days. And then just:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-9_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-9_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002274.049027895182\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-10_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-10_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002239.696202531646\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-11_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-11_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002268.484848484848\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFinally, after 3,5 weeks (2 was promissed), they presented me an offer:\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-12_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-12_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002259.442096365173\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ESo, let me get this straight: they claim it\u2019s all absolutelly, totally my fault, and that\u2019s why they will do everything they possibly can to make me pay as little as possible (yet not nothing)? Yeah, right, it makes so much sense...\u003C\/p\u003E\n\u003Cp\u003EThey made the Vorlieferant replace the motherboard for half the price, they covered a half of the rest themselves and also the delivery costs \u2013 all because I \u201cmechanically\u201d broke my laptop and they are not responsible at all. Ha. Ha. Ha.\u003C\/p\u003E\n\u003Cp\u003EBut anyways, I obviously had enough at that point. The stress of losing your computer when you\u2019re a software developer, and also of being charged 520\u20ac for the crappiness of their product, especially now of all times when I also got a back payment for rent, some medical bills and was preparing a wedding \u2013 the stress was just too huge. That\u2019s why 130\u20ac was an amount that I was willing to pay for the fix, even though I still didn\u2019t agree with their version.\u003C\/p\u003E\n\u003Cp\u003ESo there we were \u2013 the transfer was made right away, received the next day, and they promissed to process everything within two weeks.\u003C\/p\u003E\n\u003Cp\u003EIt took them three (March 15th \u2013 April 5th). Late again.\u003C\/p\u003E\n\u003Cp\u003EBut the next day my computer was back home. I\u2019m like after a really bad dream \u2013 not happy, just glad it\u2019s finally over.\u003C\/p\u003E","words":466,"readTime":2,"lang":"en"}}},"blog\/technology\/mysn-schenker-kurwa-ma\u0107-de":{"key":"blog\/technology\/mysn-schenker-kurwa-ma\u0107-de","type":"article","published":true,"meta":{"createdAt":"2018-02-17T12:28:46+01:00","publishedAt":"2018-02-17T12:14:00+01:00","group":"customer-rants","links":[{"icon":"pencil","colour":"info","url":"https:\/\/avris.it\/blog\/mysn-de-schenker-a-bittersweet-ending-of-a-horrible-customer-service","displayUrl":"A bittersweet ending of this story"}],"category":"blog","subcategory":"technology","slug":"mysn-schenker-kurwa-ma\u0107-de"},"content":{"de":{"slug":"mysn-schenker-kurwa-ma\u0107-de","title":"mySN.de \/ Schenker \u2013 schlechte Erfahrung, nicht zu empf\u00e4hlen \ud83d\ude20","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGVUlEQVRIiXWWzW4cxxWFv1tV3TM9v\/zRiMMhKUqWJUWwjQBO7G1WQZBXMPJOAbLIQxjIM9hGNpEDW14IdgxDsiOJpCSKIjn\/0911bxbdpKggKaDRjUZX1ek6955zZDhYs7wsmc2WFDHiEBADBFUwM5xzOOcQES6GiIAAIgj1vb6gmocJIIgzRARTAzMQCImjkSY0mw1azYxOu02SOMJ8uWI2X6FaTVIMUwC73NzMLjeKqjhxGIb3vgbhcCKIc2DVTBHBe0+\/3+fa5jXW19dYW1uj1WrR7\/bodlpkzZTx+JzpfMZ8PmM8HiNOxC4WqPY0VHlnhBBQ1eqvEZwPmBlZltHv9xlcGzAajRgOtxluDxltj9jZGTEYXCPPc+bzBYdHRxy\/PubVq2OOXrzg8OiI1yevmc\/nlEXJqliiURERsUsKMJwTwF3SkiQpvV6fzc1Nrl\/fYnd3j\/39G9x+7zY3b92k027TamWUsWQ8nvD65ISDwxc8ffaMg4NDjo9fc\/LmDdPZDDNlsViwWq4oY47GSFkWODGcOLwDcc4ZQLvdotvtsrmxwWBzwHA4Yms4Yn1jHec9UY2yLCljpIyR8\/Mx4\/GEPM85PTtnNpuhaqgpZVmQr5bEGAnB452QhEC322F9rU+\/36PbbpEkAbPIdDJmNp9TrFYVoMFgg1\/dvYdLGkQ1ohrT6Zw3Z+fkeYGZXRZ38AERRwierNmk02nRabfYHm6xd2OPne1ttra26PW6qCrT6YTJZEqel4wnY05P33B6dsp0cs5kMub4+ARDEYGiqAGJ87iQ4rxHpKLLiSNJAmmSkDWbXL9+nRt7N3j\/9m1u3drn2uYmahFVI01TDDg\/O+Pw4DnLxZytrQGmJY9\/ecrZ+TnD7R2SRsZiuSQNwmKxZDw+49tvvyFrpCxqGsU5Z1mrRRkjgrB\/Y4+7799lNBqxtTVkNNplZ3eXjY0NHj95zMOHDzFTyrJkd3eXm\/t7rK+tAfDgwT8YDK5x\/\/49xuMJq6IEcWTtFj\/+8D0vXr1hMV8wm004Oz3h+PUJz589Iy9yiiJntcoJAPlqRdbKuH\/3Dp9+8inD7R1++PFffP3Pr2l3vuezz\/7Ew+++4eHD79jZ3WEynXH+5pijBz+TJr\/DVAne0+l22Lt5i3Z3jSgBt5iTBMfPTx7z+ed\/4+nzI\/LlAtVIjBEzRa2iS8xQjFB1kue9vR3u3b2LCSSNFLOCaCVHRwd88eUXPHr0iG63w6vjY\/prfX79wR0+\/OA+Pz35N3\/+y195dnBIcJ7R9oCPPrzPy5cvOT0bc3p2xmQyYTqdIWK1pinOWdXmKBrryxTx3puI0Ov3yLIWWdZCVVmt8loUoSwjZVlWOiTw209+wx\/\/8HtmkzE\/Pf6FVrvNV1\/9nYPDQ5wITgQzJWqJqaKqqEY0VicTo14R3ivKXkmNmPeekAQajWal7OIuO+viY9W3z0masLe3R75cMZ1OSRsphwcHNQ1vFR7RSrWvvAIQJ4QQaDRSWlmTdjtjfa1Lt9O6AFQBCGmK9x7TypNifMv1W4C1H1VGxv8bzjuazbTSt06H9fU+\/X6fXq9Dp5WRZU2Cd6hFRAzvBNUS8d6ZiNTWAM45zMDqja\/62NXn\/w3IaGYZH3\/8EaPRkH6vV\/kbELyj0WiQpgGzqnaS4NEYq72JlEVOuGLgmBkxxndc\/SoQEbnC9X9hESHLmuzv73Dnzm289zQaTdJGQvCeJDgQKMuS4F1lFd5RFgXOC8tlgXdStb2I4J0DFFV7pw6ugoDKaEPwhHAhoobUiydpYK3fw4nQSFIajYSLLk4SR1mUZM0GGiMhOJyDJGmhGvHOUI2Ei7pwUh1rFL10e1cXn\/dyqeDe+0ugaRowrWKP91XeSRspIQScBxEjSQKNRsA7R\/CeNE0wVWIsq84zxQmoRqbT6cUJcRm0vPckQXA1CBGH84JGw3t3WTcXgStJAtGq1hYR0iQlCZ40TXGuOsGLhvBOKIvKG4uiQJwRiwKzWJuzVsJY1QggDlTBOcRV+cjM0FgVu6rW6VEwoKw7MEkS1CBGxVQRR0VH8LX7l6gIyxirIFevW+YFsSyIsaAsSoqyqCi7yEJmVndFHT\/rwIYYevFdnV2iKVABU1WCdxREFssFsSwxS+ucI6CKVSgwrJaUoqasoirPc1SV\/wDhNHm2gKzJHQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-0_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMeinen Rechner hab ich von \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/mysn.de\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E mySN.de \/ Schenker Technologies\u003C\/a\u003E\u003C\/strong\u003E gekauft. Es scheinte eine gute Idee zu sein. Was es aber gar nicht. Ich f\u00fchle micht von mySN betrogen und we M\u00fcll behandelt. Ihre Kundenservice ist voll \u003Cstrong\u003Eunprofessionel\u003C\/strong\u003E, ihre \u003Cstrong\u003EHardware ist Schei\u00dfe\u003C\/strong\u003E und sie scheinen sogar nicht zu wissen, was sie im Lager haben und wie viel ihre Teile kosten. Im Ernsts!\u003C\/p\u003E\n\u003Cp\u003EDas ist mein (verk\u00fcrztes) Geschichte:\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGVUlEQVRIiXWWzW4cxxWFv1tV3TM9v\/zRiMMhKUqWJUWwjQBO7G1WQZBXMPJOAbLIQxjIM9hGNpEDW14IdgxDsiOJpCSKIjn\/0911bxbdpKggKaDRjUZX1ek6955zZDhYs7wsmc2WFDHiEBADBFUwM5xzOOcQES6GiIAAIgj1vb6gmocJIIgzRARTAzMQCImjkSY0mw1azYxOu02SOMJ8uWI2X6FaTVIMUwC73NzMLjeKqjhxGIb3vgbhcCKIc2DVTBHBe0+\/3+fa5jXW19dYW1uj1WrR7\/bodlpkzZTx+JzpfMZ8PmM8HiNOxC4WqPY0VHlnhBBQ1eqvEZwPmBlZltHv9xlcGzAajRgOtxluDxltj9jZGTEYXCPPc+bzBYdHRxy\/PubVq2OOXrzg8OiI1yevmc\/nlEXJqliiURERsUsKMJwTwF3SkiQpvV6fzc1Nrl\/fYnd3j\/39G9x+7zY3b92k027TamWUsWQ8nvD65ISDwxc8ffaMg4NDjo9fc\/LmDdPZDDNlsViwWq4oY47GSFkWODGcOLwDcc4ZQLvdotvtsrmxwWBzwHA4Yms4Yn1jHec9UY2yLCljpIyR8\/Mx4\/GEPM85PTtnNpuhaqgpZVmQr5bEGAnB452QhEC322F9rU+\/36PbbpEkAbPIdDJmNp9TrFYVoMFgg1\/dvYdLGkQ1ohrT6Zw3Z+fkeYGZXRZ38AERRwierNmk02nRabfYHm6xd2OPne1ttra26PW6qCrT6YTJZEqel4wnY05P33B6dsp0cs5kMub4+ARDEYGiqAGJ87iQ4rxHpKLLiSNJAmmSkDWbXL9+nRt7N3j\/9m1u3drn2uYmahFVI01TDDg\/O+Pw4DnLxZytrQGmJY9\/ecrZ+TnD7R2SRsZiuSQNwmKxZDw+49tvvyFrpCxqGsU5Z1mrRRkjgrB\/Y4+7799lNBqxtTVkNNplZ3eXjY0NHj95zMOHDzFTyrJkd3eXm\/t7rK+tAfDgwT8YDK5x\/\/49xuMJq6IEcWTtFj\/+8D0vXr1hMV8wm004Oz3h+PUJz589Iy9yiiJntcoJAPlqRdbKuH\/3Dp9+8inD7R1++PFffP3Pr2l3vuezz\/7Ew+++4eHD79jZ3WEynXH+5pijBz+TJr\/DVAne0+l22Lt5i3Z3jSgBt5iTBMfPTx7z+ed\/4+nzI\/LlAtVIjBEzRa2iS8xQjFB1kue9vR3u3b2LCSSNFLOCaCVHRwd88eUXPHr0iG63w6vjY\/prfX79wR0+\/OA+Pz35N3\/+y195dnBIcJ7R9oCPPrzPy5cvOT0bc3p2xmQyYTqdIWK1pinOWdXmKBrryxTx3puI0Ov3yLIWWdZCVVmt8loUoSwjZVlWOiTw209+wx\/\/8HtmkzE\/Pf6FVrvNV1\/9nYPDQ5wITgQzJWqJqaKqqEY0VicTo14R3ivKXkmNmPeekAQajWal7OIuO+viY9W3z0masLe3R75cMZ1OSRsphwcHNQ1vFR7RSrWvvAIQJ4QQaDRSWlmTdjtjfa1Lt9O6AFQBCGmK9x7TypNifMv1W4C1H1VGxv8bzjuazbTSt06H9fU+\/X6fXq9Dp5WRZU2Cd6hFRAzvBNUS8d6ZiNTWAM45zMDqja\/62NXn\/w3IaGYZH3\/8EaPRkH6vV\/kbELyj0WiQpgGzqnaS4NEYq72JlEVOuGLgmBkxxndc\/SoQEbnC9X9hESHLmuzv73Dnzm289zQaTdJGQvCeJDgQKMuS4F1lFd5RFgXOC8tlgXdStb2I4J0DFFV7pw6ugoDKaEPwhHAhoobUiydpYK3fw4nQSFIajYSLLk4SR1mUZM0GGiMhOJyDJGmhGvHOUI2Ei7pwUh1rFL10e1cXn\/dyqeDe+0ugaRowrWKP91XeSRspIQScBxEjSQKNRsA7R\/CeNE0wVWIsq84zxQmoRqbT6cUJcRm0vPckQXA1CBGH84JGw3t3WTcXgStJAtGq1hYR0iQlCZ40TXGuOsGLhvBOKIvKG4uiQJwRiwKzWJuzVsJY1QggDlTBOcRV+cjM0FgVu6rW6VEwoKw7MEkS1CBGxVQRR0VH8LX7l6gIyxirIFevW+YFsSyIsaAsSoqyqCi7yEJmVndFHT\/rwIYYevFdnV2iKVABU1WCdxREFssFsSwxS+ucI6CKVSgwrJaUoqasoirPc1SV\/wDhNHm2gKzJHQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMeinen Rechner hab ich von \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/mysn.de\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E mySN.de \/ Schenker Technologies\u003C\/a\u003E\u003C\/strong\u003E gekauft. Es scheinte eine gute Idee zu sein. Was es aber gar nicht. Ich f\u00fchle micht von mySN betrogen und we M\u00fcll behandelt. Ihre Kundenservice ist voll \u003Cstrong\u003Eunprofessionel\u003C\/strong\u003E, ihre \u003Cstrong\u003EHardware ist Schei\u00dfe\u003C\/strong\u003E und sie scheinen sogar nicht zu wissen, was sie im Lager haben und wie viel ihre Teile kosten. Im Ernsts!\u003C\/p\u003E\n\u003Cp\u003EDas ist mein (verk\u00fcrztes) Geschichte:\u003C\/p\u003E\n\u003Cp\u003EDen Laptop hab ich am 13.07.2017 bestellt. Offensichtlich haben sie meine Bestellung fast eine Woche gar nicht bearbeitet, \u003Cstrong\u003Esogar nicht \u00fcberpr\u00fcft, ob sie alle Teile im Lager haben\u003C\/strong\u003E, denn am 19.07 haben sie mir geschrieben, dass sie keine US-Layout Tastatur haben, w\u00fcrde mir UK auch passen?\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022430.71230342276\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAQCAYAAAB+690jAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACe0lEQVRIib2U2W4UMRBFj7e2u2dJJgl5YRE\/zw\/wQzwmgmhmFGXU3d6Kh55pIqIAEYT7ZJfLVde3yqW+fP4ki7cfGd98IKWEaxwpJUopWGtRSrHZbBARlsslxhhEBKUUwJM1gFJqtj+2Peez3+8JIWCtxaIU2liM0aAaai20bYtSmpwjpVSWyyVKqTnov8bZ2dlMUskEdtstAtRa0VpTawXAe896vf6lKn+r0GObPbFcrlZPLp\/I\/U\/MhLbbLaUURAQRwdrpSGolH\/sppUzXtVxdXb0aoblk3759JaVMrRXn3FFOTd\/3eN9MzkqRUkZrRdN4SsnEccRaQ4xbtFaEcE2pgjGaGCPOOfq+J4TA+fk5IYQ51i9LlnNGRNDazA4wBVZKUfKeUhKu2WBtwzgOOOd4++7dUc33L+qh5zA3SCmV4xW01lNAoGs7EEGbM6y7RKpi6Hucc8QYubu74+bm5i8L9QNzyWqtT17086u01uSc51l0+o2PFTnt5wTH9Yt\/2W63Y+h7rLM41xBjQqRSS0XpSUHvAyDknCm5YKzBGEOMI8EHqggKhdKaYejx3nN9ff0ihWZCKSWEKbExgkLIpSACuk491nih5EwphdV6xeHhQKHgfWCMEUQw1iIlY41h6Htubm+JMXKxuWC9Xv05oZOcxlhiHJEqIGCtQSuNMJFSQNe1jGPEGMMYR4L3RGCxXDEM\/VQeEVzTkFPCNw339\/fsd1tCO929vLygbdsnhOYeOhwO1FqptWKMoZSCc46SM2hNLZmm8XRd938mtXNuJmStxXv\/bOLXxEzo4eGBnDMgWOsYxpH16vc1fzVC3ntCCCwWi\/nwd0PsNfAdo3HKKlodhesAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022430.71230342276\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDas war unprofessionel und leicht \u00e4rgerlich, aber mir hat UK-Layout gepasst, so... Ich habe sie aber daran hingewiesen, dass f\u00fcr andere Teile ihre Website doch \u201cleider nicht verf\u00fcgbar, voraussichtliche Wartezeit ...\u201d zeigen kann, dann wieso k\u00f6nnen sie dieses Info nicht aktualisieren? Sie haben ihre Website korrigiert, aber keine M\u00fche gegeben, mich zu Antworten.\u003C\/p\u003E\n\u003Cp\u003EAm n\u00e4chsten Tag hab ich einen weiteren Email bekommen. Sie konnten den bestellten RAM-Speicher nicht finden. Noch mal, der Ersatz war OK, aber warum haben sie es fr\u00fcher nicht \u00fcberpr\u00fcft?\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022281.51711378353\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAKCAYAAADcpvzeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB1ElEQVQ4jbWTy44TQQxFj6vK\/QzMKGiyQeL\/P4It34KEAtJIQ3fSXXax6KQhQzK8hFeWbZWv7VPy8cP7oq9eM715y3GaUFVyzuScqaoKM2O73ZLnGUKgbRqapkFEeG6llDX+J\/7j4yNVVaGqpMOXTxQ3wu4dqhUhBJomkXMGYLvd0vf9T42v2TWRz+PXau7u7r7n3b0A7Pd7cs6UUgghrP5ut6OqqosHz5O9JOxva1ZBwzAwTxNFBAGKOyJCjJFpnlFVzIycjRCWuKpyOBwAUFVKKZQC7kZKCXcHwMzYbDbUdb02vyZIREjnQEoJMyPGiEjAbDlZVVWEGAkhEEKkbSPujtnSrK7rJSeCueNeSGmpLwVEwE\/D3drWxebKYnzef2aaZ6CQcyalRAyBw3ECgb7rGIaBvu8ZxxERwc1JGk9bC7gXNn3PMA64GW3XkeeZ4zxTa0XOmbqpeXh4AK4Dns6rQgSzfOJFiHHhKMaIWcbd0ZQYxwNuRlIlpoggqCoAMcDT1yfu7+\/ZbDY3Ib\/F1AVD4zhiZivUZ9VBBD+d9Pzd\/yfU6ey4O+5OKQV3p23bi9\/1r\/bjaV6qWaEOIaxQe1k4Oh6PCyvuqCpd192c8lfNfte+AU6DP3budERNAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022281.51711378353\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWir haben solche Emails hin und zur\u00fcck geschick. Aber endlich hab ich meinen Rechner bekommen \u2013 nach zu viel Zeit und zu viel Stress...\u003C\/p\u003E\n\u003Cp\u003EDer Laptop hat gut funktioniert, ich hatte keine Beschwerden \u2013 vielleicht au\u00dfer Lautsprecher, \u003Cstrong\u003Edie Tonqualit\u00e4t ist einfach furchtbar\u003C\/strong\u003E... Aber dann lief es schief.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EDas Ladeger\u00e4t wurde wahllos getrennt\u003C\/strong\u003E. Dann war wieder an nach ein paar Minuten. Dann wieder aus. Ein Tag war besser, der andere war schlechter. Ich hab fast aufgeh\u00f6rt nur Akku zu benutzen, weil ich Angst hatte, dass er alle wird und dann k\u00f6nnte es unm\u00f6glich sein, ihm wieder zu laden.\u003C\/p\u003E\n\u003Cp\u003EIch konnte es aber noch nicht zur Garantiereparatur schicken, weil ich meinen Rechner unbedingt brauchte. Das Problem mit Laden war \u00e4rgerlich und beunrihigend, aber ich konnte es f\u00fcr welche Zeit leiden.\u003C\/p\u003E\n\u003Cp\u003EAber nach ~ 2 Wochen hat etwas passiert. Als ich das Ladeger\u00e4t aus dem Ladeport gezogen habe, \u003Cstrong\u003Eist ein Bolzen von dem Ladeport irgendwie abgebrochen und im Ladeger\u00e4t geblieben\u003C\/strong\u003E. What the fuck?!\u003C\/p\u003E\n\u003Cp\u003ELadeport ist eine l\u00e4ngliche Tube mit dem Bolzen voll drin, 90\u00b0-winklig. Wie w\u00e4re es sogar m\u00f6glich, durch normaler Benutzung zu verursachen? Es geht nur wenn der Bolzen \/ Ladeport von Anfang fehlerhaft war.\u003C\/p\u003E\n\u003Cp\u003ELaut einer Freundin, die Expert in \u00e4nliche Reparaturen ist, mein Schuld ist hier ausgeschlossen. mySN ist das aber alles egal.\u003C\/p\u003E\n\u003Cp\u003ESie haben mir gesagt, dass \u201cF\u00fcr den Fall einer mechanischen Besch\u00e4digung vom Netzteil bzw. Ladeport vom Notebook ist die Reparatur nicht innerhalb Ihrer Garantie und somit nicht kostenfrei\u201d. Sie haben nicht gesagt \u003Cstrong\u003Ewie viel soll ich bezahlen\u003C\/strong\u003E. Sie forderten die Originalverpackung von mir \u2013 die ich nicht mehr habe, weil Garantiebedingungen fordern es auch nicht. Und sie haben \u003Cstrong\u003Emeine Kennw\u00f6rter gefordert\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cp\u003ENach meinem wutenden Email, haben sie \u201cmechanische Besch\u00e4digung\u201d mit \u201cden Fall eines gewaltsamen Einwirkens\u201d ersetzt \u2013 und weil es keine gab, dachte ich ich werde nicht bezahlen mussen. Sie haben die Kosten ein neuen Mainboard (!) \u201cgrob cirka 300-350\u20ac\u201d gesch\u00e4tzt. Ja, \u003Cstrong\u003Edie kennen die Kosten von ihre Ersatzteile nicht\u003C\/strong\u003E, sie k\u00f6nnen die nur \u00b150\u20ac sch\u00e4tzen. Die OVP brauchen sie auch nicht mehr - nur so gesagt hatten. Die Kennw\u00f6rter brauchen sie auch nicht mehr - nur so gesagt hatten. \u003C\/p\u003E\n\u003Cp\u003EEs hat eine Woche gedauert, ohne Rechner, einfach die Emails hin und zur\u00fcck zu senden, weil jeder hat \u003Cstrong\u003Emindestens 24 Stunden gebraucht, zu antworten\u003C\/strong\u003E. Sie haben mir auch einen Link zu DHL Retoure Service f\u00fcr... \u00d6sterreich statt Deutschland geschickt. Noch mal, Schenker\/mySN zeigt, wie unprofessionel sind sie.\u003C\/p\u003E\n\u003Cp\u003EAm Ende hab ich geschaff, ihnen meinen Rechner zu schicken. Zwei Tage nach dem Empfang, haben sie mir geschrieben: \u201cLeider musst du bezahlen. Wie viel? Sagen wir bald.\u201d\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-3_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022188.61909175162\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAHCAYAAABgOO8AAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABPklEQVQokZ2T3UoDMRCFvySbjV2oN7XQ4kXxkfqmPoH3+hqigi0ulO3vZma80K6lWLWem4TMx5mTIXGvd7dWXo1ZDq7p9y\/JOSMipJSoqooQAocyM5xz3fqdzmXW6zUiQq\/Xo9i8PILzxNENq9UKyZlYliwWC5qmQc0YDAZcpATQNTjV6K\/MIVtV1VdIMzOAuq5ZbzYUwdM0S+4fHihCYDabMZ1OwTmCD6gJOQsxRtrtjjKV5JyJMZLbllAUmCoGtG1LWZaoKmAURSSL4J1DVHE4TIXReIz3\/iOgqhqAiOC9x8wQEebzOSKCiDCZTL69nap2Rv\/VsUcXqK7f2G53qBopRVSN4XB4csyfgz2p\/zLFvrAvhuDJWQB4fn4ixkRud+AcWYTxaESM8awQh+e\/Md0bOsfop\/3e6\/iX\/ZV5ByCO4voy0njaAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-3_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022188.61909175162\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u201cBald\u201d was am n\u00e4chsten Tag. Und jeztz kostet neues Mainboard 449\u20ac, nicht \u201ccirka 300-350\u20ac\u201d. Plus Technikereinsatz, plus DHL \u2013 520\u20ac zusammen.\u003C\/p\u003E\n\u003Cp\u003EDas ist \u003Cstrong\u003Efast halb des originallen Preis\u003C\/strong\u003E. Wieso k\u00f6nnte ich von mySN\/Schenker nicht betrogen f\u00fchlen? Es ist bestimmt die schlimmste Kundenerfahrung, die ich hatte \u2013 von Anfang bis Ende: Hardwarequalit\u00e4t, Kundenservice, Professionalismus, Garantie, alles ist Schei\u00dfe.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["computer","crap","customer service","laptop","mysn","opinion","quality","review","schenker","schenker technologies","service","unprofessional","warranty"],"hasMore":true,"image":"https:\/\/avris.it\/image\/mysn-0_small.jpeg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMeinen Rechner hab ich von \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/mysn.de\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E mySN.de \/ Schenker Technologies\u003C\/a\u003E\u003C\/strong\u003E gekauft. Es scheinte eine gute Idee zu sein. Was es aber gar nicht. Ich f\u00fchle micht von mySN betrogen und we M\u00fcll behandelt. Ihre Kundenservice ist voll \u003Cstrong\u003Eunprofessionel\u003C\/strong\u003E, ihre \u003Cstrong\u003EHardware ist Schei\u00dfe\u003C\/strong\u003E und sie scheinen sogar nicht zu wissen, was sie im Lager haben und wie viel ihre Teile kosten. Im Ernsts!\u003C\/p\u003E\n\u003Cp\u003EDas ist mein (verk\u00fcrztes) Geschichte:\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMeinen Rechner hab ich von \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/mysn.de\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E mySN.de \/ Schenker Technologies\u003C\/a\u003E\u003C\/strong\u003E gekauft. Es scheinte eine gute Idee zu sein. Was es aber gar nicht. Ich f\u00fchle micht von mySN betrogen und we M\u00fcll behandelt. Ihre Kundenservice ist voll \u003Cstrong\u003Eunprofessionel\u003C\/strong\u003E, ihre \u003Cstrong\u003EHardware ist Schei\u00dfe\u003C\/strong\u003E und sie scheinen sogar nicht zu wissen, was sie im Lager haben und wie viel ihre Teile kosten. Im Ernsts!\u003C\/p\u003E\n\u003Cp\u003EDas ist mein (verk\u00fcrztes) Geschichte:\u003C\/p\u003E\n\u003Cp\u003EDen Laptop hab ich am 13.07.2017 bestellt. Offensichtlich haben sie meine Bestellung fast eine Woche gar nicht bearbeitet, \u003Cstrong\u003Esogar nicht \u00fcberpr\u00fcft, ob sie alle Teile im Lager haben\u003C\/strong\u003E, denn am 19.07 haben sie mir geschrieben, dass sie keine US-Layout Tastatur haben, w\u00fcrde mir UK auch passen?\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-1_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-1_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022107.67807585569\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EDas war unprofessionel und leicht \u00e4rgerlich, aber mir hat UK-Layout gepasst, so... Ich habe sie aber daran hingewiesen, dass f\u00fcr andere Teile ihre Website doch \u201cleider nicht verf\u00fcgbar, voraussichtliche Wartezeit ...\u201d zeigen kann, dann wieso k\u00f6nnen sie dieses Info nicht aktualisieren? Sie haben ihre Website korrigiert, aber keine M\u00fche gegeben, mich zu Antworten.\u003C\/p\u003E\n\u003Cp\u003EAm n\u00e4chsten Tag hab ich einen weiteren Email bekommen. Sie konnten den bestellten RAM-Speicher nicht finden. Noch mal, der Ersatz war OK, aber warum haben sie es fr\u00fcher nicht \u00fcberpr\u00fcft?\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-2_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-2_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002270.379278445883\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWir haben solche Emails hin und zur\u00fcck geschick. Aber endlich hab ich meinen Rechner bekommen \u2013 nach zu viel Zeit und zu viel Stress...\u003C\/p\u003E\n\u003Cp\u003EDer Laptop hat gut funktioniert, ich hatte keine Beschwerden \u2013 vielleicht au\u00dfer Lautsprecher, \u003Cstrong\u003Edie Tonqualit\u00e4t ist einfach furchtbar\u003C\/strong\u003E... Aber dann lief es schief.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EDas Ladeger\u00e4t wurde wahllos getrennt\u003C\/strong\u003E. Dann war wieder an nach ein paar Minuten. Dann wieder aus. Ein Tag war besser, der andere war schlechter. Ich hab fast aufgeh\u00f6rt nur Akku zu benutzen, weil ich Angst hatte, dass er alle wird und dann k\u00f6nnte es unm\u00f6glich sein, ihm wieder zu laden.\u003C\/p\u003E\n\u003Cp\u003EIch konnte es aber noch nicht zur Garantiereparatur schicken, weil ich meinen Rechner unbedingt brauchte. Das Problem mit Laden war \u00e4rgerlich und beunrihigend, aber ich konnte es f\u00fcr welche Zeit leiden.\u003C\/p\u003E\n\u003Cp\u003EAber nach ~ 2 Wochen hat etwas passiert. Als ich das Ladeger\u00e4t aus dem Ladeport gezogen habe, \u003Cstrong\u003Eist ein Bolzen von dem Ladeport irgendwie abgebrochen und im Ladeger\u00e4t geblieben\u003C\/strong\u003E. What the fuck?!\u003C\/p\u003E\n\u003Cp\u003ELadeport ist eine l\u00e4ngliche Tube mit dem Bolzen voll drin, 90\u00b0-winklig. Wie w\u00e4re es sogar m\u00f6glich, durch normaler Benutzung zu verursachen? Es geht nur wenn der Bolzen \/ Ladeport von Anfang fehlerhaft war.\u003C\/p\u003E\n\u003Cp\u003ELaut einer Freundin, die Expert in \u00e4nliche Reparaturen ist, mein Schuld ist hier ausgeschlossen. mySN ist das aber alles egal.\u003C\/p\u003E\n\u003Cp\u003ESie haben mir gesagt, dass \u201cF\u00fcr den Fall einer mechanischen Besch\u00e4digung vom Netzteil bzw. Ladeport vom Notebook ist die Reparatur nicht innerhalb Ihrer Garantie und somit nicht kostenfrei\u201d. Sie haben nicht gesagt \u003Cstrong\u003Ewie viel soll ich bezahlen\u003C\/strong\u003E. Sie forderten die Originalverpackung von mir \u2013 die ich nicht mehr habe, weil Garantiebedingungen fordern es auch nicht. Und sie haben \u003Cstrong\u003Emeine Kennw\u00f6rter gefordert\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cp\u003ENach meinem wutenden Email, haben sie \u201cmechanische Besch\u00e4digung\u201d mit \u201cden Fall eines gewaltsamen Einwirkens\u201d ersetzt \u2013 und weil es keine gab, dachte ich ich werde nicht bezahlen mussen. Sie haben die Kosten ein neuen Mainboard (!) \u201cgrob cirka 300-350\u20ac\u201d gesch\u00e4tzt. Ja, \u003Cstrong\u003Edie kennen die Kosten von ihre Ersatzteile nicht\u003C\/strong\u003E, sie k\u00f6nnen die nur \u00b150\u20ac sch\u00e4tzen. Die OVP brauchen sie auch nicht mehr - nur so gesagt hatten. Die Kennw\u00f6rter brauchen sie auch nicht mehr - nur so gesagt hatten. \u003C\/p\u003E\n\u003Cp\u003EEs hat eine Woche gedauert, ohne Rechner, einfach die Emails hin und zur\u00fcck zu senden, weil jeder hat \u003Cstrong\u003Emindestens 24 Stunden gebraucht, zu antworten\u003C\/strong\u003E. Sie haben mir auch einen Link zu DHL Retoure Service f\u00fcr... \u00d6sterreich statt Deutschland geschickt. Noch mal, Schenker\/mySN zeigt, wie unprofessionel sind sie.\u003C\/p\u003E\n\u003Cp\u003EAm Ende hab ich geschaff, ihnen meinen Rechner zu schicken. Zwei Tage nach dem Empfang, haben sie mir geschrieben: \u201cLeider musst du bezahlen. Wie viel? Sagen wir bald.\u201d\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-3_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-3_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002247.154772937905\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u201cBald\u201d was am n\u00e4chsten Tag. Und jeztz kostet neues Mainboard 449\u20ac, nicht \u201ccirka 300-350\u20ac\u201d. Plus Technikereinsatz, plus DHL \u2013 520\u20ac zusammen.\u003C\/p\u003E\n\u003Cp\u003EDas ist \u003Cstrong\u003Efast halb des originallen Preis\u003C\/strong\u003E. Wieso k\u00f6nnte ich von mySN\/Schenker nicht betrogen f\u00fchlen? Es ist bestimmt die schlimmste Kundenerfahrung, die ich hatte \u2013 von Anfang bis Ende: Hardwarequalit\u00e4t, Kundenservice, Professionalismus, Garantie, alles ist Schei\u00dfe.\u003C\/p\u003E","words":706,"readTime":3,"lang":"de"},"en":{"slug":"mysn-schenker-kurwa-ma\u0107-en","title":"mySN.de \/ Schenker \u2013 kurwa ma\u0107! \ud83d\ude20","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGVUlEQVRIiXWWzW4cxxWFv1tV3TM9v\/zRiMMhKUqWJUWwjQBO7G1WQZBXMPJOAbLIQxjIM9hGNpEDW14IdgxDsiOJpCSKIjn\/0911bxbdpKggKaDRjUZX1ek6955zZDhYs7wsmc2WFDHiEBADBFUwM5xzOOcQES6GiIAAIgj1vb6gmocJIIgzRARTAzMQCImjkSY0mw1azYxOu02SOMJ8uWI2X6FaTVIMUwC73NzMLjeKqjhxGIb3vgbhcCKIc2DVTBHBe0+\/3+fa5jXW19dYW1uj1WrR7\/bodlpkzZTx+JzpfMZ8PmM8HiNOxC4WqPY0VHlnhBBQ1eqvEZwPmBlZltHv9xlcGzAajRgOtxluDxltj9jZGTEYXCPPc+bzBYdHRxy\/PubVq2OOXrzg8OiI1yevmc\/nlEXJqliiURERsUsKMJwTwF3SkiQpvV6fzc1Nrl\/fYnd3j\/39G9x+7zY3b92k027TamWUsWQ8nvD65ISDwxc8ffaMg4NDjo9fc\/LmDdPZDDNlsViwWq4oY47GSFkWODGcOLwDcc4ZQLvdotvtsrmxwWBzwHA4Yms4Yn1jHec9UY2yLCljpIyR8\/Mx4\/GEPM85PTtnNpuhaqgpZVmQr5bEGAnB452QhEC322F9rU+\/36PbbpEkAbPIdDJmNp9TrFYVoMFgg1\/dvYdLGkQ1ohrT6Zw3Z+fkeYGZXRZ38AERRwierNmk02nRabfYHm6xd2OPne1ttra26PW6qCrT6YTJZEqel4wnY05P33B6dsp0cs5kMub4+ARDEYGiqAGJ87iQ4rxHpKLLiSNJAmmSkDWbXL9+nRt7N3j\/9m1u3drn2uYmahFVI01TDDg\/O+Pw4DnLxZytrQGmJY9\/ecrZ+TnD7R2SRsZiuSQNwmKxZDw+49tvvyFrpCxqGsU5Z1mrRRkjgrB\/Y4+7799lNBqxtTVkNNplZ3eXjY0NHj95zMOHDzFTyrJkd3eXm\/t7rK+tAfDgwT8YDK5x\/\/49xuMJq6IEcWTtFj\/+8D0vXr1hMV8wm004Oz3h+PUJz589Iy9yiiJntcoJAPlqRdbKuH\/3Dp9+8inD7R1++PFffP3Pr2l3vuezz\/7Ew+++4eHD79jZ3WEynXH+5pijBz+TJr\/DVAne0+l22Lt5i3Z3jSgBt5iTBMfPTx7z+ed\/4+nzI\/LlAtVIjBEzRa2iS8xQjFB1kue9vR3u3b2LCSSNFLOCaCVHRwd88eUXPHr0iG63w6vjY\/prfX79wR0+\/OA+Pz35N3\/+y195dnBIcJ7R9oCPPrzPy5cvOT0bc3p2xmQyYTqdIWK1pinOWdXmKBrryxTx3puI0Ov3yLIWWdZCVVmt8loUoSwjZVlWOiTw209+wx\/\/8HtmkzE\/Pf6FVrvNV1\/9nYPDQ5wITgQzJWqJqaKqqEY0VicTo14R3ivKXkmNmPeekAQajWal7OIuO+viY9W3z0masLe3R75cMZ1OSRsphwcHNQ1vFR7RSrWvvAIQJ4QQaDRSWlmTdjtjfa1Lt9O6AFQBCGmK9x7TypNifMv1W4C1H1VGxv8bzjuazbTSt06H9fU+\/X6fXq9Dp5WRZU2Cd6hFRAzvBNUS8d6ZiNTWAM45zMDqja\/62NXn\/w3IaGYZH3\/8EaPRkH6vV\/kbELyj0WiQpgGzqnaS4NEYq72JlEVOuGLgmBkxxndc\/SoQEbnC9X9hESHLmuzv73Dnzm289zQaTdJGQvCeJDgQKMuS4F1lFd5RFgXOC8tlgXdStb2I4J0DFFV7pw6ugoDKaEPwhHAhoobUiydpYK3fw4nQSFIajYSLLk4SR1mUZM0GGiMhOJyDJGmhGvHOUI2Ei7pwUh1rFL10e1cXn\/dyqeDe+0ugaRowrWKP91XeSRspIQScBxEjSQKNRsA7R\/CeNE0wVWIsq84zxQmoRqbT6cUJcRm0vPckQXA1CBGH84JGw3t3WTcXgStJAtGq1hYR0iQlCZ40TXGuOsGLhvBOKIvKG4uiQJwRiwKzWJuzVsJY1QggDlTBOcRV+cjM0FgVu6rW6VEwoKw7MEkS1CBGxVQRR0VH8LX7l6gIyxirIFevW+YFsSyIsaAsSoqyqCi7yEJmVndFHT\/rwIYYevFdnV2iKVABU1WCdxREFssFsSwxS+ucI6CKVSgwrJaUoqasoirPc1SV\/wDhNHm2gKzJHQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-0_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve bought my laptop from \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/mysn.de\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E mySN.de \/ Schenker Technologies\u003C\/a\u003E\u003C\/strong\u003E. It seemed like a good idea at the time. But it definitely was not. I feel scammed by them, I feel treated like trash by them. Their customer service is \u003Cstrong\u003Eunprofessional\u003C\/strong\u003E, their \u003Cstrong\u003Ehardware is crap\u003C\/strong\u003E and they don\u2019t even seem to know what they have in storage and how much do their parts cost. Seriously!\u003C\/p\u003E\n\u003Cp\u003EHere\u2019s my story in short:\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGVUlEQVRIiXWWzW4cxxWFv1tV3TM9v\/zRiMMhKUqWJUWwjQBO7G1WQZBXMPJOAbLIQxjIM9hGNpEDW14IdgxDsiOJpCSKIjn\/0911bxbdpKggKaDRjUZX1ek6955zZDhYs7wsmc2WFDHiEBADBFUwM5xzOOcQES6GiIAAIgj1vb6gmocJIIgzRARTAzMQCImjkSY0mw1azYxOu02SOMJ8uWI2X6FaTVIMUwC73NzMLjeKqjhxGIb3vgbhcCKIc2DVTBHBe0+\/3+fa5jXW19dYW1uj1WrR7\/bodlpkzZTx+JzpfMZ8PmM8HiNOxC4WqPY0VHlnhBBQ1eqvEZwPmBlZltHv9xlcGzAajRgOtxluDxltj9jZGTEYXCPPc+bzBYdHRxy\/PubVq2OOXrzg8OiI1yevmc\/nlEXJqliiURERsUsKMJwTwF3SkiQpvV6fzc1Nrl\/fYnd3j\/39G9x+7zY3b92k027TamWUsWQ8nvD65ISDwxc8ffaMg4NDjo9fc\/LmDdPZDDNlsViwWq4oY47GSFkWODGcOLwDcc4ZQLvdotvtsrmxwWBzwHA4Yms4Yn1jHec9UY2yLCljpIyR8\/Mx4\/GEPM85PTtnNpuhaqgpZVmQr5bEGAnB452QhEC322F9rU+\/36PbbpEkAbPIdDJmNp9TrFYVoMFgg1\/dvYdLGkQ1ohrT6Zw3Z+fkeYGZXRZ38AERRwierNmk02nRabfYHm6xd2OPne1ttra26PW6qCrT6YTJZEqel4wnY05P33B6dsp0cs5kMub4+ARDEYGiqAGJ87iQ4rxHpKLLiSNJAmmSkDWbXL9+nRt7N3j\/9m1u3drn2uYmahFVI01TDDg\/O+Pw4DnLxZytrQGmJY9\/ecrZ+TnD7R2SRsZiuSQNwmKxZDw+49tvvyFrpCxqGsU5Z1mrRRkjgrB\/Y4+7799lNBqxtTVkNNplZ3eXjY0NHj95zMOHDzFTyrJkd3eXm\/t7rK+tAfDgwT8YDK5x\/\/49xuMJq6IEcWTtFj\/+8D0vXr1hMV8wm004Oz3h+PUJz589Iy9yiiJntcoJAPlqRdbKuH\/3Dp9+8inD7R1++PFffP3Pr2l3vuezz\/7Ew+++4eHD79jZ3WEynXH+5pijBz+TJr\/DVAne0+l22Lt5i3Z3jSgBt5iTBMfPTx7z+ed\/4+nzI\/LlAtVIjBEzRa2iS8xQjFB1kue9vR3u3b2LCSSNFLOCaCVHRwd88eUXPHr0iG63w6vjY\/prfX79wR0+\/OA+Pz35N3\/+y195dnBIcJ7R9oCPPrzPy5cvOT0bc3p2xmQyYTqdIWK1pinOWdXmKBrryxTx3puI0Ov3yLIWWdZCVVmt8loUoSwjZVlWOiTw209+wx\/\/8HtmkzE\/Pf6FVrvNV1\/9nYPDQ5wITgQzJWqJqaKqqEY0VicTo14R3ivKXkmNmPeekAQajWal7OIuO+viY9W3z0masLe3R75cMZ1OSRsphwcHNQ1vFR7RSrWvvAIQJ4QQaDRSWlmTdjtjfa1Lt9O6AFQBCGmK9x7TypNifMv1W4C1H1VGxv8bzjuazbTSt06H9fU+\/X6fXq9Dp5WRZU2Cd6hFRAzvBNUS8d6ZiNTWAM45zMDqja\/62NXn\/w3IaGYZH3\/8EaPRkH6vV\/kbELyj0WiQpgGzqnaS4NEYq72JlEVOuGLgmBkxxndc\/SoQEbnC9X9hESHLmuzv73Dnzm289zQaTdJGQvCeJDgQKMuS4F1lFd5RFgXOC8tlgXdStb2I4J0DFFV7pw6ugoDKaEPwhHAhoobUiydpYK3fw4nQSFIajYSLLk4SR1mUZM0GGiMhOJyDJGmhGvHOUI2Ei7pwUh1rFL10e1cXn\/dyqeDe+0ugaRowrWKP91XeSRspIQScBxEjSQKNRsA7R\/CeNE0wVWIsq84zxQmoRqbT6cUJcRm0vPckQXA1CBGH84JGw3t3WTcXgStJAtGq1hYR0iQlCZ40TXGuOsGLhvBOKIvKG4uiQJwRiwKzWJuzVsJY1QggDlTBOcRV+cjM0FgVu6rW6VEwoKw7MEkS1CBGxVQRR0VH8LX7l6gIyxirIFevW+YFsSyIsaAsSoqyqCi7yEJmVndFHT\/rwIYYevFdnV2iKVABU1WCdxREFssFsSwxS+ucI6CKVSgwrJaUoqasoirPc1SV\/wDhNHm2gKzJHQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve bought my laptop from \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/mysn.de\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E mySN.de \/ Schenker Technologies\u003C\/a\u003E\u003C\/strong\u003E. It seemed like a good idea at the time. But it definitely was not. I feel scammed by them, I feel treated like trash by them. Their customer service is \u003Cstrong\u003Eunprofessional\u003C\/strong\u003E, their \u003Cstrong\u003Ehardware is crap\u003C\/strong\u003E and they don\u2019t even seem to know what they have in storage and how much do their parts cost. Seriously!\u003C\/p\u003E\n\u003Cp\u003EHere\u2019s my story in short:\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve ordered my laptop on 13.07.2017. Apparently they didn\u2019t even start processing that order for almost a week, \u003Cstrong\u003Enot even check if they have all the parts\u003C\/strong\u003E, because on 19.07 they wrote me that they don\u2019t have any keyboards with US layout, would I be fine with UK?\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022430.71230342276\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAQCAYAAAB+690jAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACe0lEQVRIib2U2W4UMRBFj7e2u2dJJgl5YRE\/zw\/wQzwmgmhmFGXU3d6Kh55pIqIAEYT7ZJfLVde3yqW+fP4ki7cfGd98IKWEaxwpJUopWGtRSrHZbBARlsslxhhEBKUUwJM1gFJqtj+2Peez3+8JIWCtxaIU2liM0aAaai20bYtSmpwjpVSWyyVKqTnov8bZ2dlMUskEdtstAtRa0VpTawXAe896vf6lKn+r0GObPbFcrlZPLp\/I\/U\/MhLbbLaUURAQRwdrpSGolH\/sppUzXtVxdXb0aoblk3759JaVMrRXn3FFOTd\/3eN9MzkqRUkZrRdN4SsnEccRaQ4xbtFaEcE2pgjGaGCPOOfq+J4TA+fk5IYQ51i9LlnNGRNDazA4wBVZKUfKeUhKu2WBtwzgOOOd4++7dUc33L+qh5zA3SCmV4xW01lNAoGs7EEGbM6y7RKpi6Hucc8QYubu74+bm5i8L9QNzyWqtT17086u01uSc51l0+o2PFTnt5wTH9Yt\/2W63Y+h7rLM41xBjQqRSS0XpSUHvAyDknCm5YKzBGEOMI8EHqggKhdKaYejx3nN9ff0ihWZCKSWEKbExgkLIpSACuk491nih5EwphdV6xeHhQKHgfWCMEUQw1iIlY41h6Htubm+JMXKxuWC9Xv05oZOcxlhiHJEqIGCtQSuNMJFSQNe1jGPEGMMYR4L3RGCxXDEM\/VQeEVzTkFPCNw339\/fsd1tCO929vLygbdsnhOYeOhwO1FqptWKMoZSCc46SM2hNLZmm8XRd938mtXNuJmStxXv\/bOLXxEzo4eGBnDMgWOsYxpH16vc1fzVC3ntCCCwWi\/nwd0PsNfAdo3HKKlodhesAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-1_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022430.71230342276\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWell, it\u2019s unprofessional and mildly annoying, but I was in fact fine with UK-layout. I have pointed them out though, that for other parts their website is able to show \u201cnot available in stock, foreseen waiting time ...\u201d, so how come they aren\u2019t able to keep that info up to date? They did update the website, but didn\u2019t bother to answer my email.\u003C\/p\u003E\n\u003Cp\u003EThe next day I got another email. This time they couldn\u2019t find the RAM I had ordered. Again, I was fine with the replacement, but why the hell didn\u2019t they check it earlier?\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022281.51711378353\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAKCAYAAADcpvzeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB1ElEQVQ4jbWTy44TQQxFj6vK\/QzMKGiyQeL\/P4It34KEAtJIQ3fSXXax6KQhQzK8hFeWbZWv7VPy8cP7oq9eM715y3GaUFVyzuScqaoKM2O73ZLnGUKgbRqapkFEeG6llDX+J\/7j4yNVVaGqpMOXTxQ3wu4dqhUhBJomkXMGYLvd0vf9T42v2TWRz+PXau7u7r7n3b0A7Pd7cs6UUgghrP5ut6OqqosHz5O9JOxva1ZBwzAwTxNFBAGKOyJCjJFpnlFVzIycjRCWuKpyOBwAUFVKKZQC7kZKCXcHwMzYbDbUdb02vyZIREjnQEoJMyPGiEjAbDlZVVWEGAkhEEKkbSPujtnSrK7rJSeCueNeSGmpLwVEwE\/D3drWxebKYnzef2aaZ6CQcyalRAyBw3ECgb7rGIaBvu8ZxxERwc1JGk9bC7gXNn3PMA64GW3XkeeZ4zxTa0XOmbqpeXh4AK4Dns6rQgSzfOJFiHHhKMaIWcbd0ZQYxwNuRlIlpoggqCoAMcDT1yfu7+\/ZbDY3Ib\/F1AVD4zhiZivUZ9VBBD+d9Pzd\/yfU6ey4O+5OKQV3p23bi9\/1r\/bjaV6qWaEOIaxQe1k4Oh6PCyvuqCpd192c8lfNfte+AU6DP3budERNAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-2_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022281.51711378353\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI was exchanging emails like those back and forth with them. But finally, I got my computer, though after way too much waiting and stress...\u003C\/p\u003E\n\u003Cp\u003EIt worked fine, I didn\u2019t complain. Well, except about the speakers \u2013 the \u003Cstrong\u003Esound quality is just awful\u003C\/strong\u003E... And then it started going bad.\u003C\/p\u003E\n\u003Cp\u003EThe \u003Cstrong\u003Echarger would just disconnect randomly\u003C\/strong\u003E. Then connect back after a couple of minutes. Then disconnect again. One day it was better, the other it was worse. I almost didn\u2019t use it on battery anymore, for fear I would drain it and then not be able to charge it back.\u003C\/p\u003E\n\u003Cp\u003EBut I didn\u2019t send it to warranty repair yet, because I really needed to have my laptop and use it. The problem with charger was very annoying and worrying, but I could live with it for a while.\u003C\/p\u003E\n\u003Cp\u003EBut after ~ 2 weeks something happened. When I unplugged the charger, the pin from the socket inside of the computer \u003Cstrong\u003Egot snapped off somehow (!) and stayed inside the charger\u003C\/strong\u003E. What the fuck!?\u003C\/p\u003E\n\u003Cp\u003EThe socket is an elongated tube with the pin fully inside it, not sticking out and only accessible at 90\u00b0. How on Earth could I create such damage but normal usage, if they socket weren\u2019t defective in the first place?\u003C\/p\u003E\n\u003Cp\u003EAccording to a friend who\u2019s an expert in computer repairs it\u2019s not possible. But mySN.de doesn\u2019t give a crap.\u003C\/p\u003E\n\u003Cp\u003EThey told me that in case of \u201cmechanical damage\u201d I would have to pay for the repair myself. And they \u003Cstrong\u003Edidn\u2019t say how much\u003C\/strong\u003E. And they required me to send the computer in the \u003Cstrong\u003Eoriginal packing\u003C\/strong\u003E \u2013 which I didn\u2019t keep and which they don\u2019t require in the terms of warranty. And they \u003Cstrong\u003Erequired my password\u003C\/strong\u003E. \u003C\/p\u003E\n\u003Cp\u003EAfter my angry email they changed the \u201cmechanical damage\u201d to \u201cviolent abuse\u201d \u2013 and since there was none, I think I shouldn\u2019t be charged. They estimated the cost of a new motherboard (!) to be around 300-350\u20ac. Yup, they \u003Cstrong\u003Edon\u2019t know how much their own parts cost\u003C\/strong\u003E, they can just estimate it \u00b150\u20ac. They also said that original packing isn\u2019t required after all, they just say so bacause of reasons. And that my password isn\u2019t required either, they just say so bacause of reasons.\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve spent a week, without a computer, just exchanging emails with them, because every one of them took them \u003Cstrong\u003Eat least 24h to respond\u003C\/strong\u003E to. They also sent me a link to DHL Retoure Service for... Austria (I live in Germany). Again, Schenker\/mySN shows how unprofessional they are.\u003C\/p\u003E\n\u003Cp\u003EFinally, I\u2019ve managed to send my computer to them. Two days after they received it, I got an email: \u201cSorry, you\u2019ll have to pay for it. How much? We\u2019ll tell you soon\u201d.\u003C\/p\u003E\n\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-3_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022188.61909175162\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAHCAYAAABgOO8AAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABPklEQVQokZ2T3UoDMRCFvySbjV2oN7XQ4kXxkfqmPoH3+hqigi0ulO3vZma80K6lWLWem4TMx5mTIXGvd7dWXo1ZDq7p9y\/JOSMipJSoqooQAocyM5xz3fqdzmXW6zUiQq\/Xo9i8PILzxNENq9UKyZlYliwWC5qmQc0YDAZcpATQNTjV6K\/MIVtV1VdIMzOAuq5ZbzYUwdM0S+4fHihCYDabMZ1OwTmCD6gJOQsxRtrtjjKV5JyJMZLbllAUmCoGtG1LWZaoKmAURSSL4J1DVHE4TIXReIz3\/iOgqhqAiOC9x8wQEebzOSKCiDCZTL69nap2Rv\/VsUcXqK7f2G53qBopRVSN4XB4csyfgz2p\/zLFvrAvhuDJWQB4fn4ixkRud+AcWYTxaESM8awQh+e\/Md0bOsfop\/3e6\/iX\/ZV5ByCO4voy0njaAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/mysn-3_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022188.61909175162\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u201cSoon\u201d meant the next day. Turns out the motherboard costs 449\u20ac, not \u201caround 300-350\u20ac\u201d. Plus service fee, plus courier back \u2013 520\u20ac in total.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s \u003Cstrong\u003Eclose to a half\u003C\/strong\u003E of the original price. How on Earth am I supposed not to feel scammed by mySN\/Schenker? It is definitely the worst customer experience I\u2019ve ever had \u2013 top to bottom: hardware quality, customer service, professionalism, warranty, everything sucks.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["ansicht","bewertung","customer service","empfehlung","erfahrung","guarantie","komputer","meinung","mysn","qualit\u00e4t","rechner","reparatur","rezension","schei\u00dfe","schenker","schenker technologies","service"],"hasMore":true,"image":"https:\/\/avris.it\/image\/mysn-0_small.jpeg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve bought my laptop from \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/mysn.de\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E mySN.de \/ Schenker Technologies\u003C\/a\u003E\u003C\/strong\u003E. It seemed like a good idea at the time. But it definitely was not. I feel scammed by them, I feel treated like trash by them. Their customer service is \u003Cstrong\u003Eunprofessional\u003C\/strong\u003E, their \u003Cstrong\u003Ehardware is crap\u003C\/strong\u003E and they don\u2019t even seem to know what they have in storage and how much do their parts cost. Seriously!\u003C\/p\u003E\n\u003Cp\u003EHere\u2019s my story in short:\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-0_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-0_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve bought my laptop from \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/mysn.de\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E mySN.de \/ Schenker Technologies\u003C\/a\u003E\u003C\/strong\u003E. It seemed like a good idea at the time. But it definitely was not. I feel scammed by them, I feel treated like trash by them. Their customer service is \u003Cstrong\u003Eunprofessional\u003C\/strong\u003E, their \u003Cstrong\u003Ehardware is crap\u003C\/strong\u003E and they don\u2019t even seem to know what they have in storage and how much do their parts cost. Seriously!\u003C\/p\u003E\n\u003Cp\u003EHere\u2019s my story in short:\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve ordered my laptop on 13.07.2017. Apparently they didn\u2019t even start processing that order for almost a week, \u003Cstrong\u003Enot even check if they have all the parts\u003C\/strong\u003E, because on 19.07 they wrote me that they don\u2019t have any keyboards with US layout, would I be fine with UK?\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-1_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-1_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022107.67807585569\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWell, it\u2019s unprofessional and mildly annoying, but I was in fact fine with UK-layout. I have pointed them out though, that for other parts their website is able to show \u201cnot available in stock, foreseen waiting time ...\u201d, so how come they aren\u2019t able to keep that info up to date? They did update the website, but didn\u2019t bother to answer my email.\u003C\/p\u003E\n\u003Cp\u003EThe next day I got another email. This time they couldn\u2019t find the RAM I had ordered. Again, I was fine with the replacement, but why the hell didn\u2019t they check it earlier?\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-2_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-2_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002270.379278445883\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI was exchanging emails like those back and forth with them. But finally, I got my computer, though after way too much waiting and stress...\u003C\/p\u003E\n\u003Cp\u003EIt worked fine, I didn\u2019t complain. Well, except about the speakers \u2013 the \u003Cstrong\u003Esound quality is just awful\u003C\/strong\u003E... And then it started going bad.\u003C\/p\u003E\n\u003Cp\u003EThe \u003Cstrong\u003Echarger would just disconnect randomly\u003C\/strong\u003E. Then connect back after a couple of minutes. Then disconnect again. One day it was better, the other it was worse. I almost didn\u2019t use it on battery anymore, for fear I would drain it and then not be able to charge it back.\u003C\/p\u003E\n\u003Cp\u003EBut I didn\u2019t send it to warranty repair yet, because I really needed to have my laptop and use it. The problem with charger was very annoying and worrying, but I could live with it for a while.\u003C\/p\u003E\n\u003Cp\u003EBut after ~ 2 weeks something happened. When I unplugged the charger, the pin from the socket inside of the computer \u003Cstrong\u003Egot snapped off somehow (!) and stayed inside the charger\u003C\/strong\u003E. What the fuck!?\u003C\/p\u003E\n\u003Cp\u003EThe socket is an elongated tube with the pin fully inside it, not sticking out and only accessible at 90\u00b0. How on Earth could I create such damage but normal usage, if they socket weren\u2019t defective in the first place?\u003C\/p\u003E\n\u003Cp\u003EAccording to a friend who\u2019s an expert in computer repairs it\u2019s not possible. But mySN.de doesn\u2019t give a crap.\u003C\/p\u003E\n\u003Cp\u003EThey told me that in case of \u201cmechanical damage\u201d I would have to pay for the repair myself. And they \u003Cstrong\u003Edidn\u2019t say how much\u003C\/strong\u003E. And they required me to send the computer in the \u003Cstrong\u003Eoriginal packing\u003C\/strong\u003E \u2013 which I didn\u2019t keep and which they don\u2019t require in the terms of warranty. And they \u003Cstrong\u003Erequired my password\u003C\/strong\u003E. \u003C\/p\u003E\n\u003Cp\u003EAfter my angry email they changed the \u201cmechanical damage\u201d to \u201cviolent abuse\u201d \u2013 and since there was none, I think I shouldn\u2019t be charged. They estimated the cost of a new motherboard (!) to be around 300-350\u20ac. Yup, they \u003Cstrong\u003Edon\u2019t know how much their own parts cost\u003C\/strong\u003E, they can just estimate it \u00b150\u20ac. They also said that original packing isn\u2019t required after all, they just say so bacause of reasons. And that my password isn\u2019t required either, they just say so bacause of reasons.\u003C\/p\u003E\n\u003Cp\u003EI\u2019ve spent a week, without a computer, just exchanging emails with them, because every one of them took them \u003Cstrong\u003Eat least 24h to respond\u003C\/strong\u003E to. They also sent me a link to DHL Retoure Service for... Austria (I live in Germany). Again, Schenker\/mySN shows how unprofessional they are.\u003C\/p\u003E\n\u003Cp\u003EFinally, I\u2019ve managed to send my computer to them. Two days after they received it, I got an email: \u201cSorry, you\u2019ll have to pay for it. How much? We\u2019ll tell you soon\u201d.\u003C\/p\u003E\n\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mysn-3_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mysn-3_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u002247.154772937905\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u201cSoon\u201d meant the next day. Turns out the motherboard costs 449\u20ac, not \u201caround 300-350\u20ac\u201d. Plus service fee, plus courier back \u2013 520\u20ac in total.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s \u003Cstrong\u003Eclose to a half\u003C\/strong\u003E of the original price. How on Earth am I supposed not to feel scammed by mySN\/Schenker? It is definitely the worst customer experience I\u2019ve ever had \u2013 top to bottom: hardware quality, customer service, professionalism, warranty, everything sucks.\u003C\/p\u003E","words":748,"readTime":3,"lang":"en"}}},"blog\/technology\/moving-to-vanilla-js":{"key":"blog\/technology\/moving-to-vanilla-js","type":"article","published":true,"meta":{"createdAt":"2018-01-19T19:02:20+01:00","publishedAt":"2018-01-31T19:01:00+01:00","group":"vanillin","category":"blog","subcategory":"technology","slug":"moving-to-vanilla-js"},"content":{"en":{"slug":"moving-to-vanilla-js","title":"Moving to vanilla JS","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-forms-multiple_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022201.10091743119\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAPCAYAAACMa21tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB5klEQVRIib2VTW4TQRCFv+rpiRMyDnISLyEcACkhXAEuAVsuxQk4AogFSNkgWLIFkVVAiW1kouD58XQXi\/H4D409YxHeZko93VWvq15VS5ymygrI5KsKIov2yoMbwgrCoD8gsIY8dwTWgiqdTmcSXFHVKZESegtsjDFYADFCnueIGARwqihFdkSEb1+\/cH1zw\/5Bl6P799Y67l1d8uPyijwbc\/r4tBEpiZPVJQOmGWqK8lK1yYhgq4\/M3JXaMcasdeq9R4Gg5l738RPu7Axz8gj79AlWKq8w+2HE0B\/0iKI92tFuZYDcOdJ0TBiGDIdDRAzdw\/3K\/Wk2Ri++Q6+PPz9HBCQpu6xMSFkdma1536RkUnRgnTKLIKMROvyFtCOk3UbiNFs4KUw6aEpON9ZQU4gY7HL\/6l8GGCMkSUJrq4W1ttKh844sG2PDkDRJCIKAne3tyv25c+Sv3+DevcecHBM+f7asobk6LVGM4wRrLVaqCQUmILCTm6jHe1nfZqrgHKiWGsr+Tz1qwtbRh\/P+1giMfMrP8W92gxaHW22q8z+HOjNlU7y6+MDbwWcObMTLhy+wayfp0oO6YP+DYj\/Y6XLX3uF476h4quKk0NAsmCIUYtSJ0Ip1QUQX7IKYTMdCM3t+Xs3sP+dY5dEk0L+pAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-forms-multiple_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022201.10091743119\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWhile working on \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Forms\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Avris Forms v4.0\u003C\/a\u003E, I\u2019ve decided to migrate some code from \u003Ca href=\u0022http:\/\/coffeescript.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E CoffeScript\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/jquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E jQuery\u003C\/a\u003E to \u003Ca href=\u0022http:\/\/vanilla-js.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Vanilla JS\u003C\/a\u003E. And I guess it might be a good idea to share this transition \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-forms-multiple_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022654\u0022 height=\u0022274\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAPCAYAAACMa21tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB5klEQVRIib2VTW4TQRCFv+rpiRMyDnISLyEcACkhXAEuAVsuxQk4AogFSNkgWLIFkVVAiW1kouD58XQXi\/H4D409YxHeZko93VWvq15VS5ymygrI5KsKIov2yoMbwgrCoD8gsIY8dwTWgiqdTmcSXFHVKZESegtsjDFYADFCnueIGARwqihFdkSEb1+\/cH1zw\/5Bl6P799Y67l1d8uPyijwbc\/r4tBEpiZPVJQOmGWqK8lK1yYhgq4\/M3JXaMcasdeq9R4Gg5l738RPu7Axz8gj79AlWKq8w+2HE0B\/0iKI92tFuZYDcOdJ0TBiGDIdDRAzdw\/3K\/Wk2Ri++Q6+PPz9HBCQpu6xMSFkdma1536RkUnRgnTKLIKMROvyFtCOk3UbiNFs4KUw6aEpON9ZQU4gY7HL\/6l8GGCMkSUJrq4W1ttKh844sG2PDkDRJCIKAne3tyv25c+Sv3+DevcecHBM+f7asobk6LVGM4wRrLVaqCQUmILCTm6jHe1nfZqrgHKiWGsr+Tz1qwtbRh\/P+1giMfMrP8W92gxaHW22q8z+HOjNlU7y6+MDbwWcObMTLhy+wayfp0oO6YP+DYj\/Y6XLX3uF476h4quKk0NAsmCIUYtSJ0Ip1QUQX7IKYTMdCM3t+Xs3sP+dY5dEk0L+pAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-forms-multiple_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022654\u0022 height=\u0022274\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWhile working on \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Forms\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Avris Forms v4.0\u003C\/a\u003E, I\u2019ve decided to migrate some code from \u003Ca href=\u0022http:\/\/coffeescript.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E CoffeScript\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/jquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E jQuery\u003C\/a\u003E to \u003Ca href=\u0022http:\/\/vanilla-js.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Vanilla JS\u003C\/a\u003E. And I guess it might be a good idea to share this transition \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EThe code handles the form widget visible in the screenshot above. More specifically: those buttons in the right column. Clicking on the green one adds a new element\/row based on a template hidden inside a \u003Ccode\u003E\u0026lt;script\u0026gt;\u003C\/code\u003E tag. Clicking on a red button results in removal of the current row (after asking for a confirmation).\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E$(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027body\u0027\u003C\/span\u003E).on \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027click\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple-add\u0027\u003C\/span\u003E, -\u0026gt;\n  $form = $(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E).parents(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple\u0027\u003C\/span\u003E)\n  newIndices = $form.find(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027[data-index^=new]\u0027\u003C\/span\u003E).map((i, el) -\u0026gt; el.dataset[\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027index\u0027\u003C\/span\u003E].substr(\u003Cspan class=\u0022hljs-number\u0022\u003E3\u003C\/span\u003E)).get()\n  newIndex = \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E newIndices.length then \u003Cspan class=\u0022hljs-built_in\u0022\u003EMath\u003C\/span\u003E.max.apply(\u003Cspan class=\u0022hljs-literal\u0022\u003Enull\u003C\/span\u003E, newIndices) + \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eelse\u003C\/span\u003E \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E\n  $template = $($form.find(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple-add-template\u0027\u003C\/span\u003E).html().replace(\u003Cspan class=\u0022hljs-regexp\u0022\u003E\/%i%\/g\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027new\u0027\u003C\/span\u003E + newIndex))\n  $(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E).parents(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027tr\u0027\u003C\/span\u003E).before $template\n  $template.find(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027:input:enabled:visible:first\u0027\u003C\/span\u003E).focus()\n\n$(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027body\u0027\u003C\/span\u003E).on \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027click\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple-remove\u0027\u003C\/span\u003E, -\u0026gt;\n  \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-literal\u0022\u003Efalse\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E !confirm(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Are you sure?\u0027\u003C\/span\u003E))\n  $(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E).parents(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027tr\u0027\u003C\/span\u003E).remove()\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIt was not a part of the library (as the library was supposed to only provide PHP), instead each project included this part on its own. Which led to code duplication (and the worst kind: between projects) and also kinda prevented me from abandoning CoffeeScript in newer projects, even if I wanted to. \u003C\/p\u003E\n\u003Cp\u003EAnd I did want to, because JavaScript has matured as a language over the last years. An additional level of complexity in my projects simply wasn\u2019t necessary anymore. CoffeeScript did a great job of making fontend scripting bearable, but now it\u2019s slowly time for it to get a deserved retirement.\u003C\/p\u003E\n\u003Cp\u003ESo I\u2019ve decided to integrate the frontend part into the library. Except I shouldn\u2019t be forcing users to use CoffeeScript or jQuery, it should just work out of the box in any project.\u003C\/p\u003E\n\u003Cp\u003ESince CoffeeScript compiles into JS (although usually with from some unnecessary returns and similar features), getting rid of it is really simple. After using \u003Ca href=\u0022http:\/\/js2.coffee\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E js2coffee\u003C\/a\u003E or \u003Ca href=\u0022http:\/\/decaffeinate-project.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E decaffeinate\u003C\/a\u003E we would end up with something like this:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E$(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027body\u0027\u003C\/span\u003E).on(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027click\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple-add\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003E\u003C\/span\u003E) \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E $form, $template, newIndex, newIndices;\n    $form = $(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E).parents(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple\u0027\u003C\/span\u003E);\n    newIndices = $form.find(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027[data-index^=new]\u0027\u003C\/span\u003E).map(\u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003Ei, el\u003C\/span\u003E) \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E el.dataset[\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027index\u0027\u003C\/span\u003E].substr(\u003Cspan class=\u0022hljs-number\u0022\u003E3\u003C\/span\u003E);\n    }).get();\n    newIndex = newIndices.length ? \u003Cspan class=\u0022hljs-built_in\u0022\u003EMath\u003C\/span\u003E.max.apply(\u003Cspan class=\u0022hljs-literal\u0022\u003Enull\u003C\/span\u003E, newIndices) + \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E : \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E;\n    $template = $($form.find(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple-add-template\u0027\u003C\/span\u003E).html().replace(\u003Cspan class=\u0022hljs-regexp\u0022\u003E\/%i%\/g\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027new\u0027\u003C\/span\u003E + newIndex));\n    $(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E).parents(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027tr\u0027\u003C\/span\u003E).before($template);\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $template.find(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027:input:enabled:visible:first\u0027\u003C\/span\u003E).focus();\n});\n\n$(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027body\u0027\u003C\/span\u003E).on(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027click\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple-remove\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003E\u003C\/span\u003E) \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!confirm(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Are you sure?\u0027\u003C\/span\u003E)) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-literal\u0022\u003Efalse\u003C\/span\u003E;\n    }\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E).parents(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027tr\u0027\u003C\/span\u003E).remove();\n});\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ERemoving the dependency on jQuery is more tricky.\u003C\/p\u003E\n\u003Cp\u003EThere are some \u003Ca href=\u0022http:\/\/youmightnotneedjquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E nice lists\u003C\/a\u003E that show you how to replace some jQuery usage with plain JS. Those Javascript versions used to be longer, more complicated and require some browser-specific checks and adjustments. Those times are almost over though (as you can see from the list), so the need for jQuery gets smaller and smaller.\u003C\/p\u003E\n\u003Cp\u003EReplacing those calls from the list with Vanilla JS\u2019s counterparts was not enough in my case. I needed two functionalities more: finding an element\u2019s parent by a selector (\u003Ccode\u003E$el.parents(\u0027.foo\u0027)\u003C\/code\u003E) and binding an event listener to elements matching a selector, even if those elements don\u2019t exist yet at the moment of binding (\u003Ccode\u003E$(\u0027body\u0027).on(\u0027click\u0027, \u0027.foo\u0027, =\u0026gt; ... )\u003C\/code\u003E).\u003C\/p\u003E\n\u003Cp\u003EThey were surprisingly easy to implement:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E findParent = \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003Eel, selector\u003C\/span\u003E) \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Edo\u003C\/span\u003E {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (el.matches(selector)) {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E el;\n        }\n        el = el.parentNode;\n    } \u003Cspan class=\u0022hljs-keyword\u0022\u003Ewhile\u003C\/span\u003E (el \u0026amp;\u0026amp; el.matches);\n};\n\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E on = \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E (\u003Cspan class=\u0022hljs-params\u0022\u003Eselector, event, handler\u003C\/span\u003E) \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-built_in\u0022\u003Edocument\u003C\/span\u003E.addEventListener(event, \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E (\u003Cspan class=\u0022hljs-params\u0022\u003Ee\u003C\/span\u003E) \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E match = findParent(e.target, selector);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (match) {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E result = handler.apply(match, [e]);\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (result === \u003Cspan class=\u0022hljs-literal\u0022\u003Efalse\u003C\/span\u003E) {\n                e.preventDefault();\n                e.stopPropagation();\n            }\n        }\n    });\n};\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWith those two helpers I could transform my code to this vanilla JavaScript:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003Eon(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple-add\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027click\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E (\u003Cspan class=\u0022hljs-params\u0022\u003E\u003C\/span\u003E) \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E form = findParent(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple\u0027\u003C\/span\u003E);\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!form) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E newIndices = \u003Cspan class=\u0022hljs-built_in\u0022\u003EArray\u003C\/span\u003E.from(form.querySelectorAll(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027[data-index^=new]\u0027\u003C\/span\u003E)).map(\u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E (\u003Cspan class=\u0022hljs-params\u0022\u003Eel\u003C\/span\u003E) \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E el.dataset[\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027index\u0027\u003C\/span\u003E].substr(\u003Cspan class=\u0022hljs-number\u0022\u003E3\u003C\/span\u003E);\n    });\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E newIndex = newIndices.length ? \u003Cspan class=\u0022hljs-built_in\u0022\u003EMath\u003C\/span\u003E.max.apply(\u003Cspan class=\u0022hljs-literal\u0022\u003Enull\u003C\/span\u003E, newIndices) + \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E : \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E template = form.querySelector(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple-add-template\u0027\u003C\/span\u003E).innerHTML.replace(\u003Cspan class=\u0022hljs-regexp\u0022\u003E\/%i%\/g\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027new\u0027\u003C\/span\u003E + newIndex);\n\n    findParent(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027tr\u0027\u003C\/span\u003E).insertAdjacentHTML(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027beforebegin\u0027\u003C\/span\u003E, template);\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E firstInput = form.querySelector(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027[data-index=new\u0027\u003C\/span\u003E+newIndex+\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027] :enabled\u0027\u003C\/span\u003E);\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (firstInput) {\n        firstInput.focus();\n    }\n});\n\non(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.form-multiple-remove\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027click\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E (\u003Cspan class=\u0022hljs-params\u0022\u003E\u003C\/span\u003E) \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!confirm(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Are you sure?\u0027\u003C\/span\u003E)) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-literal\u0022\u003Efalse\u003C\/span\u003E;\n    }\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E row = findParent(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027tr\u0027\u003C\/span\u003E);\n    row.parentNode.removeChild(row);\n});\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ENot bad, is it? \ud83d\ude09\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["coffeescript","javascript","jquery","js","programming","vanilla"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-forms-multiple_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-forms-multiple_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-forms-multiple_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022100.5504587156\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWhile working on \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Forms\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Avris Forms v4.0\u003C\/a\u003E, I\u2019ve decided to migrate some code from \u003Ca href=\u0022http:\/\/coffeescript.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E CoffeScript\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/jquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E jQuery\u003C\/a\u003E to \u003Ca href=\u0022http:\/\/vanilla-js.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Vanilla JS\u003C\/a\u003E. And I guess it might be a good idea to share this transition \ud83d\ude09\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-forms-multiple_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-forms-multiple_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022100.5504587156\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWhile working on \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Forms\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Avris Forms v4.0\u003C\/a\u003E, I\u2019ve decided to migrate some code from \u003Ca href=\u0022http:\/\/coffeescript.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E CoffeScript\u003C\/a\u003E with \u003Ca href=\u0022https:\/\/jquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E jQuery\u003C\/a\u003E to \u003Ca href=\u0022http:\/\/vanilla-js.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Vanilla JS\u003C\/a\u003E. And I guess it might be a good idea to share this transition \ud83d\ude09\u003C\/p\u003E\n\u003Cp\u003EThe code handles the form widget visible in the screenshot above. More specifically: those buttons in the right column. Clicking on the green one adds a new element\/row based on a template hidden inside a \u003Ccode\u003E\u0026lt;script\u0026gt;\u003C\/code\u003E tag. Clicking on a red button results in removal of the current row (after asking for a confirmation).\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003E$(\u0027body\u0027).on \u0027click\u0027, \u0027.form-multiple-add\u0027, -\u0026gt;\n  $form = $(this).parents(\u0027.form-multiple\u0027)\n  newIndices = $form.find(\u0027[data-index^=new]\u0027).map((i, el) -\u0026gt; el.dataset[\u0027index\u0027].substr(3)).get()\n  newIndex = if newIndices.length then Math.max.apply(null, newIndices) + 1 else 0\n  $template = $($form.find(\u0027.form-multiple-add-template\u0027).html().replace(\/%i%\/g, \u0027new\u0027 + newIndex))\n  $(this).parents(\u0027tr\u0027).before $template\n  $template.find(\u0027:input:enabled:visible:first\u0027).focus()\n\n$(\u0027body\u0027).on \u0027click\u0027, \u0027.form-multiple-remove\u0027, -\u0026gt;\n  return false if !confirm(\u0027Are you sure?\u0027))\n  $(this).parents(\u0027tr\u0027).remove()\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIt was not a part of the library (as the library was supposed to only provide PHP), instead each project included this part on its own. Which led to code duplication (and the worst kind: between projects) and also kinda prevented me from abandoning CoffeeScript in newer projects, even if I wanted to. \u003C\/p\u003E\n\u003Cp\u003EAnd I did want to, because JavaScript has matured as a language over the last years. An additional level of complexity in my projects simply wasn\u2019t necessary anymore. CoffeeScript did a great job of making fontend scripting bearable, but now it\u2019s slowly time for it to get a deserved retirement.\u003C\/p\u003E\n\u003Cp\u003ESo I\u2019ve decided to integrate the frontend part into the library. Except I shouldn\u2019t be forcing users to use CoffeeScript or jQuery, it should just work out of the box in any project.\u003C\/p\u003E\n\u003Cp\u003ESince CoffeeScript compiles into JS (although usually with from some unnecessary returns and similar features), getting rid of it is really simple. After using \u003Ca href=\u0022http:\/\/js2.coffee\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E js2coffee\u003C\/a\u003E or \u003Ca href=\u0022http:\/\/decaffeinate-project.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E decaffeinate\u003C\/a\u003E we would end up with something like this:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003E$(\u0027body\u0027).on(\u0027click\u0027, \u0027.form-multiple-add\u0027, function() {\n    var $form, $template, newIndex, newIndices;\n    $form = $(this).parents(\u0027.form-multiple\u0027);\n    newIndices = $form.find(\u0027[data-index^=new]\u0027).map(function(i, el) {\n        return el.dataset[\u0027index\u0027].substr(3);\n    }).get();\n    newIndex = newIndices.length ? Math.max.apply(null, newIndices) + 1 : 0;\n    $template = $($form.find(\u0027.form-multiple-add-template\u0027).html().replace(\/%i%\/g, \u0027new\u0027 + newIndex));\n    $(this).parents(\u0027tr\u0027).before($template);\n    return $template.find(\u0027:input:enabled:visible:first\u0027).focus();\n});\n\n$(\u0027body\u0027).on(\u0027click\u0027, \u0027.form-multiple-remove\u0027, function() {\n    if (!confirm(\u0027Are you sure?\u0027)) {\n        return false;\n    }\n    return $(this).parents(\u0027tr\u0027).remove();\n});\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ERemoving the dependency on jQuery is more tricky.\u003C\/p\u003E\n\u003Cp\u003EThere are some \u003Ca href=\u0022http:\/\/youmightnotneedjquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E nice lists\u003C\/a\u003E that show you how to replace some jQuery usage with plain JS. Those Javascript versions used to be longer, more complicated and require some browser-specific checks and adjustments. Those times are almost over though (as you can see from the list), so the need for jQuery gets smaller and smaller.\u003C\/p\u003E\n\u003Cp\u003EReplacing those calls from the list with Vanilla JS\u2019s counterparts was not enough in my case. I needed two functionalities more: finding an element\u2019s parent by a selector (\u003Ccode\u003E$el.parents(\u0027.foo\u0027)\u003C\/code\u003E) and binding an event listener to elements matching a selector, even if those elements don\u2019t exist yet at the moment of binding (\u003Ccode\u003E$(\u0027body\u0027).on(\u0027click\u0027, \u0027.foo\u0027, =\u0026gt; ... )\u003C\/code\u003E).\u003C\/p\u003E\n\u003Cp\u003EThey were surprisingly easy to implement:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003Evar findParent = function(el, selector) {\n    do {\n        if (el.matches(selector)) {\n            return el;\n        }\n        el = el.parentNode;\n    } while (el \u0026amp;\u0026amp; el.matches);\n};\n\nvar on = function (selector, event, handler) {\n    document.addEventListener(event, function (e) {\n        var match = findParent(e.target, selector);\n        if (match) {\n            var result = handler.apply(match, [e]);\n            if (result === false) {\n                e.preventDefault();\n                e.stopPropagation();\n            }\n        }\n    });\n};\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWith those two helpers I could transform my code to this vanilla JavaScript:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003Eon(\u0027.form-multiple-add\u0027, \u0027click\u0027, function () {\n    var form = findParent(this, \u0027.form-multiple\u0027);\n    if (!form) {\n        return;\n    }\n\n    var newIndices = Array.from(form.querySelectorAll(\u0027[data-index^=new]\u0027)).map(function (el) {\n        return el.dataset[\u0027index\u0027].substr(3);\n    });\n    var newIndex = newIndices.length ? Math.max.apply(null, newIndices) + 1 : 0;\n\n    var template = form.querySelector(\u0027.form-multiple-add-template\u0027).innerHTML.replace(\/%i%\/g, \u0027new\u0027 + newIndex);\n\n    findParent(this, \u0027tr\u0027).insertAdjacentHTML(\u0027beforebegin\u0027, template);\n\n    var firstInput = form.querySelector(\u0027[data-index=new\u0027+newIndex+\u0027] :enabled\u0027);\n    if (firstInput) {\n        firstInput.focus();\n    }\n});\n\non(\u0027.form-multiple-remove\u0027, \u0027click\u0027, function () {\n    if (!confirm(\u0027Are you sure?\u0027)) {\n        return false;\n    }\n    var row = findParent(this, \u0027tr\u0027);\n    row.parentNode.removeChild(row);\n});\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ENot bad, is it? \ud83d\ude09\u003C\/p\u003E","words":731,"readTime":3,"lang":"en"}}},"blog\/technology\/immutable-and-stateless":{"key":"blog\/technology\/immutable-and-stateless","type":"article","published":true,"meta":{"createdAt":"2018-01-14T13:35:17+01:00","publishedAt":"2018-01-14T13:24:00+01:00","group":null,"category":"blog","subcategory":"technology","slug":"immutable-and-stateless"},"content":{"en":{"slug":"immutable-and-stateless","title":"On the importance of immutability and statelessness","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mutants-everywhere_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022261.6\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAATCAYAAAD4f6+NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGxklEQVRIiVWW229cVxXGf\/syZ+bMzRPbsV3bgSRtcJrUJSmJklaNiihUDRJEPCFFPMCfAOIf4IV\/AnjgAQlaxAM88YD6kFBoGhTSNL0kdhw7Tnyb8XjuZ+bsvRcPZ5KSLR1t6eyzz\/7W9631ra1+\/tOrgjbklPB0GGOwVpHTCgigAAGFotlNCCFA9op8FJGmKSJCCIGeA2U0RaPZSDXFWhlr7bM9z\/aKjOdAGI54tdDGGo0FQYKAeQpHCMHjUkXQGmMURgkiQv9gn5\/88lfkcjnW1tao1\/c4\/fLLrK6u0my1uXjxInfu3GFhYYFiscgf3nufg1H\/\/w7\/KmgRQSmFCAQUMgZns\/CzoZSi1UvQKgAKRKGV4HotSp0Gc7Fm89Emy68uZ5GKsLb2AOcc09PTzMzM8GRzk+BSUJpvnDjBjbu3nwPyPDvyjOkgCoVC\/eJnV0WUEOfyGA31To\/D1SIiCuc9Adj6z8dcPj3Di0dm+PNmQOVrDIKnWi6ROs9olIKGfD6msX9AMc4zUZtgtd4mRBpjDAgEGcsVBJAxK0I68pyKWhQN6AylQquMIaUUSPZ5ECG4wIXT83x9NkaXy7w9q4mTA6oGSLow7JOXlJI4zKBNhOAHCeFgl3w4QLJTCYRMCxEmCajE81QIACcKUYL2IeA8pM7jQgBRGXbJHlGwdHye+Tii0mkwbTxT2meAg4BLmPQ9nBsihHHkgsPQkeozmV5yq0Qu4QUTeG0KTsQpIfWZbApSCYh4NKIgCE403glBAl7CM10Ryz82Ax0xxHGOraFnJxHGZ3Nh2vLdF0ucKsaEp4GMZxGVVZ8IT5ij1O5yugyDRpdSeQqJFBKyAEaiUaLRZIUNAbwIPgSC13j\/VeKJMnzYNAxGjtlIUauWcAS8CJPGQxihGRKbCBAW5w2VqZhKZewXwEDHTE1ZGp0uaZzjk539p0soBT4oPKC9ypgQIHhFCJqhCzgRfBACPlNPR9xYb\/LH21tsp2H8J8NKP8fSfJmlmsP1PGcWylg7pGn3oJNgySzj3eM13l5a4H4HPmob0kIOJdmaljFTItjMgDxBMupEhGHq0U4Q0WjxLB+bIHnwBWbUot32xNOevFbUKjX+vd3i0Z92aLoehSNFGjVDt5iw8kGf7y8d581XjnL9yRaXFiI+uPWQYa5AMIaKdJgMe6zqYyhgKJkBWCUhY2DMXzkuYIxGkRlXjKOxepNoeoF7TxocmnRsbt9j4dwMcXHEt0\/Mcrh8nJmJdb7cesLtVov6ukb3hW6nR82khNJj1pqOh\/UBJg3kfEoinj2pkJdWVv5qhBQ0Nku8kGW7ZLCc98+qYzY6oD2oc\/1akx9\/Z4l7Dzaoql0kLJAUO7T1SWrlGmv3P8T\/bYXcleOoVkSlZHjv+mcMvUJXNH+V++z0PdpX0UEjIngUmhEiQrmsKeQN9jk7zxJjXCEZQzXaLJ54iXe\/d4qVtRW0KTOyMWpfsTvoMXfmSxruHsm0YeXk12hcM1RLFeJqzJsXjnJ39yF6FwJl9NjjApmdCJ4yPVJdYm7C0h0OsSIpzo1QPsk6ShA0CvCgFMq0KOQOcfvOXfoHj5BkhJUqYb\/ByJZQe5ajySFa\/RrDfJ\/dgx0+vf8YZSrUJg+olLsIYAjjBg0Yi40UPk2ZtNsMmEJGFeyohY3q97DiMEpnGxXkxvaEhjvNFrWtzxlJRBTlODdT4v3P+ixXE+7vDdj+LOa\/7W0e7LVZ32vR6vYo5fO8cXKRnE+Ik2HW0WXMvoJgI8IQckFIUFAYUm9oGPawc3lw2KzzAnpxmTRotNYko4Tlo9Ns7rTp1g\/o2grNXIHjFwy+lmfYuIaeP8ZGe4MwUeT10+fY32\/S7fYpz0+gkoQgQqVSxVpLr9fD5iMmymW2d7eR3gHS2kIPEqxN8Ah24D0SFAoICt5450e88tr58fWiThSGhOkWxwoxly9f5je\/\/R1TJcs3L1zik49vcekHV5ldukehUGBxcYGd3V0erW9w5swZPv\/ic86dO8\/Ozg5nz57l5s2brKyscOXKFW7c+Ih\/\/uX3xDZrvBow1mJzWhF0xo4RxcbGBvHEJPV6HWs0Sb+DMpbDhw+zvr7OcDgiUSnOOaZmZuj1uvjRiK3mPnNzs+zt7LI4fYg7t24yWZtga2ubBw9WmZqaIkkSclqzt7tHCILN5TBGgxgMDq0C6tc\/XBaR7O4jGlr9IaDRCspxIM4P+PSxodNpMj\/zAjfak7x1xGHSNnkMJop56\/Vv8fe7W\/S2H\/PO+SUqk4f512qf5uoNnAiozPVVEEx1GlOu4ZyjEOXIWwMiuKRLVK7yP6sQ4wkEHMxKAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/mutants-everywhere_small.jpg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022261.6\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKeeping your classes \u003Cstrong\u003Eimmutable and stateless\u003C\/strong\u003E makes your code \u003Cem\u003Eway\u003C\/em\u003E less prone to bugs. Yet somehow this clean code rule isn\u2019t as popular and as often invoked as\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Single_responsibility_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E SRP\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/You_aren%27t_gonna_need_it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E YAGNI\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Don%27t_repeat_yourself\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DRY\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/KISS_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E KISS\u003C\/a\u003E\nand others... Maybe it\u2019s because of the lack of a catchy acronym?\u003C\/p\u003E\n\u003Cp\u003EAnyways, I\u2019d like to take a look at two examples of when sticking to this rule could save your ass (or at least save you some time debugging).\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/mutants-everywhere_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022600\u0022 height=\u0022327\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAATCAYAAAD4f6+NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGxklEQVRIiVWW229cVxXGf\/syZ+bMzRPbsV3bgSRtcJrUJSmJklaNiihUDRJEPCFFPMCfAOIf4IV\/AnjgAQlaxAM88YD6kFBoGhTSNL0kdhw7Tnyb8XjuZ+bsvRcPZ5KSLR1t6eyzz\/7W9631ra1+\/tOrgjbklPB0GGOwVpHTCgigAAGFotlNCCFA9op8FJGmKSJCCIGeA2U0RaPZSDXFWhlr7bM9z\/aKjOdAGI54tdDGGo0FQYKAeQpHCMHjUkXQGmMURgkiQv9gn5\/88lfkcjnW1tao1\/c4\/fLLrK6u0my1uXjxInfu3GFhYYFiscgf3nufg1H\/\/w7\/KmgRQSmFCAQUMgZns\/CzoZSi1UvQKgAKRKGV4HotSp0Gc7Fm89Emy68uZ5GKsLb2AOcc09PTzMzM8GRzk+BSUJpvnDjBjbu3nwPyPDvyjOkgCoVC\/eJnV0WUEOfyGA31To\/D1SIiCuc9Adj6z8dcPj3Di0dm+PNmQOVrDIKnWi6ROs9olIKGfD6msX9AMc4zUZtgtd4mRBpjDAgEGcsVBJAxK0I68pyKWhQN6AylQquMIaUUSPZ5ECG4wIXT83x9NkaXy7w9q4mTA6oGSLow7JOXlJI4zKBNhOAHCeFgl3w4QLJTCYRMCxEmCajE81QIACcKUYL2IeA8pM7jQgBRGXbJHlGwdHye+Tii0mkwbTxT2meAg4BLmPQ9nBsihHHkgsPQkeozmV5yq0Qu4QUTeG0KTsQpIfWZbApSCYh4NKIgCE403glBAl7CM10Ryz82Ax0xxHGOraFnJxHGZ3Nh2vLdF0ucKsaEp4GMZxGVVZ8IT5ij1O5yugyDRpdSeQqJFBKyAEaiUaLRZIUNAbwIPgSC13j\/VeKJMnzYNAxGjtlIUauWcAS8CJPGQxihGRKbCBAW5w2VqZhKZewXwEDHTE1ZGp0uaZzjk539p0soBT4oPKC9ypgQIHhFCJqhCzgRfBACPlNPR9xYb\/LH21tsp2H8J8NKP8fSfJmlmsP1PGcWylg7pGn3oJNgySzj3eM13l5a4H4HPmob0kIOJdmaljFTItjMgDxBMupEhGHq0U4Q0WjxLB+bIHnwBWbUot32xNOevFbUKjX+vd3i0Z92aLoehSNFGjVDt5iw8kGf7y8d581XjnL9yRaXFiI+uPWQYa5AMIaKdJgMe6zqYyhgKJkBWCUhY2DMXzkuYIxGkRlXjKOxepNoeoF7TxocmnRsbt9j4dwMcXHEt0\/Mcrh8nJmJdb7cesLtVov6ukb3hW6nR82khNJj1pqOh\/UBJg3kfEoinj2pkJdWVv5qhBQ0Nku8kGW7ZLCc98+qYzY6oD2oc\/1akx9\/Z4l7Dzaoql0kLJAUO7T1SWrlGmv3P8T\/bYXcleOoVkSlZHjv+mcMvUJXNH+V++z0PdpX0UEjIngUmhEiQrmsKeQN9jk7zxJjXCEZQzXaLJ54iXe\/d4qVtRW0KTOyMWpfsTvoMXfmSxruHsm0YeXk12hcM1RLFeJqzJsXjnJ39yF6FwJl9NjjApmdCJ4yPVJdYm7C0h0OsSIpzo1QPsk6ShA0CvCgFMq0KOQOcfvOXfoHj5BkhJUqYb\/ByJZQe5ajySFa\/RrDfJ\/dgx0+vf8YZSrUJg+olLsIYAjjBg0Yi40UPk2ZtNsMmEJGFeyohY3q97DiMEpnGxXkxvaEhjvNFrWtzxlJRBTlODdT4v3P+ixXE+7vDdj+LOa\/7W0e7LVZ32vR6vYo5fO8cXKRnE+Ik2HW0WXMvoJgI8IQckFIUFAYUm9oGPawc3lw2KzzAnpxmTRotNYko4Tlo9Ns7rTp1g\/o2grNXIHjFwy+lmfYuIaeP8ZGe4MwUeT10+fY32\/S7fYpz0+gkoQgQqVSxVpLr9fD5iMmymW2d7eR3gHS2kIPEqxN8Ah24D0SFAoICt5450e88tr58fWiThSGhOkWxwoxly9f5je\/\/R1TJcs3L1zik49vcekHV5ldukehUGBxcYGd3V0erW9w5swZPv\/ic86dO8\/Ozg5nz57l5s2brKyscOXKFW7c+Ih\/\/uX3xDZrvBow1mJzWhF0xo4RxcbGBvHEJPV6HWs0Sb+DMpbDhw+zvr7OcDgiUSnOOaZmZuj1uvjRiK3mPnNzs+zt7LI4fYg7t24yWZtga2ubBw9WmZqaIkkSclqzt7tHCILN5TBGgxgMDq0C6tc\/XBaR7O4jGlr9IaDRCspxIM4P+PSxodNpMj\/zAjfak7x1xGHSNnkMJop56\/Vv8fe7W\/S2H\/PO+SUqk4f512qf5uoNnAiozPVVEEx1GlOu4ZyjEOXIWwMiuKRLVK7yP6sQ4wkEHMxKAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/mutants-everywhere_big.jpg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022600\u0022 height=\u0022327\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/makeameme.org\/meme\/mutants-mutants-everywhere-n6biem\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        makeameme.org\/meme\/mutants-mutants-everywhere-n6biem\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKeeping your classes \u003Cstrong\u003Eimmutable and stateless\u003C\/strong\u003E makes your code \u003Cem\u003Eway\u003C\/em\u003E less prone to bugs. Yet somehow this clean code rule isn\u2019t as popular and as often invoked as\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Single_responsibility_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E SRP\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/You_aren%27t_gonna_need_it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E YAGNI\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Don%27t_repeat_yourself\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DRY\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/KISS_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E KISS\u003C\/a\u003E\nand others... Maybe it\u2019s because of the lack of a catchy acronym?\u003C\/p\u003E\n\u003Cp\u003EAnyways, I\u2019d like to take a look at two examples of when sticking to this rule could save your ass (or at least save you some time debugging).\u003C\/p\u003E\n\u003Ch3\u003EDateTime\u003C\/h3\u003E\n\u003Cp\u003EPHP offers a \u003Ccode\u003EDateTime\u003C\/code\u003E object that encapsulates, well, a date and time. And it\u2019s pretty cool: it can parse strings like \u201cnext monday\u201d, it can understand instructions like modify \u201c+1 week midnight\u201d, the standard library offers support for time zones and for iterating over time (like from \u201cnow\u201d to \u201c+1 day\u201d every \u201c+30 minutes\u201d).\u003C\/p\u003E\n\u003Cp\u003EBut there\u2019s a huge catch involved: \u003Ccode\u003EDateTime\u003C\/code\u003E is mutable.\u003C\/p\u003E\n\u003Cp\u003ELet\u2019s say you have a \u003Ccode\u003EUser\u003C\/code\u003E entity:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-comment\u0022\u003E\/**\n * \u003Cspan class=\u0022hljs-doctag\u0022\u003E@ORM\u003C\/span\u003E\\Entity\n * \u003Cspan class=\u0022hljs-doctag\u0022\u003E@ORM\u003C\/span\u003E\\Table\n **\/\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EUser\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-comment\u0022\u003E\/**\n     * \u003Cspan class=\u0022hljs-doctag\u0022\u003E@var\u003C\/span\u003E \\DateTime\n     * \u003Cspan class=\u0022hljs-doctag\u0022\u003E@ORM\u003C\/span\u003E\\Column(type=\u0022datetime\u0022)\n     *\/\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $createdAt;\n\n    \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ many other fields...\u003C\/span\u003E\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003E__construct\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;createdAt = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E \\DateTime();\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EgetCreatedAt\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E: \\\u003Cspan class=\u0022hljs-title\u0022\u003EDateTime\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;createdAt;\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIt looks as if you could be sure that \u003Ccode\u003EcreatedAt\u003C\/code\u003E will be stored in the database as exactly the moment when the entity was first created, right? After all there\u2019s no setter given, so unless you hack around with reflections, there\u2019s no way to modify that value ever again, is there?\u003C\/p\u003E\n\u003Cp\u003EWell, let\u2019s say in your app it\u2019s important to display, how many Sundays have passed since some stuff happened, and one of them is the registration of a given user.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EcountSundays\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E(\\DateTime $datetime)\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003Eint\u003C\/span\u003E\n\u003C\/span\u003E{\n    $datetime-\u0026gt;modify(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027next sunday 23:59:59\u0027\u003C\/span\u003E);\n    $sundays = \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ewhile\u003C\/span\u003E ($datetime \u0026lt; \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E \\DateTime(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027now\u0027\u003C\/span\u003E)) {\n        $sundays++;\n        $datetime-\u0026gt;modify(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027+1 week\u0027\u003C\/span\u003E);\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $sundays;\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAt first glance this code seems fine as well. We get some value, we use it to calculate some other value, and we return the result. But notice that we keep modifying the input data! If you did it with a string, int or an array, the input would not be modified at all (unless explicitly passed as reference, \u003Ccode\u003E\u0026amp;$string\u003C\/code\u003E). But \u003Ccode\u003E\\DateTime\u003C\/code\u003E, although it\u2019s just a simple value wrapped in a class, is a class after all, so it\u2019s always passed by reference.\u003C\/p\u003E\n\u003Cp\u003ESo even though you cannot set \u003Ccode\u003EUser\u003C\/code\u003E\u2019s \u003Ccode\u003EcreatedAt\u003C\/code\u003E to a \u003Cem\u003Edifferent\u003C\/em\u003E object, you can pass that object to some function that will modify the \u003Cem\u003Einside\u003C\/em\u003E of that object. So if you happen to save your \u003Ccode\u003EUser\u003C\/code\u003E entity to the database after its number of Sundays has been calculated, you will end up with all the users having been registered \u003Cem\u003Ein the future\u003C\/em\u003E and constantly changing their registration date.\u003C\/p\u003E\n\u003Cp\u003EIt might be quite difficult to find the source of this bug. After all, there is no setter, and the connection between this date and \u003Ccode\u003EcountSundays\u003C\/code\u003E might not be too obvious \u2013 maybe hidden in a Twig extension or an external library...\u003C\/p\u003E\n\u003Cp\u003EHow to mitigate that? Ideally, use \u003Ca href=\u0022https:\/\/secure.php.net\/manual\/en\/class.datetimeimmutable.php\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u003Ccode\u003EDateTimeImmuttable\u003C\/code\u003E\u003C\/a\u003E, which \u201cbehaves the same as DateTime except it never modifies itself but returns a new object instead\u201d.\u003C\/p\u003E\n\u003Cp\u003EOr if you don\u2019t want to adjust your whole project to use \u003Ccode\u003EDateTimeImmuttable\u003C\/code\u003E, you might instead remember to \u003Ccode\u003Eclone\u003C\/code\u003E a \u003Ccode\u003EDateTime\u003C\/code\u003E variable before passing it anywhere.\u003C\/p\u003E\n\u003Cp\u003EBtw, in the Rust programming language all variables are \u003Ca href=\u0022https:\/\/doc.rust-lang.org\/book\/first-edition\/mutability.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E immutable by default\u003C\/a\u003E \ud83d\ude0d\u003C\/p\u003E\n\u003Ch3\u003EInvoices import\u003C\/h3\u003E\n\u003Cp\u003EI had to work on a code like this recently:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003EinvoiceService = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E InvoiceService\nshop = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Shop\n\ninvoices = shop.loadInvoices\n\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Efor\u003C\/span\u003E each invoice in invoices {\n    invoiceService.saveInvoice(invoice)\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd somewhere inside \u003Ccode\u003EsaveInvoice\u003C\/code\u003E, this function was executed:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ErunSQL\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E(sql)\u003C\/span\u003E \u003C\/span\u003E{\n    result = database_exec(sql)\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E result is \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E {\n        log(database_error)\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Edie\u003C\/span\u003E\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe code was PHP, but it\u2019s such a \u003Ca href=\u0022http:\/\/govnokod.ru\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E govnokod\u003C\/a\u003E that the above pseudocode with ~90% of original logic removed, is the best way to show it without crying...\u003C\/p\u003E\n\u003Cp\u003ESo the problem was: no invoices are generated anymore. Can you see why? If any invoice fails, the script just logs the error and just dies. When it runs again, it tries with the same invoice and dies again, over and over again, never even trying to handle any other invoice.\u003C\/p\u003E\n\u003Cp\u003EThe underlying error was easy to find and reasonably easy to fix. But we wanted to also make that old, shitty code just a tiny bit better \u2013 if one invoice fails, it shouldn\u2019t block all the others anymore.\u003C\/p\u003E\n\u003Cp\u003EInstead of \u003Ccode\u003Edie\u003C\/code\u003E-ing, the \u003Ccode\u003ErunSQL\u003C\/code\u003E would throw an exception. All the other places, where \u003Ccode\u003ErunSQL\u003C\/code\u003E is used, would basically work as they used to (uncaught exception would terminate the script anyway), but on loading the invoices we would just catch the exception and carry on with all the other invoices.\u003C\/p\u003E\n\u003Cp\u003EWhat could possibly go wrong?\u003C\/p\u003E\n\u003Cp\u003EWell, if you do it on Friday, while starting to get a bit sick, and with \u003Ccode\u003EInvoiceService\u003C\/code\u003E class consisting of \u0026gt;1000 lines of messy, overcomplicated code \u2013 a lot can go wrong.\u003C\/p\u003E\n\u003Cp\u003EAll because \u003Ccode\u003EInvoiceService\u003C\/code\u003E is stateful. That means running \u003Ccode\u003EinvoiceService.saveInvoice(invoice)\u003C\/code\u003E might result in different stuff actually being done, depending on the context it was run in. In this case, the class was keeping invoice items (and other stuff) as a private object property \u2013 first loading them from somewhere, then saving to the database, and finally cleaning it up.\u003C\/p\u003E\n\u003Cp\u003EObviously, with the try-catch, the last step wouldn\u2019t be executed. So if \u003Ccode\u003EinvoiceService.saveInvoice(invoice1)\u003C\/code\u003E fails, then \u003Ccode\u003EinvoiceService.saveInvoice(invoice2)\u003C\/code\u003E wouldn\u2019t really save the \u003Ccode\u003Einvoice2\u003C\/code\u003E, as name suggests \u2013 it would load \u003Ccode\u003Einvoice2\u003C\/code\u003E plus some failing items from \u003Ccode\u003Einvoice1\u003C\/code\u003E... The errors pile up, the invoice items accumulate, and we end up with hundreds of invalid (empty) invoices with the last one claiming that someone owes us 1,9 mln \u20ac...\u003C\/p\u003E\n\u003Ch3\u003EAlways immutable and stateless?\u003C\/h3\u003E\n\u003Cp\u003EObviously not. Some types of classes you \u003Cem\u003Eexpect\u003C\/em\u003E to be stateful. What would be the point of a \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Builder_pattern\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Builder\u003C\/a\u003E, if it couldn\u2019t hold an internal state? How to implement \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Event_(computing)\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Events\u003C\/a\u003E elegantly, if they were immutable?\u003C\/p\u003E\n\u003Cp\u003EForm libraries like \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/forms.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony Forms\u003C\/a\u003E or \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Forms\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Avris Forms\u003C\/a\u003E require you to provide getters and setters for your entity \u2013 and it reflects how your database probably works: a user might change their username or avatar, so the programmer shouldn\u2019t \u003Cem\u003Eexpect\u003C\/em\u003E them to be immutable. (Unless you\u2019re using \u003Ca href=\u0022https:\/\/martinfowler.com\/eaaDev\/EventSourcing.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Event Sourcing\u003C\/a\u003E, then good for you!).\u003C\/p\u003E\n\u003Cp\u003EBasically, it\u2019s all about what you would expect from a class, see \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Principle_of_least_astonishment\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Principle of least astonishment\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EA simple data value objects, like \u003Ca href=\u0022https:\/\/secure.php.net\/manual\/en\/class.datetimeimmutable.php\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E date and time\u003C\/a\u003E, or \u003Ca href=\u0022https:\/\/github.com\/moneyphp\/money\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E monetary value\u003C\/a\u003E should consistently represent the same value. Services that offer a method \u003Ccode\u003EhandleFoo(Foo)\u003C\/code\u003E should behave exactly the same for the same \u003Ccode\u003EFoo\u003C\/code\u003E, regardless of when were they triggered.\u003C\/p\u003E\n\u003Cp\u003EEntities though can be mutable in your project, and that\u2019s ok. Builders, by their nature, are mutable, and that\u2019s fine. You can even see that from the methods they provide: \u003Ccode\u003EaddFoo\u003C\/code\u003E etc. suggest you shouldn\u2019t expect immutability from them.\u003C\/p\u003E\n\u003Cp\u003EI think that Rust\u2019s approach should be followed: immutability by default, mutability explicitly declared. In other terms: write immutable classes, unless you can find a good justification for making one mutable.\u003C\/p\u003E\n\u003Cp\u003EAnd when it comes to finding a nice acronym for this rule... how about JAM?\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EJustify All Mutants\u003C\/strong\u003E.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["bug","class","clean code","immutability","immutable","programming","security","stateless","statelessness"],"hasMore":true,"image":"https:\/\/avris.it\/image\/mutants-everywhere_small.jpg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mutants-everywhere_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mutants-everywhere_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022130.8\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKeeping your classes \u003Cstrong\u003Eimmutable and stateless\u003C\/strong\u003E makes your code \u003Cem\u003Eway\u003C\/em\u003E less prone to bugs. Yet somehow this clean code rule isn\u2019t as popular and as often invoked as\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Single_responsibility_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E SRP\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/You_aren%27t_gonna_need_it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E YAGNI\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Don%27t_repeat_yourself\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DRY\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/KISS_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E KISS\u003C\/a\u003E\nand others... Maybe it\u2019s because of the lack of a catchy acronym?\u003C\/p\u003E\n\u003Cp\u003EAnyways, I\u2019d like to take a look at two examples of when sticking to this rule could save your ass (or at least save you some time debugging).\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/mutants-everywhere_big.jpg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/mutants-everywhere_mini.jpg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022130.8\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/makeameme.org\/meme\/mutants-mutants-everywhere-n6biem\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Emakeameme.org\/meme\/mutants-mutants-everywhere-n6biem\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKeeping your classes \u003Cstrong\u003Eimmutable and stateless\u003C\/strong\u003E makes your code \u003Cem\u003Eway\u003C\/em\u003E less prone to bugs. Yet somehow this clean code rule isn\u2019t as popular and as often invoked as\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Single_responsibility_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E SRP\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/You_aren%27t_gonna_need_it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E YAGNI\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Don%27t_repeat_yourself\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DRY\u003C\/a\u003E,\n\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/KISS_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E KISS\u003C\/a\u003E\nand others... Maybe it\u2019s because of the lack of a catchy acronym?\u003C\/p\u003E\n\u003Cp\u003EAnyways, I\u2019d like to take a look at two examples of when sticking to this rule could save your ass (or at least save you some time debugging).\u003C\/p\u003E\n\u003Ch3\u003EDateTime\u003C\/h3\u003E\n\u003Cp\u003EPHP offers a \u003Ccode\u003EDateTime\u003C\/code\u003E object that encapsulates, well, a date and time. And it\u2019s pretty cool: it can parse strings like \u201cnext monday\u201d, it can understand instructions like modify \u201c+1 week midnight\u201d, the standard library offers support for time zones and for iterating over time (like from \u201cnow\u201d to \u201c+1 day\u201d every \u201c+30 minutes\u201d).\u003C\/p\u003E\n\u003Cp\u003EBut there\u2019s a huge catch involved: \u003Ccode\u003EDateTime\u003C\/code\u003E is mutable.\u003C\/p\u003E\n\u003Cp\u003ELet\u2019s say you have a \u003Ccode\u003EUser\u003C\/code\u003E entity:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E\/**\n * @ORM\\Entity\n * @ORM\\Table\n **\/\nclass User\n{\n    \/**\n     * @var \\DateTime\n     * @ORM\\Column(type=\u0022datetime\u0022)\n     *\/\n    private $createdAt;\n\n    \/\/ many other fields...\n\n    public function __construct()\n    {\n        $this-\u0026gt;createdAt = new \\DateTime();\n    }\n\n    public function getCreatedAt(): \\DateTime\n    {\n        return $this-\u0026gt;createdAt;\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIt looks as if you could be sure that \u003Ccode\u003EcreatedAt\u003C\/code\u003E will be stored in the database as exactly the moment when the entity was first created, right? After all there\u2019s no setter given, so unless you hack around with reflections, there\u2019s no way to modify that value ever again, is there?\u003C\/p\u003E\n\u003Cp\u003EWell, let\u2019s say in your app it\u2019s important to display, how many Sundays have passed since some stuff happened, and one of them is the registration of a given user.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic function countSundays(\\DateTime $datetime): int\n{\n    $datetime-\u0026gt;modify(\u0027next sunday 23:59:59\u0027);\n    $sundays = 0;\n\n    while ($datetime \u0026lt; new \\DateTime(\u0027now\u0027)) {\n        $sundays++;\n        $datetime-\u0026gt;modify(\u0027+1 week\u0027);\n    }\n\n    return $sundays;\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAt first glance this code seems fine as well. We get some value, we use it to calculate some other value, and we return the result. But notice that we keep modifying the input data! If you did it with a string, int or an array, the input would not be modified at all (unless explicitly passed as reference, \u003Ccode\u003E\u0026amp;$string\u003C\/code\u003E). But \u003Ccode\u003E\\DateTime\u003C\/code\u003E, although it\u2019s just a simple value wrapped in a class, is a class after all, so it\u2019s always passed by reference.\u003C\/p\u003E\n\u003Cp\u003ESo even though you cannot set \u003Ccode\u003EUser\u003C\/code\u003E\u2019s \u003Ccode\u003EcreatedAt\u003C\/code\u003E to a \u003Cem\u003Edifferent\u003C\/em\u003E object, you can pass that object to some function that will modify the \u003Cem\u003Einside\u003C\/em\u003E of that object. So if you happen to save your \u003Ccode\u003EUser\u003C\/code\u003E entity to the database after its number of Sundays has been calculated, you will end up with all the users having been registered \u003Cem\u003Ein the future\u003C\/em\u003E and constantly changing their registration date.\u003C\/p\u003E\n\u003Cp\u003EIt might be quite difficult to find the source of this bug. After all, there is no setter, and the connection between this date and \u003Ccode\u003EcountSundays\u003C\/code\u003E might not be too obvious \u2013 maybe hidden in a Twig extension or an external library...\u003C\/p\u003E\n\u003Cp\u003EHow to mitigate that? Ideally, use \u003Ca href=\u0022https:\/\/secure.php.net\/manual\/en\/class.datetimeimmutable.php\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u003Ccode\u003EDateTimeImmuttable\u003C\/code\u003E\u003C\/a\u003E, which \u201cbehaves the same as DateTime except it never modifies itself but returns a new object instead\u201d.\u003C\/p\u003E\n\u003Cp\u003EOr if you don\u2019t want to adjust your whole project to use \u003Ccode\u003EDateTimeImmuttable\u003C\/code\u003E, you might instead remember to \u003Ccode\u003Eclone\u003C\/code\u003E a \u003Ccode\u003EDateTime\u003C\/code\u003E variable before passing it anywhere.\u003C\/p\u003E\n\u003Cp\u003EBtw, in the Rust programming language all variables are \u003Ca href=\u0022https:\/\/doc.rust-lang.org\/book\/first-edition\/mutability.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E immutable by default\u003C\/a\u003E \ud83d\ude0d\u003C\/p\u003E\n\u003Ch3\u003EInvoices import\u003C\/h3\u003E\n\u003Cp\u003EI had to work on a code like this recently:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003EinvoiceService = new InvoiceService\nshop = new Shop\n\ninvoices = shop.loadInvoices\n\nfor each invoice in invoices {\n    invoiceService.saveInvoice(invoice)\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd somewhere inside \u003Ccode\u003EsaveInvoice\u003C\/code\u003E, this function was executed:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Efunction runSQL(sql) {\n    result = database_exec(sql)\n    if result is false {\n        log(database_error)\n        die\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EThe code was PHP, but it\u2019s such a \u003Ca href=\u0022http:\/\/govnokod.ru\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E govnokod\u003C\/a\u003E that the above pseudocode with ~90% of original logic removed, is the best way to show it without crying...\u003C\/p\u003E\n\u003Cp\u003ESo the problem was: no invoices are generated anymore. Can you see why? If any invoice fails, the script just logs the error and just dies. When it runs again, it tries with the same invoice and dies again, over and over again, never even trying to handle any other invoice.\u003C\/p\u003E\n\u003Cp\u003EThe underlying error was easy to find and reasonably easy to fix. But we wanted to also make that old, shitty code just a tiny bit better \u2013 if one invoice fails, it shouldn\u2019t block all the others anymore.\u003C\/p\u003E\n\u003Cp\u003EInstead of \u003Ccode\u003Edie\u003C\/code\u003E-ing, the \u003Ccode\u003ErunSQL\u003C\/code\u003E would throw an exception. All the other places, where \u003Ccode\u003ErunSQL\u003C\/code\u003E is used, would basically work as they used to (uncaught exception would terminate the script anyway), but on loading the invoices we would just catch the exception and carry on with all the other invoices.\u003C\/p\u003E\n\u003Cp\u003EWhat could possibly go wrong?\u003C\/p\u003E\n\u003Cp\u003EWell, if you do it on Friday, while starting to get a bit sick, and with \u003Ccode\u003EInvoiceService\u003C\/code\u003E class consisting of \u0026gt;1000 lines of messy, overcomplicated code \u2013 a lot can go wrong.\u003C\/p\u003E\n\u003Cp\u003EAll because \u003Ccode\u003EInvoiceService\u003C\/code\u003E is stateful. That means running \u003Ccode\u003EinvoiceService.saveInvoice(invoice)\u003C\/code\u003E might result in different stuff actually being done, depending on the context it was run in. In this case, the class was keeping invoice items (and other stuff) as a private object property \u2013 first loading them from somewhere, then saving to the database, and finally cleaning it up.\u003C\/p\u003E\n\u003Cp\u003EObviously, with the try-catch, the last step wouldn\u2019t be executed. So if \u003Ccode\u003EinvoiceService.saveInvoice(invoice1)\u003C\/code\u003E fails, then \u003Ccode\u003EinvoiceService.saveInvoice(invoice2)\u003C\/code\u003E wouldn\u2019t really save the \u003Ccode\u003Einvoice2\u003C\/code\u003E, as name suggests \u2013 it would load \u003Ccode\u003Einvoice2\u003C\/code\u003E plus some failing items from \u003Ccode\u003Einvoice1\u003C\/code\u003E... The errors pile up, the invoice items accumulate, and we end up with hundreds of invalid (empty) invoices with the last one claiming that someone owes us 1,9 mln \u20ac...\u003C\/p\u003E\n\u003Ch3\u003EAlways immutable and stateless?\u003C\/h3\u003E\n\u003Cp\u003EObviously not. Some types of classes you \u003Cem\u003Eexpect\u003C\/em\u003E to be stateful. What would be the point of a \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Builder_pattern\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Builder\u003C\/a\u003E, if it couldn\u2019t hold an internal state? How to implement \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Event_(computing)\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Events\u003C\/a\u003E elegantly, if they were immutable?\u003C\/p\u003E\n\u003Cp\u003EForm libraries like \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/forms.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony Forms\u003C\/a\u003E or \u003Ca href=\u0022https:\/\/gitlab.com\/Avris\/Forms\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Avris Forms\u003C\/a\u003E require you to provide getters and setters for your entity \u2013 and it reflects how your database probably works: a user might change their username or avatar, so the programmer shouldn\u2019t \u003Cem\u003Eexpect\u003C\/em\u003E them to be immutable. (Unless you\u2019re using \u003Ca href=\u0022https:\/\/martinfowler.com\/eaaDev\/EventSourcing.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Event Sourcing\u003C\/a\u003E, then good for you!).\u003C\/p\u003E\n\u003Cp\u003EBasically, it\u2019s all about what you would expect from a class, see \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Principle_of_least_astonishment\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Principle of least astonishment\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EA simple data value objects, like \u003Ca href=\u0022https:\/\/secure.php.net\/manual\/en\/class.datetimeimmutable.php\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E date and time\u003C\/a\u003E, or \u003Ca href=\u0022https:\/\/github.com\/moneyphp\/money\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E monetary value\u003C\/a\u003E should consistently represent the same value. Services that offer a method \u003Ccode\u003EhandleFoo(Foo)\u003C\/code\u003E should behave exactly the same for the same \u003Ccode\u003EFoo\u003C\/code\u003E, regardless of when were they triggered.\u003C\/p\u003E\n\u003Cp\u003EEntities though can be mutable in your project, and that\u2019s ok. Builders, by their nature, are mutable, and that\u2019s fine. You can even see that from the methods they provide: \u003Ccode\u003EaddFoo\u003C\/code\u003E etc. suggest you shouldn\u2019t expect immutability from them.\u003C\/p\u003E\n\u003Cp\u003EI think that Rust\u2019s approach should be followed: immutability by default, mutability explicitly declared. In other terms: write immutable classes, unless you can find a good justification for making one mutable.\u003C\/p\u003E\n\u003Cp\u003EAnd when it comes to finding a nice acronym for this rule... how about JAM?\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EJustify All Mutants\u003C\/strong\u003E.\u003C\/p\u003E","words":1181,"readTime":5,"lang":"en"}}},"blog\/technology\/perfect-code-coverage":{"key":"blog\/technology\/perfect-code-coverage","type":"article","published":true,"meta":{"createdAt":"2017-12-25T00:26:11+01:00","publishedAt":"2017-12-25T13:30:00+01:00","group":"mocks","category":"blog","subcategory":"technology","slug":"perfect-code-coverage"},"content":{"en":{"slug":"perfect-code-coverage","title":"Perfect code coverage","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/coverage_small.png\u0022 alt=\u0022100% coverage - feels good!\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022203.90824129142\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAPCAYAAACMa21tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADkklEQVRIibWWXYscRRSGn1Pd1R\/T053t3TXZ3QghaiDoteLdguAvyn\/ywh8RxIg3XngpIoKyH3Eyk5lZp6e7q7qry4tZJ5nNigbMCwUF\/RTn7ToflFhr\/dXVFd57vPeICBsJ4NFaYxxYB3Eo5GnEu1IQBIhzzjvn3lmQt5FSivDvzW3avbF\/V9\/3vHz5EgDnHCcnJ29tSkzX+qpZEUX6jY8rWzFrNwEynbEX3mHyx4SjoyO0DmlbA3iM6pi3c+q6xtU9R\/k9qtUaFSgODg7QOkIp4aK5BGA6nXIcHoMTet\/x8MMHtK1hlGSEjan44acfuXtyQhorYv3qtn6e\/8I3F98C8EHxkC8ffEHt\/+RiYcnyEetVhTWWSyZ89\/x7AB7tfcTx+D1svSbNMlq1Yras8AJf\/fY1AHuUPPn8CVpHWGv5ffYrnW855AjlgdEoAUAHu+lRIgQSXq8AgCjWBOFmr6OIKI4JJHjFoa65iCBQIILWGhWoLcNz4fLyOU+fPkVrTR7toSONUrKpIUHAQ+8ges1THCQcJgcA5NEYPDtrcI7BOeIg3nLjKN9hvBuwtkeFast8+slnWGs5PT0F4Pz8jPRQQyKEfvA0xpIAHg+vFXHjGibN5LqGRiDQdR2iAhBIRgnW2h2uiPMtF2iNBIogVDjvtszZ\/Jz8XsGzZ894\/PgxnRiKaLTJCnjqtSFUslM\/cP2XN+Scw\/sBANMaOtvh\/Zugcw4\/DPhhoLP9DtO3PcYY8jxHKUV+Z4xpWwY\/EIoIRZ4S69vb+2aoJE0I9aYjRYQkTRAr\/8CFiFIkaYTzm1nnPdzfP6EsS8qyxFrLo+OPmV29wJkBaZq1v5jOyfI7uMGjBPbHMSIwDMMmjZvwBNfzqmka0jQFoG0adBSD3OC8p2kNaZrQ9z11XdM7R9PU3D96n+l0SlmWLJdL0jRFRMiyDBmG4ZbE\/L8ahoGqqiiKgqqq0FpT1zXj8RhrLVmWbVlljeHi8pJqvX5nhlarFVmWsVgs0FrT9z3WWrTWtG0LwNnZGefn50jXNn42eYESwXtPURZM51NGaYKIwuNJsozJbEYURwgQxQl39+79JzN1XWOtRSlFURR0XUfTNCRJgjFma9QYQ1EUSNu2vq7rTXCdIsAweMJQcKYmiDMC8XTWMiiNVkLfW1CaIFAMptqMgddeC3EcE8cxAMvlkrIst122WCwoyxIRYT6fs7+\/vz3nvecvzIfJZKZPRaUAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/coverage_small.png\u0022 alt=\u0022100% coverage - feels good!\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022203.90824129142\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHaving 100% of LOC covered by unit tests certainly feels like a great achievement. But beware \u2013 that doesn\u2019t necessarily mean your code is \u003Cem\u003Eperfectly\u003C\/em\u003E covered. Lines of code coverage is a really nice indicator of your app\u2019s stability, but is can also hide some  risks.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/coverage_big.png\u0022 alt=\u0022100% coverage - feels good!\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022407.81648258284\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAPCAYAAACMa21tAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADkklEQVRIibWWXYscRRSGn1Pd1R\/T053t3TXZ3QghaiDoteLdguAvyn\/ywh8RxIg3XngpIoKyH3Eyk5lZp6e7q7qry4tZJ5nNigbMCwUF\/RTn7ToflFhr\/dXVFd57vPeICBsJ4NFaYxxYB3Eo5GnEu1IQBIhzzjvn3lmQt5FSivDvzW3avbF\/V9\/3vHz5EgDnHCcnJ29tSkzX+qpZEUX6jY8rWzFrNwEynbEX3mHyx4SjoyO0DmlbA3iM6pi3c+q6xtU9R\/k9qtUaFSgODg7QOkIp4aK5BGA6nXIcHoMTet\/x8MMHtK1hlGSEjan44acfuXtyQhorYv3qtn6e\/8I3F98C8EHxkC8ffEHt\/+RiYcnyEetVhTWWSyZ89\/x7AB7tfcTx+D1svSbNMlq1Yras8AJf\/fY1AHuUPPn8CVpHWGv5ffYrnW855AjlgdEoAUAHu+lRIgQSXq8AgCjWBOFmr6OIKI4JJHjFoa65iCBQIILWGhWoLcNz4fLyOU+fPkVrTR7toSONUrKpIUHAQ+8ges1THCQcJgcA5NEYPDtrcI7BOeIg3nLjKN9hvBuwtkeFast8+slnWGs5PT0F4Pz8jPRQQyKEfvA0xpIAHg+vFXHjGibN5LqGRiDQdR2iAhBIRgnW2h2uiPMtF2iNBIogVDjvtszZ\/Jz8XsGzZ894\/PgxnRiKaLTJCnjqtSFUslM\/cP2XN+Scw\/sBANMaOtvh\/Zugcw4\/DPhhoLP9DtO3PcYY8jxHKUV+Z4xpWwY\/EIoIRZ4S69vb+2aoJE0I9aYjRYQkTRAr\/8CFiFIkaYTzm1nnPdzfP6EsS8qyxFrLo+OPmV29wJkBaZq1v5jOyfI7uMGjBPbHMSIwDMMmjZvwBNfzqmka0jQFoG0adBSD3OC8p2kNaZrQ9z11XdM7R9PU3D96n+l0SlmWLJdL0jRFRMiyDBmG4ZbE\/L8ahoGqqiiKgqqq0FpT1zXj8RhrLVmWbVlljeHi8pJqvX5nhlarFVmWsVgs0FrT9z3WWrTWtG0LwNnZGefn50jXNn42eYESwXtPURZM51NGaYKIwuNJsozJbEYURwgQxQl39+79JzN1XWOtRSlFURR0XUfTNCRJgjFma9QYQ1EUSNu2vq7rTXCdIsAweMJQcKYmiDMC8XTWMiiNVkLfW1CaIFAMptqMgddeC3EcE8cxAMvlkrIst122WCwoyxIRYT6fs7+\/vz3nvecvzIfJZKZPRaUAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/coverage_big.png\u0022 alt=\u0022100% coverage - feels good!\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022407.81648258284\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHaving 100% of LOC covered by unit tests certainly feels like a great achievement. But beware \u2013 that doesn\u2019t necessarily mean your code is \u003Cem\u003Eperfectly\u003C\/em\u003E covered. Lines of code coverage is a really nice indicator of your app\u2019s stability, but is can also hide some  risks.\u003C\/p\u003E\n\u003Ch3\u003ECyclomatic complexity\u003C\/h3\u003E\n\u003Cp\u003ELet\u2019s say you have simple method to test:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EcalculateStuff\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003Eint\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;debug) {\n        \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ do some stuff\u003C\/span\u003E\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $result;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E;\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EHow many test cases should you write for it? Obviously, two: one to check for a valid output if \u003Ccode\u003Edebug\u003C\/code\u003E is true, and one when it\u2019s false. If you only write one of them, LOC coverage will make it clearly visible that something is missing. But what if your code looks like this?\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EcalculateStuff\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E: \u003Cspan class=\u0022hljs-title\u0022\u003Eint\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;debug ? \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;calculateResult() : \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E;\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EYou still have exactly the same two \u003Cem\u003Elogic paths\u003C\/em\u003E, but only one line of code. Testing any of those paths will result in the entire method being \u201ccovered\u201d.\u003C\/p\u003E\n\u003Cp\u003EAnd what about this code?\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EonException\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E(ExceptionEvent $event)\u003C\/span\u003E:\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (!\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;debug) {\n        $event-\u0026gt;setResponse(\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;renderErrorPage());\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIf you first test the case when \u003Ccode\u003E$debug === false\u003C\/code\u003E, then grab some lunch, and then come back not remembering the details, but seeing a 100% coverage \u2013 will you remember to also test the other case?\u003C\/p\u003E\n\u003Cp\u003ESumming up: having the tests execute every single \u003Cstrong\u003Eline\u003C\/strong\u003E of your code still does not guarantee that all the \u003Cstrong\u003Elogical paths\u003C\/strong\u003E of your class are being executed.\u003C\/p\u003E\n\u003Ch3\u003EMissing assertions\u003C\/h3\u003E\n\u003Cp\u003EAlso: having all the logical paths \u003Cstrong\u003Eexecuted\u003C\/strong\u003E doesn\u2019t necessarily mean you got them \u003Cstrong\u003Etested\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EFoo\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Erun\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($input)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ lots of complex logic\u003C\/span\u003E\n\n        \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ write the result to a file\u003C\/span\u003E\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $output;\n    }\n\n    \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ lots of private methods\u003C\/span\u003E\n}\n\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EFooTest\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ETestCase\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EtestRun\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E\n    \u003C\/span\u003E{\n        $foo = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Foo;\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;assertEquals(\u003Cspan class=\u0022hljs-number\u0022\u003E8\u003C\/span\u003E, $foo-\u0026gt;run(\u003Cspan class=\u0022hljs-number\u0022\u003E123\u003C\/span\u003E));\n        \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ other, similar test cases\u003C\/span\u003E\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIt\u2019s very possible this test will cover every single line of those \u003Ccode\u003Elots of complex logic\u003C\/code\u003E. But what about the side effects? We are writing something to a file after all (a log maybe?). We are testing that the output is correct for a given input, but we forgot to test that the side effects are also working as expected.\u003C\/p\u003E\n\u003Cp\u003EThe nicest would be, of course, to avoid any side effects and code more functional-programming-style, but that might not always be doable easily enough. So the second best thing would be this: don\u2019t trust your coverage, check if what was covered, was also tested.\u003C\/p\u003E\n\u003Ch3\u003ELeaky coverage\u003C\/h3\u003E\n\u003Cp\u003EIt\u2019s virtually impossible to mock \u003Cem\u003Eall\u003C\/em\u003E the dependencies away. Well, ok, it\u2019s \u003Cem\u003Epossible\u003C\/em\u003E, but sometimes it\u2019s more effort than it\u2019s \u003Cem\u003Eworth\u003C\/em\u003E. Most of the time when you\u2019re testing class \u003Ccode\u003EX\u003C\/code\u003E, some lines of classes \u003Ccode\u003EY\u003C\/code\u003E and \u003Ccode\u003EZ\u003C\/code\u003E will also get executed. Usually, it\u2019s harmless. But sometimes it could blow up in your face \u2013 you could get the entire class \u003Ccode\u003EY\u003C\/code\u003E \u201ccovered\u201d without actually testing it. It\u2019s then very tempting to just leave it as it is (100% achieved, why would I even bother?) and very simple to just miss it.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why it\u2019s a great habit to tell the testing framework, what are you testing with this specific case. In \u003Ca href=\u0022https:\/\/phpunit.de\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PHPUnit\u003C\/a\u003E you can do it using the \u003Ccode\u003E@covers\u003C\/code\u003E annotation. If you specify that \u003Ccode\u003EXTest\u003C\/code\u003E \u003Ccode\u003E@covers X\u003C\/code\u003E, PHPUnit will still execute the code of \u003Ccode\u003EY\u003C\/code\u003E and \u003Ccode\u003EZ\u003C\/code\u003E, but will not count that as a coverage of \u003Ccode\u003EY\u003C\/code\u003E and \u003Ccode\u003EZ\u003C\/code\u003E.\u003C\/p\u003E\n\u003Ch3\u003EAchieving 100%\u003C\/h3\u003E\n\u003Cp\u003ELet\u2019s not kid ourselves \u2013 the test cases for more complex applications are never \u003Cem\u003Eperfect\u003C\/em\u003E in the sense of covering every single scenario that your code might run into. It\u2019s just not worth the effort, \u201cgood enough\u201d is usually good enough.\u003C\/p\u003E\n\u003Cp\u003EStill, having high coverage is a good indicator. The higher it is, and the more \u003Cem\u003Emeaningful\u003C\/em\u003E it is (in terms of what I wrote above) \u2013 the safer you can feel when refactoring your code, or modifying it in any other way.\u003C\/p\u003E\n\u003Cp\u003EBut getting to 100% is not easy.\u003C\/p\u003E\n\u003Ch4\u003ETestable code\u003C\/h4\u003E\n\u003Cp\u003EFollow clean code rules and use design patterns. If you repeat yourself (\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Don%27t_repeat_yourself\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DRY\u003C\/a\u003E), you\u2019ll have to repeat the tests as well. If your class has multiple responsibilities (\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Single_responsibility_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E SRP\u003C\/a\u003E), it becomes considerably more difficult to test it. Testing (A+B) together can sometimes be way way harder than testing A + testing B.\u003C\/p\u003E\n\u003Cp\u003EUse \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Inversion_of_control\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E inversion of control\u003C\/a\u003E, like \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E DI\u003C\/a\u003E. If your class creates its dependencies or fetches them as a singleton, it\u2019s almost impossible to reliably mock those dependencies away. If you just pass them in the constructor though \u2013 it\u2019s an easy peasy to just pass a mock instead of an actual object.\u003C\/p\u003E\n\u003Cp\u003EThe simpler your code, the easier it is to test it. When writing tests for \u003Ca href=\u0022\/projects\/micrus-v4\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus\u003C\/a\u003E v4.0, I was surprised how much has my coverage grew not by adding new tests but by removing some not-so-useful, outdated or too complex code.\u003C\/p\u003E\n\u003Ch4\u003EAspectMock\u003C\/h4\u003E\n\u003Cp\u003EThere is a really fancy and clever library for PHP, \u003Ca href=\u0022https:\/\/github.com\/Codeception\/AspectMock\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E AspectMock\u003C\/a\u003E, that uses the power of aspect oriented programming to \u003Cem\u003Emake everything testable\u003C\/em\u003E. Static methods, final classes, global system functions, dependencies created inside of the tested class \u2013 everything. It basically modifies the source code in run-time, letting you do \u003Cem\u003Eanything\u003C\/em\u003E with it.\u003C\/p\u003E\n\u003Cp\u003EAwesome as it may be, I\u2019ve decided to move away from it. Micrus v4.0 doesn\u2019t use it all, even though in v3.0 it was a basis for every single mock. Why?\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s quite an overhead, both in terms of speed and the time spent to configure it (best case scenario is very simple, but as soon as anything is misconfigured, debugging becomes a nightmare).\u003C\/p\u003E\n\u003Cp\u003EBut most importantly: it \u003Cem\u003Elets you get away with ugly code\u003C\/em\u003E. Why would you care about passing the dependencies in the constructor, if AspectMock lets you mock all the anti-patterns you can think of? Why would you care about making your code testable (= simple), if \u003Cem\u003Eeverything is testable\u003C\/em\u003E?\u003C\/p\u003E\n\u003Cp\u003EIf you depend on a legacy code, AspectMock might be your only chance to test some parts of it at all. However, if you\u2019re writing something modern \u2013 I\u2019d recommend avoiding this kind of magic.\u003C\/p\u003E\n\u003Ch4\u003EAlternatives\u003C\/h4\u003E\n\u003Cp\u003EHow to achieve 100% coverage without resolving to AspectMock or similar magic? I\u2019ve got some advice more specific than just SOLID or DI (although they are essential).\u003C\/p\u003E\n\u003Cp\u003EMost importantly: mocking the global functions. That\u2019s the feature for which I was considering staying with AspectMock after all. Then I found \u003Ca href=\u0022https:\/\/marcelog.github.io\/articles\/php_mock_global_functions_for_unit_tests_with_phpunit.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E this article\u003C\/a\u003E, showing how to achieve a similar result without that much overhead. It wasn\u2019t easy to use and re-use though, so I decided to write a solution which is. That\u2019s how \u003Ca href=\u0022\/projects\/avris-functionmock\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Avris FunctionMock\u003C\/a\u003E was born.\u003C\/p\u003E\n\u003Cp\u003EBasically it lets you write something like:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003EFunctionMock::create(\u003Cspan class=\u0022hljs-keyword\u0022\u003E__NAMESPACE__\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027time\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-number\u0022\u003E123456789\u003C\/span\u003E);\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003Eand it will make all the calls to \u003Ccode\u003Etime()\u003C\/code\u003E inside \u003Ccode\u003E__NAMESPACE__\u003C\/code\u003E return \u003Ccode\u003E123456789\u003C\/code\u003E regardless of what the actual time is. You can also use a callback, disable a mock and validate how many times and with what arguments was the mock invoked.\u003C\/p\u003E\n\u003Cp\u003EWhen it comes to the issue of accessing private\/protected methods\/properties (which you shouldn\u2019t do, but sometimes have to), reflections come to the rescue:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$r = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E \\ReflectionProperty(Application::class, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027commands\u0027\u003C\/span\u003E);\n$r-\u0026gt;setAccessible(\u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E);\n$commands = array_keys($r-\u0026gt;getValue($consoleApp));\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;assertEquals([\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027help\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027list\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027test\u0027\u003C\/span\u003E], $commands);\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003Eor\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$r = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E \\ReflectionMethod(FillEnvCommand::class, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027getDefaults\u0027\u003C\/span\u003E);\n$r-\u0026gt;setAccessible(\u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E);\n$defaults = iterator_to_array($r-\u0026gt;invoke($command));\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIf you\u2019re being nice and keep your classes \u003Ccode\u003Efinal\u003C\/code\u003E (to enforce \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Composition_over_inheritance\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Composition over inheritance\u003C\/a\u003E), you should also be nice and make them implement an interface and depend on that interface (\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_inversion_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Dependency inversion principle\u003C\/a\u003E). You can\u2019t mock a final class \u2013 but you can mock that interface.\u003C\/p\u003E\n\u003Cp\u003EAnd when it comes to mocking static methods \u2013 if you need to mock them, you\u2019re doing something wrong. Static methods should be avoided, except for things like factories etc.\u003C\/p\u003E\n\u003Ch3\u003ESumming up\u003C\/h3\u003E\n\u003Cp\u003EHaving high code coverage is nice, but remember it might give you a false feeling of security. Don\u2019t rely simply on that one number. And that\u2019s basically all I wanted to say \ud83d\ude01\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["aspectmock","code","coverage","mock","php","phpunit","programming","tests","unit tests"],"hasMore":true,"image":"https:\/\/avris.it\/image\/coverage_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/coverage_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/coverage_mini.png\u0022 alt=\u0022100% coverage - feels good!\u0022 width=\u0022240\u0022 height=\u0022101.95412064571\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHaving 100% of LOC covered by unit tests certainly feels like a great achievement. But beware \u2013 that doesn\u2019t necessarily mean your code is \u003Cem\u003Eperfectly\u003C\/em\u003E covered. Lines of code coverage is a really nice indicator of your app\u2019s stability, but is can also hide some  risks.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/coverage_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/coverage_mini.png\u0022 alt=\u0022100% coverage - feels good!\u0022 width=\u0022240\u0022 height=\u0022101.95412064571\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EHaving 100% of LOC covered by unit tests certainly feels like a great achievement. But beware \u2013 that doesn\u2019t necessarily mean your code is \u003Cem\u003Eperfectly\u003C\/em\u003E covered. Lines of code coverage is a really nice indicator of your app\u2019s stability, but is can also hide some  risks.\u003C\/p\u003E\n\u003Ch3\u003ECyclomatic complexity\u003C\/h3\u003E\n\u003Cp\u003ELet\u2019s say you have simple method to test:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003Epublic function calculateStuff(): int\n{\n    if ($this-\u0026gt;debug) {\n        \/\/ do some stuff\n        return $result;\n    }\n\n    return 0;\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EHow many test cases should you write for it? Obviously, two: one to check for a valid output if \u003Ccode\u003Edebug\u003C\/code\u003E is true, and one when it\u2019s false. If you only write one of them, LOC coverage will make it clearly visible that something is missing. But what if your code looks like this?\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003Epublic function calculateStuff(): int\n{\n    return $this-\u0026gt;debug ? $this-\u0026gt;calculateResult() : 0;\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EYou still have exactly the same two \u003Cem\u003Elogic paths\u003C\/em\u003E, but only one line of code. Testing any of those paths will result in the entire method being \u201ccovered\u201d.\u003C\/p\u003E\n\u003Cp\u003EAnd what about this code?\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003Epublic function onException(ExceptionEvent $event):\n{\n    if (!$this-\u0026gt;debug) {\n        $event-\u0026gt;setResponse($this-\u0026gt;renderErrorPage());\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIf you first test the case when \u003Ccode\u003E$debug === false\u003C\/code\u003E, then grab some lunch, and then come back not remembering the details, but seeing a 100% coverage \u2013 will you remember to also test the other case?\u003C\/p\u003E\n\u003Cp\u003ESumming up: having the tests execute every single \u003Cstrong\u003Eline\u003C\/strong\u003E of your code still does not guarantee that all the \u003Cstrong\u003Elogical paths\u003C\/strong\u003E of your class are being executed.\u003C\/p\u003E\n\u003Ch3\u003EMissing assertions\u003C\/h3\u003E\n\u003Cp\u003EAlso: having all the logical paths \u003Cstrong\u003Eexecuted\u003C\/strong\u003E doesn\u2019t necessarily mean you got them \u003Cstrong\u003Etested\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003Eclass Foo\n{\n    public function run($input)\n    {\n        \/\/ lots of complex logic\n\n        \/\/ write the result to a file\n\n        return $output;\n    }\n\n    \/\/ lots of private methods\n}\n\nclass FooTest extends TestCase\n{\n    public function testRun()\n    {\n        $foo = new Foo;\n\n        $this-\u0026gt;assertEquals(8, $foo-\u0026gt;run(123));\n        \/\/ other, similar test cases\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIt\u2019s very possible this test will cover every single line of those \u003Ccode\u003Elots of complex logic\u003C\/code\u003E. But what about the side effects? We are writing something to a file after all (a log maybe?). We are testing that the output is correct for a given input, but we forgot to test that the side effects are also working as expected.\u003C\/p\u003E\n\u003Cp\u003EThe nicest would be, of course, to avoid any side effects and code more functional-programming-style, but that might not always be doable easily enough. So the second best thing would be this: don\u2019t trust your coverage, check if what was covered, was also tested.\u003C\/p\u003E\n\u003Ch3\u003ELeaky coverage\u003C\/h3\u003E\n\u003Cp\u003EIt\u2019s virtually impossible to mock \u003Cem\u003Eall\u003C\/em\u003E the dependencies away. Well, ok, it\u2019s \u003Cem\u003Epossible\u003C\/em\u003E, but sometimes it\u2019s more effort than it\u2019s \u003Cem\u003Eworth\u003C\/em\u003E. Most of the time when you\u2019re testing class \u003Ccode\u003EX\u003C\/code\u003E, some lines of classes \u003Ccode\u003EY\u003C\/code\u003E and \u003Ccode\u003EZ\u003C\/code\u003E will also get executed. Usually, it\u2019s harmless. But sometimes it could blow up in your face \u2013 you could get the entire class \u003Ccode\u003EY\u003C\/code\u003E \u201ccovered\u201d without actually testing it. It\u2019s then very tempting to just leave it as it is (100% achieved, why would I even bother?) and very simple to just miss it.\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why it\u2019s a great habit to tell the testing framework, what are you testing with this specific case. In \u003Ca href=\u0022https:\/\/phpunit.de\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PHPUnit\u003C\/a\u003E you can do it using the \u003Ccode\u003E@covers\u003C\/code\u003E annotation. If you specify that \u003Ccode\u003EXTest\u003C\/code\u003E \u003Ccode\u003E@covers X\u003C\/code\u003E, PHPUnit will still execute the code of \u003Ccode\u003EY\u003C\/code\u003E and \u003Ccode\u003EZ\u003C\/code\u003E, but will not count that as a coverage of \u003Ccode\u003EY\u003C\/code\u003E and \u003Ccode\u003EZ\u003C\/code\u003E.\u003C\/p\u003E\n\u003Ch3\u003EAchieving 100%\u003C\/h3\u003E\n\u003Cp\u003ELet\u2019s not kid ourselves \u2013 the test cases for more complex applications are never \u003Cem\u003Eperfect\u003C\/em\u003E in the sense of covering every single scenario that your code might run into. It\u2019s just not worth the effort, \u201cgood enough\u201d is usually good enough.\u003C\/p\u003E\n\u003Cp\u003EStill, having high coverage is a good indicator. The higher it is, and the more \u003Cem\u003Emeaningful\u003C\/em\u003E it is (in terms of what I wrote above) \u2013 the safer you can feel when refactoring your code, or modifying it in any other way.\u003C\/p\u003E\n\u003Cp\u003EBut getting to 100% is not easy.\u003C\/p\u003E\n\u003Ch4\u003ETestable code\u003C\/h4\u003E\n\u003Cp\u003EFollow clean code rules and use design patterns. If you repeat yourself (\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Don%27t_repeat_yourself\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DRY\u003C\/a\u003E), you\u2019ll have to repeat the tests as well. If your class has multiple responsibilities (\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Single_responsibility_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E SRP\u003C\/a\u003E), it becomes considerably more difficult to test it. Testing (A+B) together can sometimes be way way harder than testing A + testing B.\u003C\/p\u003E\n\u003Cp\u003EUse \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Inversion_of_control\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E inversion of control\u003C\/a\u003E, like \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E DI\u003C\/a\u003E. If your class creates its dependencies or fetches them as a singleton, it\u2019s almost impossible to reliably mock those dependencies away. If you just pass them in the constructor though \u2013 it\u2019s an easy peasy to just pass a mock instead of an actual object.\u003C\/p\u003E\n\u003Cp\u003EThe simpler your code, the easier it is to test it. When writing tests for \u003Ca href=\u0022\/projects\/micrus-v4.lite\u0022\u003E Micrus\u003C\/a\u003E v4.0, I was surprised how much has my coverage grew not by adding new tests but by removing some not-so-useful, outdated or too complex code.\u003C\/p\u003E\n\u003Ch4\u003EAspectMock\u003C\/h4\u003E\n\u003Cp\u003EThere is a really fancy and clever library for PHP, \u003Ca href=\u0022https:\/\/github.com\/Codeception\/AspectMock\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E AspectMock\u003C\/a\u003E, that uses the power of aspect oriented programming to \u003Cem\u003Emake everything testable\u003C\/em\u003E. Static methods, final classes, global system functions, dependencies created inside of the tested class \u2013 everything. It basically modifies the source code in run-time, letting you do \u003Cem\u003Eanything\u003C\/em\u003E with it.\u003C\/p\u003E\n\u003Cp\u003EAwesome as it may be, I\u2019ve decided to move away from it. Micrus v4.0 doesn\u2019t use it all, even though in v3.0 it was a basis for every single mock. Why?\u003C\/p\u003E\n\u003Cp\u003EIt\u2019s quite an overhead, both in terms of speed and the time spent to configure it (best case scenario is very simple, but as soon as anything is misconfigured, debugging becomes a nightmare).\u003C\/p\u003E\n\u003Cp\u003EBut most importantly: it \u003Cem\u003Elets you get away with ugly code\u003C\/em\u003E. Why would you care about passing the dependencies in the constructor, if AspectMock lets you mock all the anti-patterns you can think of? Why would you care about making your code testable (= simple), if \u003Cem\u003Eeverything is testable\u003C\/em\u003E?\u003C\/p\u003E\n\u003Cp\u003EIf you depend on a legacy code, AspectMock might be your only chance to test some parts of it at all. However, if you\u2019re writing something modern \u2013 I\u2019d recommend avoiding this kind of magic.\u003C\/p\u003E\n\u003Ch4\u003EAlternatives\u003C\/h4\u003E\n\u003Cp\u003EHow to achieve 100% coverage without resolving to AspectMock or similar magic? I\u2019ve got some advice more specific than just SOLID or DI (although they are essential).\u003C\/p\u003E\n\u003Cp\u003EMost importantly: mocking the global functions. That\u2019s the feature for which I was considering staying with AspectMock after all. Then I found \u003Ca href=\u0022https:\/\/marcelog.github.io\/articles\/php_mock_global_functions_for_unit_tests_with_phpunit.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E this article\u003C\/a\u003E, showing how to achieve a similar result without that much overhead. It wasn\u2019t easy to use and re-use though, so I decided to write a solution which is. That\u2019s how \u003Ca href=\u0022\/projects\/avris-functionmock.lite\u0022\u003E Avris FunctionMock\u003C\/a\u003E was born.\u003C\/p\u003E\n\u003Cp\u003EBasically it lets you write something like:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003EFunctionMock::create(__NAMESPACE__, \u0027time\u0027, 123456789);\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003Eand it will make all the calls to \u003Ccode\u003Etime()\u003C\/code\u003E inside \u003Ccode\u003E__NAMESPACE__\u003C\/code\u003E return \u003Ccode\u003E123456789\u003C\/code\u003E regardless of what the actual time is. You can also use a callback, disable a mock and validate how many times and with what arguments was the mock invoked.\u003C\/p\u003E\n\u003Cp\u003EWhen it comes to the issue of accessing private\/protected methods\/properties (which you shouldn\u2019t do, but sometimes have to), reflections come to the rescue:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$r = new \\ReflectionProperty(Application::class, \u0027commands\u0027);\n$r-\u0026gt;setAccessible(true);\n$commands = array_keys($r-\u0026gt;getValue($consoleApp));\n$this-\u0026gt;assertEquals([\u0027help\u0027, \u0027list\u0027, \u0027test\u0027], $commands);\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003Eor\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E$r = new \\ReflectionMethod(FillEnvCommand::class, \u0027getDefaults\u0027);\n$r-\u0026gt;setAccessible(true);\n$defaults = iterator_to_array($r-\u0026gt;invoke($command));\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EIf you\u2019re being nice and keep your classes \u003Ccode\u003Efinal\u003C\/code\u003E (to enforce \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Composition_over_inheritance\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Composition over inheritance\u003C\/a\u003E), you should also be nice and make them implement an interface and depend on that interface (\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_inversion_principle\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Dependency inversion principle\u003C\/a\u003E). You can\u2019t mock a final class \u2013 but you can mock that interface.\u003C\/p\u003E\n\u003Cp\u003EAnd when it comes to mocking static methods \u2013 if you need to mock them, you\u2019re doing something wrong. Static methods should be avoided, except for things like factories etc.\u003C\/p\u003E\n\u003Ch3\u003ESumming up\u003C\/h3\u003E\n\u003Cp\u003EHaving high code coverage is nice, but remember it might give you a false feeling of security. Don\u2019t rely simply on that one number. And that\u2019s basically all I wanted to say \ud83d\ude01\u003C\/p\u003E","words":1332,"readTime":6,"lang":"en"}}},"blog\/technology\/coder-vs-developer":{"key":"blog\/technology\/coder-vs-developer","type":"article","published":true,"meta":{"createdAt":"2017-09-01T18:30:13+02:00","publishedAt":"2017-09-26T18:29:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"coder-vs-developer"},"content":{"en":{"slug":"coder-vs-developer","title":"Coder vs developer","intro":"\u003Cp\u003EProgramming isn\u2019t that hard. Really. With enough time and determination, \u003Cem\u003Ealmost everybody\u003C\/em\u003E could write some useful code. The Internet is full of tutorials that teach you programming from scratch, full of people who faced the same problems you do, full of people who solved those problems and shared their solutions for you to use, and finally full of free libraries that you can \u003Cem\u003Ejust use\u003C\/em\u003E. All you need to do is learn some tools, google your problems and put together pieces of code that you find.\u003C\/p\u003E\n\u003Cp\u003EBut if it\u2019s not a black magic, not a secret knowledge, then why are software developers \u003Cem\u003Eso\u003C\/em\u003E well paid?\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cp\u003EProgramming isn\u2019t that hard. Really. With enough time and determination, \u003Cem\u003Ealmost everybody\u003C\/em\u003E could write some useful code. The Internet is full of tutorials that teach you programming from scratch, full of people who faced the same problems you do, full of people who solved those problems and shared their solutions for you to use, and finally full of free libraries that you can \u003Cem\u003Ejust use\u003C\/em\u003E. All you need to do is learn some tools, google your problems and put together pieces of code that you find.\u003C\/p\u003E\n\u003Cp\u003EBut if it\u2019s not a black magic, not a secret knowledge, then why are software developers \u003Cem\u003Eso\u003C\/em\u003E well paid?\u003C\/p\u003E\n\u003Cp\u003EIt all comes down to the issue of \u003Cstrong\u003Emaintainability\u003C\/strong\u003E. It\u2019s not that hard to write a script that \u003Cem\u003Eworks\u003C\/em\u003E. But it requires a lot of experience to write something, which \u003Cem\u003Ecan be easily modified\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EProgrammers spend more time reading code than writing it. Seriously. Sometimes we spend the whole day digging through layers of code in search of a root cause of some bug, only to discover that all you need to fix it is to slightly modify a single line of code. (Btw, that\u2019s one of the reasons one shouldn\u2019t pay programmers \u003Ca href=\u0022\/blog\/rewarding-for-loc\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-computer-speaker\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E per line of code\u003C\/a\u003E).\u003C\/p\u003E\n\u003Cp\u003EWhen I look at some code I wrote just four years ago, I\u2019m terrified of it. If I had to modify something non-trivial on that website, I think I would have to get drunk first. It\u2019s a mess. No separation of concerns, no layers of abstraction, sensitive configs in PHP files, templates mixed up the the business logic \u2013 not only is it objectively \u003Cem\u003Eugly\u003C\/em\u003E and \u003Cem\u003Eunreadable\u003C\/em\u003E, but most importantly, it takes a lot of time to understand what the code does, how it does it and how to change it best.\u003C\/p\u003E\n\u003Cp\u003EThere is also a lot of \u003Cstrong\u003Eduplication\u003C\/strong\u003E. I wrote some code to handle a post form in the admin panel. Then copy-pasted it and adjusted to handle an image form. Then the same for a comment form. And some others. Now if I had to change something regarding the form handling generally, I\u2019d have to do it in all of those places (knowing the whole application, and trying not to forget\/miss any of them). If only I had that shared logic separated into any kind of abstraction, I would only have to update that abstraction, so that every form which uses it would just switch to the new version.\u003C\/p\u003E\n\u003Cp\u003EThat code would also cause me trouble regarding \u003Cstrong\u003Ecooperation\u003C\/strong\u003E. Not only because I would be ashamed to share my shitty code with anyone. Mostly because the experience of my shitty code would be even more shitty for someone who didn\u2019t write it. If I had written \u003Ca href=\u0022http:\/\/blog.cleancoder.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E cleaner code\u003C\/a\u003E, followed \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/contributing\/code\/standards.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E styling conventions\u003C\/a\u003E and \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/SOLID_(object-oriented_design)\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E SOLID principles\u003C\/a\u003E, wrote automated tests, used an \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Model%E2%80%93view%E2%80%93controller\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E MVC\u003C\/a\u003E framework \u2013 then every experienced developer could just jump into the project without much preparation, knowing where to look without having to know the whole project. But in case of my shitty code, they would have to suffer through a lot before being able to work on it. Plus, they\u2019d have to know Polish \u2013 for some reason I used it to name some variables and templates... \ud83e\udd26\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why I\u2019m distinguishing between \u003Cstrong\u003Ecoders\u003C\/strong\u003E and \u003Cstrong\u003Edevelopers\u003C\/strong\u003E. When I started working as a programmer, I was just a coder \u2013 I was simply able to write my ideas down as a code, to tell the computer what I want it to do. Over the years I\u2019ve gathered the mindset and the skillset of a developer \u2013 a person that, well, develops a product. From start to end, from the architecture design to unit tests, able to communicate efficiently with others who work on it (developers, project managers, designers etc.), writing a code that\u2019s easy for others to co-create and maintain. Coding is more about knowing a tool, developing is more about the mindset. I\u2019m able to switch to a different framework or a completely different language within a week or two \u2013 because those are just tools.\u003C\/p\u003E\n\u003Cp\u003ESo to sum up: of course you can hire some intern for 10 PLN\/hour \u2013 they will take a month to create something, but if they\u2019re good, they will get shit done and working just fine. However, if you want to maintain this code later, develop your product further, add more people to your team, fix some bugs that came up \u2013 it will take a lot of time, tech debt will rise, bugs will multiply, time needed for testing will become huge. And you could also hire someone for 30 EUR\/hour \u2013 who would create the same functionality in just a week, keeping the code clean, easy to maintain, up-to-date with the newest trends in the field, interoperable and easier to test.\u003C\/p\u003E\n\u003Cp\u003EAnd that\u2019s why I get so pissed when I hear stuff like \u201cmy niece also does websites, she would do it for a lollipop, and you want \u003Cem\u003Emoney\u003C\/em\u003E from me?\u201d or \u201cI had some programming in high school, looks easy, you just google stuff and copy answers from Stack Overflow, how dare you make the money you do!\u201d.\u003C\/p\u003E\n\u003Cp\u003EWell, no. Sure, programming is basically just splitting complex problems into a set of simple instructions, so that even something dumb like a computer can understand and execute them \u2013 in principal it really is easy. But when it comes to doing it \u003Cem\u003Eright\u003C\/em\u003E \u2013 that\u2019s where software development becomes a real challenge.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["coder","developer","logic","maintenance","mindset","programming"],"hasMore":true,"image":null,"introLite":"\u003Cp\u003EProgramming isn\u2019t that hard. Really. With enough time and determination, \u003Cem\u003Ealmost everybody\u003C\/em\u003E could write some useful code. The Internet is full of tutorials that teach you programming from scratch, full of people who faced the same problems you do, full of people who solved those problems and shared their solutions for you to use, and finally full of free libraries that you can \u003Cem\u003Ejust use\u003C\/em\u003E. All you need to do is learn some tools, google your problems and put together pieces of code that you find.\u003C\/p\u003E\n\u003Cp\u003EBut if it\u2019s not a black magic, not a secret knowledge, then why are software developers \u003Cem\u003Eso\u003C\/em\u003E well paid?\u003C\/p\u003E","contentLite":"\u003Cp\u003EProgramming isn\u2019t that hard. Really. With enough time and determination, \u003Cem\u003Ealmost everybody\u003C\/em\u003E could write some useful code. The Internet is full of tutorials that teach you programming from scratch, full of people who faced the same problems you do, full of people who solved those problems and shared their solutions for you to use, and finally full of free libraries that you can \u003Cem\u003Ejust use\u003C\/em\u003E. All you need to do is learn some tools, google your problems and put together pieces of code that you find.\u003C\/p\u003E\n\u003Cp\u003EBut if it\u2019s not a black magic, not a secret knowledge, then why are software developers \u003Cem\u003Eso\u003C\/em\u003E well paid?\u003C\/p\u003E\n\u003Cp\u003EIt all comes down to the issue of \u003Cstrong\u003Emaintainability\u003C\/strong\u003E. It\u2019s not that hard to write a script that \u003Cem\u003Eworks\u003C\/em\u003E. But it requires a lot of experience to write something, which \u003Cem\u003Ecan be easily modified\u003C\/em\u003E.\u003C\/p\u003E\n\u003Cp\u003EProgrammers spend more time reading code than writing it. Seriously. Sometimes we spend the whole day digging through layers of code in search of a root cause of some bug, only to discover that all you need to fix it is to slightly modify a single line of code. (Btw, that\u2019s one of the reasons one shouldn\u2019t pay programmers \u003Ca href=\u0022\/blog\/rewarding-for-loc.lite\u0022\u003E per line of code\u003C\/a\u003E).\u003C\/p\u003E\n\u003Cp\u003EWhen I look at some code I wrote just four years ago, I\u2019m terrified of it. If I had to modify something non-trivial on that website, I think I would have to get drunk first. It\u2019s a mess. No separation of concerns, no layers of abstraction, sensitive configs in PHP files, templates mixed up the the business logic \u2013 not only is it objectively \u003Cem\u003Eugly\u003C\/em\u003E and \u003Cem\u003Eunreadable\u003C\/em\u003E, but most importantly, it takes a lot of time to understand what the code does, how it does it and how to change it best.\u003C\/p\u003E\n\u003Cp\u003EThere is also a lot of \u003Cstrong\u003Eduplication\u003C\/strong\u003E. I wrote some code to handle a post form in the admin panel. Then copy-pasted it and adjusted to handle an image form. Then the same for a comment form. And some others. Now if I had to change something regarding the form handling generally, I\u2019d have to do it in all of those places (knowing the whole application, and trying not to forget\/miss any of them). If only I had that shared logic separated into any kind of abstraction, I would only have to update that abstraction, so that every form which uses it would just switch to the new version.\u003C\/p\u003E\n\u003Cp\u003EThat code would also cause me trouble regarding \u003Cstrong\u003Ecooperation\u003C\/strong\u003E. Not only because I would be ashamed to share my shitty code with anyone. Mostly because the experience of my shitty code would be even more shitty for someone who didn\u2019t write it. If I had written \u003Ca href=\u0022http:\/\/blog.cleancoder.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E cleaner code\u003C\/a\u003E, followed \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/contributing\/code\/standards.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E styling conventions\u003C\/a\u003E and \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/SOLID_(object-oriented_design)\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E SOLID principles\u003C\/a\u003E, wrote automated tests, used an \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Model%E2%80%93view%E2%80%93controller\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E MVC\u003C\/a\u003E framework \u2013 then every experienced developer could just jump into the project without much preparation, knowing where to look without having to know the whole project. But in case of my shitty code, they would have to suffer through a lot before being able to work on it. Plus, they\u2019d have to know Polish \u2013 for some reason I used it to name some variables and templates... \ud83e\udd26\u003C\/p\u003E\n\u003Cp\u003EThat\u2019s why I\u2019m distinguishing between \u003Cstrong\u003Ecoders\u003C\/strong\u003E and \u003Cstrong\u003Edevelopers\u003C\/strong\u003E. When I started working as a programmer, I was just a coder \u2013 I was simply able to write my ideas down as a code, to tell the computer what I want it to do. Over the years I\u2019ve gathered the mindset and the skillset of a developer \u2013 a person that, well, develops a product. From start to end, from the architecture design to unit tests, able to communicate efficiently with others who work on it (developers, project managers, designers etc.), writing a code that\u2019s easy for others to co-create and maintain. Coding is more about knowing a tool, developing is more about the mindset. I\u2019m able to switch to a different framework or a completely different language within a week or two \u2013 because those are just tools.\u003C\/p\u003E\n\u003Cp\u003ESo to sum up: of course you can hire some intern for 10 PLN\/hour \u2013 they will take a month to create something, but if they\u2019re good, they will get shit done and working just fine. However, if you want to maintain this code later, develop your product further, add more people to your team, fix some bugs that came up \u2013 it will take a lot of time, tech debt will rise, bugs will multiply, time needed for testing will become huge. And you could also hire someone for 30 EUR\/hour \u2013 who would create the same functionality in just a week, keeping the code clean, easy to maintain, up-to-date with the newest trends in the field, interoperable and easier to test.\u003C\/p\u003E\n\u003Cp\u003EAnd that\u2019s why I get so pissed when I hear stuff like \u201cmy niece also does websites, she would do it for a lollipop, and you want \u003Cem\u003Emoney\u003C\/em\u003E from me?\u201d or \u201cI had some programming in high school, looks easy, you just google stuff and copy answers from Stack Overflow, how dare you make the money you do!\u201d.\u003C\/p\u003E\n\u003Cp\u003EWell, no. Sure, programming is basically just splitting complex problems into a set of simple instructions, so that even something dumb like a computer can understand and execute them \u2013 in principal it really is easy. But when it comes to doing it \u003Cem\u003Eright\u003C\/em\u003E \u2013 that\u2019s where software development becomes a real challenge.\u003C\/p\u003E","words":910,"readTime":4,"lang":"en"}}},"blog\/technology\/the-non-magic-of-autowiring":{"key":"blog\/technology\/the-non-magic-of-autowiring","type":"article","published":true,"meta":{"createdAt":"2017-09-01T22:58:27+02:00","publishedAt":"2017-09-05T20:00:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"the-non-magic-of-autowiring"},"content":{"en":{"slug":"the-non-magic-of-autowiring","title":"The non-magic of autowiring","intro":"\u003Cp\u003EWhen I first heard the term \u201cAutowiring\u201d, I thought it sounds exciting. But when I learned more or less what is it about, I got pretty sceptical of the idea. Too much \u003Cem\u003Emagic\u003C\/em\u003E, too much implied information... However, when I finally used it for the first time... Gosh I wish I could never define services manually again!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cp\u003EWhen I first heard the term \u201cAutowiring\u201d, I thought it sounds exciting. But when I learned more or less what is it about, I got pretty sceptical of the idea. Too much \u003Cem\u003Emagic\u003C\/em\u003E, too much implied information... However, when I finally used it for the first time... Gosh I wish I could never define services manually again!\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Dependency Injection Container\u003C\/a\u003E is definitely my favourite design pattern \u2013 so elegant, simple and flexible!\u003C\/p\u003E\n\u003Cp\u003EIt comes with one inconvenience though: you basically need to code the same thing twice. If your service requires some dependency, it cannot just \u003Cem\u003Etake\u003C\/em\u003E it or just \u003Cem\u003Ecreate\u003C\/em\u003E it. Instead, it should \u003Cem\u003Eexpect\u003C\/em\u003E its dependencies, while the container \u003Cem\u003Eprovides\u003C\/em\u003E them from the outside. When you want to add a new dependency, you need to both add it in the class and in some external service definition. This doesn\u2019t look like much effort, but when you\u2019re intensively playing around with your services, it all adds up. I didn\u2019t even realise, how annoying that process is, until I no longer had to follow it.\u003C\/p\u003E\n\u003Cp\u003EWhen I started a fresh project recently, using the latest version of \u003Ca href=\u0022https:\/\/symfony.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony\u003C\/a\u003E after over a year of working almost exclusively with \u003Ca href=\u0022https:\/\/phalconphp.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Phalcon\u003C\/a\u003E and \u003Ca href=\u0022https:\/\/micrus.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus\u003C\/a\u003E, I had already forgotten about those two new features of Symfony: autowiring and autoconfiguration. I remembered by accident.\u003C\/p\u003E\n\u003Cp\u003EI needed a \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/templating\/twig_extension.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Twig extension\u003C\/a\u003E, so I quickly created one: simple class, extending \u003Ccode\u003E\\Twig_Extension\u003C\/code\u003E, expecting some other service in its constructor, providing some filter in \u003Ccode\u003EgetFilters()\u003C\/code\u003E. I refreshed the tab in the browser and immediately realised I\u2019m gonna see an exception \u2013 in the end, I forgot to tag this class as a \u003Ccode\u003Etwig.extension\u003C\/code\u003E, I forgot to provide the dependencies, it has to fail! But no, \u003Cstrong\u003Eit just worked\u003C\/strong\u003E!\u003C\/p\u003E\n\u003Cp\u003EThe idea behind \u003Cstrong\u003Eautowiring\u003C\/strong\u003E is pretty simple: if a service requires an instance of \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, and your DI container happens to have a service called \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, which is of type \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, then it\u2019s pretty safe to assume, that\u2019s the one you want.\u003C\/p\u003E\n\u003Cp\u003EIdeally, you should depend on abstractions, interfaces. For instance when you have multiple cache adapters, all implementing \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E, your services should depend on \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E, not on any specific implementation. This way you can always switch for instance from \u003Ccode\u003EFilesystemAdapter\u003C\/code\u003E to \u003Ccode\u003ERedisAdapter\u003C\/code\u003E without any trouble.\u003C\/p\u003E\n\u003Cp\u003EBut if you have more than one implementation of an interface, how does the autowired container know, which one to use? You tell it, by creating an alias:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs yaml border\u0022\u003E\u003Cspan class=\u0022hljs-string\u0022\u003EPsr\\Cache\\CacheItemPoolInterface:\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027@Symfony\\Component\\Cache\\Adapter\u0027\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd what about the scalars and arrays? If my service expects \u003Ccode\u003Estring $baseUrl\u003C\/code\u003E, how does the container know \u003Cem\u003Ethat\u003C\/em\u003E? Of course it doesn\u2019t, I need to specify it myself:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs yaml border\u0022\u003E\u003Cspan class=\u0022hljs-string\u0022\u003EAppBundle\\Service\\ExternalSerive:\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-attr\u0022\u003Earguments:\u003C\/span\u003E\n        \u003Cspan class=\u0022hljs-string\u0022\u003E$baseUsr:\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027https:\/\/api.external.org\/\u0027\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EYou can do the same thing for services as well. For instance when all of them should use some generic logger, except for one, which requires something more specific, just overwrite its \u003Ccode\u003Earguments.$logger\u003C\/code\u003E with the other one.\u003C\/p\u003E\n\u003Cp\u003EPretty simple, right? The idea behind \u003Cstrong\u003Eautoconfiguration\u003C\/strong\u003E is even simpler. You (or libraries, like Twig) can define that all the services which are an instance of \u003Ccode\u003EFoo\u003C\/code\u003E should automatically receive some specific config, for instance a tag. That\u2019s why I didn\u2019t have to register my Twig extension.\u003C\/p\u003E\n\u003Cp\u003EMain concern one might have about autowiring is that, although pretty simple, it sure is time-consuming. Should I sacrifice my website\u2019s performance for the developer\u2019s convenience? Of course not! Symfony\u2019s container is compiled, so autowiring has absolutely no overhead on production!\u003C\/p\u003E\n\u003Cp\u003EAlso, Symfony Container has a concept of public and private services. Public ones you can just fetch from the container wherever you wish. Private ones can only be injected into other services \u2013 if they aren\u2019t used, they get removed from the container completely.\u003C\/p\u003E\n\u003Cp\u003EAutowiring is amazing. Simple, but effective. It makes the development faster, especially in the early phase. It prevents you from repeating yourself and maintaining a lengthy \u003Ccode\u003Eservices.yml\u003C\/code\u003E file full of information noise. And, although magical, it\u2019s not magic!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["autoconfiguration","autowiring","config","container","dependency injection","php","service","symfony"],"hasMore":true,"image":null,"introLite":"\u003Cp\u003EWhen I first heard the term \u201cAutowiring\u201d, I thought it sounds exciting. But when I learned more or less what is it about, I got pretty sceptical of the idea. Too much \u003Cem\u003Emagic\u003C\/em\u003E, too much implied information... However, when I finally used it for the first time... Gosh I wish I could never define services manually again!\u003C\/p\u003E","contentLite":"\u003Cp\u003EWhen I first heard the term \u201cAutowiring\u201d, I thought it sounds exciting. But when I learned more or less what is it about, I got pretty sceptical of the idea. Too much \u003Cem\u003Emagic\u003C\/em\u003E, too much implied information... However, when I finally used it for the first time... Gosh I wish I could never define services manually again!\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Dependency_injection\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Dependency Injection Container\u003C\/a\u003E is definitely my favourite design pattern \u2013 so elegant, simple and flexible!\u003C\/p\u003E\n\u003Cp\u003EIt comes with one inconvenience though: you basically need to code the same thing twice. If your service requires some dependency, it cannot just \u003Cem\u003Etake\u003C\/em\u003E it or just \u003Cem\u003Ecreate\u003C\/em\u003E it. Instead, it should \u003Cem\u003Eexpect\u003C\/em\u003E its dependencies, while the container \u003Cem\u003Eprovides\u003C\/em\u003E them from the outside. When you want to add a new dependency, you need to both add it in the class and in some external service definition. This doesn\u2019t look like much effort, but when you\u2019re intensively playing around with your services, it all adds up. I didn\u2019t even realise, how annoying that process is, until I no longer had to follow it.\u003C\/p\u003E\n\u003Cp\u003EWhen I started a fresh project recently, using the latest version of \u003Ca href=\u0022https:\/\/symfony.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony\u003C\/a\u003E after over a year of working almost exclusively with \u003Ca href=\u0022https:\/\/phalconphp.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Phalcon\u003C\/a\u003E and \u003Ca href=\u0022https:\/\/micrus.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Micrus\u003C\/a\u003E, I had already forgotten about those two new features of Symfony: autowiring and autoconfiguration. I remembered by accident.\u003C\/p\u003E\n\u003Cp\u003EI needed a \u003Ca href=\u0022https:\/\/symfony.com\/doc\/current\/templating\/twig_extension.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Twig extension\u003C\/a\u003E, so I quickly created one: simple class, extending \u003Ccode\u003E\\Twig_Extension\u003C\/code\u003E, expecting some other service in its constructor, providing some filter in \u003Ccode\u003EgetFilters()\u003C\/code\u003E. I refreshed the tab in the browser and immediately realised I\u2019m gonna see an exception \u2013 in the end, I forgot to tag this class as a \u003Ccode\u003Etwig.extension\u003C\/code\u003E, I forgot to provide the dependencies, it has to fail! But no, \u003Cstrong\u003Eit just worked\u003C\/strong\u003E!\u003C\/p\u003E\n\u003Cp\u003EThe idea behind \u003Cstrong\u003Eautowiring\u003C\/strong\u003E is pretty simple: if a service requires an instance of \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, and your DI container happens to have a service called \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, which is of type \u003Ccode\u003EAppBundle\\Api\\CmsService\u003C\/code\u003E, then it\u2019s pretty safe to assume, that\u2019s the one you want.\u003C\/p\u003E\n\u003Cp\u003EIdeally, you should depend on abstractions, interfaces. For instance when you have multiple cache adapters, all implementing \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E, your services should depend on \u003Ccode\u003EPsr\\Cache\\CacheItemPoolInterface\u003C\/code\u003E, not on any specific implementation. This way you can always switch for instance from \u003Ccode\u003EFilesystemAdapter\u003C\/code\u003E to \u003Ccode\u003ERedisAdapter\u003C\/code\u003E without any trouble.\u003C\/p\u003E\n\u003Cp\u003EBut if you have more than one implementation of an interface, how does the autowired container know, which one to use? You tell it, by creating an alias:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-yaml\u0022\u003EPsr\\Cache\\CacheItemPoolInterface: \u0027@Symfony\\Component\\Cache\\Adapter\u0027\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd what about the scalars and arrays? If my service expects \u003Ccode\u003Estring $baseUrl\u003C\/code\u003E, how does the container know \u003Cem\u003Ethat\u003C\/em\u003E? Of course it doesn\u2019t, I need to specify it myself:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-yaml\u0022\u003EAppBundle\\Service\\ExternalSerive:\n    arguments:\n        $baseUsr: \u0027https:\/\/api.external.org\/\u0027\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EYou can do the same thing for services as well. For instance when all of them should use some generic logger, except for one, which requires something more specific, just overwrite its \u003Ccode\u003Earguments.$logger\u003C\/code\u003E with the other one.\u003C\/p\u003E\n\u003Cp\u003EPretty simple, right? The idea behind \u003Cstrong\u003Eautoconfiguration\u003C\/strong\u003E is even simpler. You (or libraries, like Twig) can define that all the services which are an instance of \u003Ccode\u003EFoo\u003C\/code\u003E should automatically receive some specific config, for instance a tag. That\u2019s why I didn\u2019t have to register my Twig extension.\u003C\/p\u003E\n\u003Cp\u003EMain concern one might have about autowiring is that, although pretty simple, it sure is time-consuming. Should I sacrifice my website\u2019s performance for the developer\u2019s convenience? Of course not! Symfony\u2019s container is compiled, so autowiring has absolutely no overhead on production!\u003C\/p\u003E\n\u003Cp\u003EAlso, Symfony Container has a concept of public and private services. Public ones you can just fetch from the container wherever you wish. Private ones can only be injected into other services \u2013 if they aren\u2019t used, they get removed from the container completely.\u003C\/p\u003E\n\u003Cp\u003EAutowiring is amazing. Simple, but effective. It makes the development faster, especially in the early phase. It prevents you from repeating yourself and maintaining a lengthy \u003Ccode\u003Eservices.yml\u003C\/code\u003E file full of information noise. And, although magical, it\u2019s not magic!\u003C\/p\u003E","words":680,"readTime":3,"lang":"en"}}},"blog\/technology\/emojis-in-doctrine":{"key":"blog\/technology\/emojis-in-doctrine","type":"article","published":true,"meta":{"createdAt":"2017-05-25T19:08:08+02:00","publishedAt":"2017-05-25T19:03:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"emojis-in-doctrine"},"content":{"en":{"slug":"emojis-in-doctrine","title":"Emojis in Doctrine \ud83d\ude0e","intro":"\u003Cp\u003EPutting emojis in your database should be a piece of cake, right? You\u2019ve had enough trouble with encodings in your lifetime, and now that we have the blessing of \u003Cstrong\u003EUTF-8\u003C\/strong\u003E, you\u2019re always so careful to use it everywhere, so you\u2019d expect all the characters to just finally work out of the box, right?\u003C\/p\u003E\n\u003Cp\u003EWell, I did expect that. But I\u2019ve recently realised I can only put \u003Cem\u003Esome\u003C\/em\u003E emojis (like \u201c\u2764\ufe0f\u201d) in by blog posts. Most of them were just lost or replaced with \u201c?\u201d by MySQL... Oh, those damn encodings again!\u003C\/p\u003E\n\u003Cp\u003EBut fortunately the solution is quite simple.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cp\u003EPutting emojis in your database should be a piece of cake, right? You\u2019ve had enough trouble with encodings in your lifetime, and now that we have the blessing of \u003Cstrong\u003EUTF-8\u003C\/strong\u003E, you\u2019re always so careful to use it everywhere, so you\u2019d expect all the characters to just finally work out of the box, right?\u003C\/p\u003E\n\u003Cp\u003EWell, I did expect that. But I\u2019ve recently realised I can only put \u003Cem\u003Esome\u003C\/em\u003E emojis (like \u201c\u2764\ufe0f\u201d) in by blog posts. Most of them were just lost or replaced with \u201c?\u201d by MySQL... Oh, those damn encodings again!\u003C\/p\u003E\n\u003Cp\u003EBut fortunately the solution is quite simple.\u003C\/p\u003E\n\u003Cp\u003EInstead of the \u003Ccode\u003Eutf8\u003C\/code\u003E charset, you need to use its superset, \u003Ccode\u003Eutf8mb4\u003C\/code\u003E. This one handles 4-byte characters and that\u2019s exactly what we need. We just have to make both the database and \u003Ca href=\u0022http:\/\/www.doctrine-project.org\/projects\/orm.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Doctrine\u003C\/a\u003E use it.\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/www.phpmyadmin.net\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E phpMyAdmin\u003C\/a\u003E or \u003Ca href=\u0022https:\/\/www.adminer.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Adminer\u003C\/a\u003E let you change the charset easily. Just go to edit table schema and switch the collation of relevant columns and tables to \u003Ccode\u003Eutf8mb4_unicode_ci\u003C\/code\u003E. Since you\u2019re going from \u003Ccode\u003Eutf8\u003C\/code\u003E to its superset, no data should become corrupted in the process. But just to play it safe, better create a \u003Cstrong\u003Ebackup\u003C\/strong\u003E before you start.\u003C\/p\u003E\n\u003Cp\u003EYou might encounter an error: \u201cSpecified key was too long; max key length is 767 bytes\u201d. That\u2019s because of some limitations of InnoDB regarding indices length. To make an index into \u003Ccode\u003Emb4\u003C\/code\u003E, you\u2019ll have to shorten the max length of a column to 191 (instead of max 255 for simple \u003Ccode\u003Eutf8\u003C\/code\u003E).\u003C\/p\u003E\n\u003Cp\u003EWhen it comes to Doctrine, you have to specify the collation and charset on the level of an entity\/table and on the level of the connection.\u003C\/p\u003E\n\u003Cp\u003EFor an entity, if you\u2019re using annotations:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs bash border\u0022\u003E\/**\n * @ORM\\Entity\n * @ORM\\Table(options={\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022collate\u0022\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022utf8mb4_unicode_ci\u0022\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0022charset\u0022\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022utf8mb4\u0022\u003C\/span\u003E})\n *\/\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EOr if you\u2019re using XML:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs xml border\u0022\u003E\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Eentity\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Ename\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022Acme\\DemoBundle\\Entity\\User\u0022\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Eoptions\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n        \u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Eoption\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Ename\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022charset\u0022\u003C\/span\u003E\u0026gt;\u003C\/span\u003Eutf8mb4\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Eoption\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n        \u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Eoption\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Ename\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022collate\u0022\u003C\/span\u003E\u0026gt;\u003C\/span\u003Eutf8mb4_unicode_ci\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Eoption\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Eoptions\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Eentity\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAs for the connection, go with:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$conn = \\Doctrine\\DBAL\\DriverManager::getConnection(\n    [\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027driver\u0027\u003C\/span\u003E   =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027pdo_mysql\u0027\u003C\/span\u003E,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027host\u0027\u003C\/span\u003E     =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027localhost\u0027\u003C\/span\u003E,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027user\u0027\u003C\/span\u003E     =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027user\u0027\u003C\/span\u003E,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027password\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027password\u0027\u003C\/span\u003E,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027dbname\u0027\u003C\/span\u003E   =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027database\u0027\u003C\/span\u003E,\n        \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027charset\u0027\u003C\/span\u003E  =\u0026gt; \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027utf8mb4\u0027\u003C\/span\u003E,\n    ],\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E \\Doctrine\\DBAL\\Configuration()\n);\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EOr in \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Symfony\u003C\/a\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs yaml border\u0022\u003E\u003Cspan class=\u0022hljs-comment\u0022\u003E# app\/config\/config.yml\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-attr\u0022\u003Edoctrine:\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-attr\u0022\u003Edbal:\u003C\/span\u003E\n        \u003Cspan class=\u0022hljs-attr\u0022\u003Echarset:\u003C\/span\u003E  \u003Cspan class=\u0022hljs-string\u0022\u003Eutf8mb4\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EOr in \u003Ca href=\u0022https:\/\/micrus.avris.it\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus\u003C\/a\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs yaml border\u0022\u003E\u003Cspan class=\u0022hljs-comment\u0022\u003E# app\/Config\/parameters.yml\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-attr\u0022\u003Edatabase:\u003C\/span\u003E\n  \u003Cspan class=\u0022hljs-attr\u0022\u003Edriver:\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003Epdo_mysql\u003C\/span\u003E\n  \u003Cspan class=\u0022hljs-attr\u0022\u003Ehost:\u003C\/span\u003E \u003Cspan class=\u0022hljs-number\u0022\u003E127.0\u003C\/span\u003E\u003Cspan class=\u0022hljs-number\u0022\u003E.0\u003C\/span\u003E\u003Cspan class=\u0022hljs-number\u0022\u003E.1\u003C\/span\u003E\n  \u003Cspan class=\u0022hljs-attr\u0022\u003Edbname:\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003Edatabase\u003C\/span\u003E\n  \u003Cspan class=\u0022hljs-attr\u0022\u003Euser:\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003Euser\u003C\/span\u003E\n  \u003Cspan class=\u0022hljs-attr\u0022\u003Epassword:\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003Epassword\u003C\/span\u003E\n  \u003Cspan class=\u0022hljs-attr\u0022\u003Echarset:\u003C\/span\u003E \u003Cspan class=\u0022hljs-string\u0022\u003Eutf8mb4\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd that would be it (hopefully). Enjoy your new emoji support! \ud83d\ude0a\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["charset","databse","doctrine","emoji","encoding","mysql","unicode","utf8"],"hasMore":true,"image":null,"introLite":"\u003Cp\u003EPutting emojis in your database should be a piece of cake, right? You\u2019ve had enough trouble with encodings in your lifetime, and now that we have the blessing of \u003Cstrong\u003EUTF-8\u003C\/strong\u003E, you\u2019re always so careful to use it everywhere, so you\u2019d expect all the characters to just finally work out of the box, right?\u003C\/p\u003E\n\u003Cp\u003EWell, I did expect that. But I\u2019ve recently realised I can only put \u003Cem\u003Esome\u003C\/em\u003E emojis (like \u201c\u2764\ufe0f\u201d) in by blog posts. Most of them were just lost or replaced with \u201c?\u201d by MySQL... Oh, those damn encodings again!\u003C\/p\u003E\n\u003Cp\u003EBut fortunately the solution is quite simple.\u003C\/p\u003E","contentLite":"\u003Cp\u003EPutting emojis in your database should be a piece of cake, right? You\u2019ve had enough trouble with encodings in your lifetime, and now that we have the blessing of \u003Cstrong\u003EUTF-8\u003C\/strong\u003E, you\u2019re always so careful to use it everywhere, so you\u2019d expect all the characters to just finally work out of the box, right?\u003C\/p\u003E\n\u003Cp\u003EWell, I did expect that. But I\u2019ve recently realised I can only put \u003Cem\u003Esome\u003C\/em\u003E emojis (like \u201c\u2764\ufe0f\u201d) in by blog posts. Most of them were just lost or replaced with \u201c?\u201d by MySQL... Oh, those damn encodings again!\u003C\/p\u003E\n\u003Cp\u003EBut fortunately the solution is quite simple.\u003C\/p\u003E\n\u003Cp\u003EInstead of the \u003Ccode\u003Eutf8\u003C\/code\u003E charset, you need to use its superset, \u003Ccode\u003Eutf8mb4\u003C\/code\u003E. This one handles 4-byte characters and that\u2019s exactly what we need. We just have to make both the database and \u003Ca href=\u0022http:\/\/www.doctrine-project.org\/projects\/orm.html\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Doctrine\u003C\/a\u003E use it.\u003C\/p\u003E\n\u003Cp\u003E\u003Ca href=\u0022https:\/\/www.phpmyadmin.net\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E phpMyAdmin\u003C\/a\u003E or \u003Ca href=\u0022https:\/\/www.adminer.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Adminer\u003C\/a\u003E let you change the charset easily. Just go to edit table schema and switch the collation of relevant columns and tables to \u003Ccode\u003Eutf8mb4_unicode_ci\u003C\/code\u003E. Since you\u2019re going from \u003Ccode\u003Eutf8\u003C\/code\u003E to its superset, no data should become corrupted in the process. But just to play it safe, better create a \u003Cstrong\u003Ebackup\u003C\/strong\u003E before you start.\u003C\/p\u003E\n\u003Cp\u003EYou might encounter an error: \u201cSpecified key was too long; max key length is 767 bytes\u201d. That\u2019s because of some limitations of InnoDB regarding indices length. To make an index into \u003Ccode\u003Emb4\u003C\/code\u003E, you\u2019ll have to shorten the max length of a column to 191 (instead of max 255 for simple \u003Ccode\u003Eutf8\u003C\/code\u003E).\u003C\/p\u003E\n\u003Cp\u003EWhen it comes to Doctrine, you have to specify the collation and charset on the level of an entity\/table and on the level of the connection.\u003C\/p\u003E\n\u003Cp\u003EFor an entity, if you\u2019re using annotations:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\/**\n * @ORM\\Entity\n * @ORM\\Table(options={\u0022collate\u0022=\u0022utf8mb4_unicode_ci\u0022, \u0022charset\u0022=\u0022utf8mb4\u0022})\n *\/\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EOr if you\u2019re using XML:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;entity name=\u0022Acme\\DemoBundle\\Entity\\User\u0022\u0026gt;\n    \u0026lt;options\u0026gt;\n        \u0026lt;option name=\u0022charset\u0022\u0026gt;utf8mb4\u0026lt;\/option\u0026gt;\n        \u0026lt;option name=\u0022collate\u0022\u0026gt;utf8mb4_unicode_ci\u0026lt;\/option\u0026gt;\n    \u0026lt;\/options\u0026gt;\n\u0026lt;\/entity\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAs for the connection, go with:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$conn = \\Doctrine\\DBAL\\DriverManager::getConnection(\n    [\n        \u0027driver\u0027   =\u0026gt; \u0027pdo_mysql\u0027,\n        \u0027host\u0027     =\u0026gt; \u0027localhost\u0027,\n        \u0027user\u0027     =\u0026gt; \u0027user\u0027,\n        \u0027password\u0027 =\u0026gt; \u0027password\u0027,\n        \u0027dbname\u0027   =\u0026gt; \u0027database\u0027,\n        \u0027charset\u0027  =\u0026gt; \u0027utf8mb4\u0027,\n    ],\n    new \\Doctrine\\DBAL\\Configuration()\n);\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EOr in \u003Ca href=\u0022https:\/\/symfony.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Symfony\u003C\/a\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E# app\/config\/config.yml\ndoctrine:\n    dbal:\n        charset:  utf8mb4\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EOr in \u003Ca href=\u0022https:\/\/micrus.avris.it\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Micrus\u003C\/a\u003E:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E# app\/Config\/parameters.yml\ndatabase:\n  driver: pdo_mysql\n  host: 127.0.0.1\n  dbname: database\n  user: user\n  password: password\n  charset: utf8mb4\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EAnd that would be it (hopefully). Enjoy your new emoji support! \ud83d\ude0a\u003C\/p\u003E","words":419,"readTime":2,"lang":"en"}}},"blog\/technology\/fuck-you-facebook":{"key":"blog\/technology\/fuck-you-facebook","type":"article","published":true,"meta":{"createdAt":"2017-05-09T19:59:39+02:00","publishedAt":"2017-05-12T12:52:00+02:00","group":"tech-breakups","category":"blog","subcategory":"technology","slug":"fuck-you-facebook"},"content":{"en":{"slug":"fuck-you-facebook","title":"Fuck you, Facebook","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/facebook-dick_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022698.88\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAkCAYAAACTz\/ouAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEiUlEQVRIia2WS29bVRDHf3Pv8SPxI682bnGpUtQKEKXdUCQWVPAJIvoRYEM3XRWJLvgkha66owsWRXSDSrOhEiiB0oRHKc2jIbR1YidO7fs49w4L27WdxHaI+EuWpXPn+Z85M0c++uwrZU8oAqSTQmgVGwvGiRFxsJGScJUohkgFkL1NAOaf0nrPj446vHfuCLlUSKUaMlUcIVKh7sfkMkkWHq7zw69llL1jFMCUSts7AhB4oaB8+32NyfEhQhvx21KFWAWNXUxCKG1sU1r3UHF7hCiYD6ffACKkR5qN6ATBaf4rStwM4iUgbkq05NuaAsgfD5e0cHi8H40dmbWVd0SxW1\/hybMNDAKOozxeXSOfzyOA6zo4joMfBLiOi4gQa8NoZG3DngjJhMFxXFQVG1lsaEkkk0wePgwoT0rrGAGSiRRBEKJxTGVrC4BcNofv+8SqhGFAPpfD831Q8H2P0dFRNtbLuMZgI4uIg6qSd5yuRAyAOA6vv\/YqAJOTk4O4eoFCobDneRRFDY606cBaS7VaZWQkj8YNKkSEIAwIgoDMcAaA0FoSxlD36gylhxpyToP8wA\/IZDO76mJaHufn55kYH2ejXGYoncbzfCYOjbO1VSWXy7G5uYkxBhuGDGcy1Go1bBiSSCRJpZKMjo1xInMCERqWRdsU2TDE8zxWHj\/m6JEjeL7P89pz4mcx2WyW1dVVDk1MUKlU8Hwfay21Wo1CocD29jaKsra2xsryMsOZDOfOvdVdA2MMxWKRkXwez\/fJZrOcmJqiXq\/jGkMumyWRSFAsFolVKZfLHDt2jFwut4v\/MAjovKwOgOu6pFMpgjBsFgiCMKTueZRKJYwxBGGA53lUq1sMDQ2xtbWJiOz6JVOpLocGIJVOc\/LUqQE9czAYgDiOEOm4ij3m60B0zIvWADStg0a7SbfgQSGKRh01OBgUdHCqAxz0M9BMc08nbQoaDqQXJx1GVAHlzwcPePr0Kf312nAGR9o0JMLMzAy3bt3i86tX25EPcGK6Iu2DxcVFZmfnqJTLxHE8UL6FjhrsdNLaWlCpVLh+\/TqXLl3igwsXGBsb2xc98CIDZfdaEubmfmJudpb5hQWmp6ex1vL1zZt8euXKALNtypv3YPe+q9XqzNy5w8cXL5JMJvnk8mW+u32bKI5ZWFjg9OnT+88gRnG6OlZQVVQV3\/e5e\/cui4uLfHnjBqBc++LaQAetKsmDv5b0+MtHMa7LzsV+7+d7\/HL\/PqdOnqRcLrO8vIy1lnfPnx\/owEaWpZW\/Gzu5eRl2iChnzp7hzNmzXWeq++k5xWlKdVw07RLYU611vM8Ogo5hpwoiHc8mlaad9lnbbv+L2Tk9jNJ4VcTNRdMXOxPtA8dtPCdNrMqz9fJ\/0d0ftMGCqXkR38zcb74k\/z8XCrz\/dhFTqwf8uLDa1\/ZwWhjNKIlEGtdRPD9moxrhBb1nkgLvvFnAgBIFATHO3k5EqUWQcBPY53WMCOKA51lC28O6AMSgMTL\/+yN9tPIEtNfuidnd+S06e7WrAg6vHD+E+H6wj8V3MAjwL0WBEtjSJKdGAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/facebook-dick_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022698.88\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI used to run a couple of Facebook fanpages. One of them was shut down three times, apparently for being \u003Ca href=\u0022\/tag\/homophobia\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-tag\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E homophobic\u003C\/a\u003E. It was quite the opposite, actually. The name could be confusing, because it was a word play on the Polish word for \u201cfaggot\u201d and a name of a Polish gossip portal. But the content was specifically anti-homophobic! It was a rainbow meme aggregator, basically a gay version of \u003Ca href=\u0022https:\/\/9gag.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E 9gag\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EBut the thing is, I can only assume why did people report my fanpage and why did moderators remove it. Did someone just assume it\u2019s homophobic without actually checking it out? Or quite the opposite: did someone consider homosexuality an abomination and just reported everything that\u2019s even remotely gay? I\u2019ll never know. The only thing Facebook bothered to tell me is that \u201cI\u2019ve abused the \u003Ca href=\u0022https:\/\/www.facebook.com\/communitystandards\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Community Standards\u003C\/a\u003E\u201d. I\u2019ve read them thoroughly and there was no abuse of them from my side.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/facebook-dick_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022500\u0022 height=\u0022728\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAkCAYAAACTz\/ouAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEiUlEQVRIia2WS29bVRDHf3Pv8SPxI682bnGpUtQKEKXdUCQWVPAJIvoRYEM3XRWJLvgkha66owsWRXSDSrOhEiiB0oRHKc2jIbR1YidO7fs49w4L27WdxHaI+EuWpXPn+Z85M0c++uwrZU8oAqSTQmgVGwvGiRFxsJGScJUohkgFkL1NAOaf0nrPj446vHfuCLlUSKUaMlUcIVKh7sfkMkkWHq7zw69llL1jFMCUSts7AhB4oaB8+32NyfEhQhvx21KFWAWNXUxCKG1sU1r3UHF7hCiYD6ffACKkR5qN6ATBaf4rStwM4iUgbkq05NuaAsgfD5e0cHi8H40dmbWVd0SxW1\/hybMNDAKOozxeXSOfzyOA6zo4joMfBLiOi4gQa8NoZG3DngjJhMFxXFQVG1lsaEkkk0wePgwoT0rrGAGSiRRBEKJxTGVrC4BcNofv+8SqhGFAPpfD831Q8H2P0dFRNtbLuMZgI4uIg6qSd5yuRAyAOA6vv\/YqAJOTk4O4eoFCobDneRRFDY606cBaS7VaZWQkj8YNKkSEIAwIgoDMcAaA0FoSxlD36gylhxpyToP8wA\/IZDO76mJaHufn55kYH2ejXGYoncbzfCYOjbO1VSWXy7G5uYkxBhuGDGcy1Go1bBiSSCRJpZKMjo1xInMCERqWRdsU2TDE8zxWHj\/m6JEjeL7P89pz4mcx2WyW1dVVDk1MUKlU8Hwfay21Wo1CocD29jaKsra2xsryMsOZDOfOvdVdA2MMxWKRkXwez\/fJZrOcmJqiXq\/jGkMumyWRSFAsFolVKZfLHDt2jFwut4v\/MAjovKwOgOu6pFMpgjBsFgiCMKTueZRKJYwxBGGA53lUq1sMDQ2xtbWJiOz6JVOpLocGIJVOc\/LUqQE9czAYgDiOEOm4ij3m60B0zIvWADStg0a7SbfgQSGKRh01OBgUdHCqAxz0M9BMc08nbQoaDqQXJx1GVAHlzwcPePr0Kf312nAGR9o0JMLMzAy3bt3i86tX25EPcGK6Iu2DxcVFZmfnqJTLxHE8UL6FjhrsdNLaWlCpVLh+\/TqXLl3igwsXGBsb2xc98CIDZfdaEubmfmJudpb5hQWmp6ex1vL1zZt8euXKALNtypv3YPe+q9XqzNy5w8cXL5JMJvnk8mW+u32bKI5ZWFjg9OnT+88gRnG6OlZQVVQV3\/e5e\/cui4uLfHnjBqBc++LaQAetKsmDv5b0+MtHMa7LzsV+7+d7\/HL\/PqdOnqRcLrO8vIy1lnfPnx\/owEaWpZW\/Gzu5eRl2iChnzp7hzNmzXWeq++k5xWlKdVw07RLYU611vM8Ogo5hpwoiHc8mlaad9lnbbv+L2Tk9jNJ4VcTNRdMXOxPtA8dtPCdNrMqz9fJ\/0d0ftMGCqXkR38zcb74k\/z8XCrz\/dhFTqwf8uLDa1\/ZwWhjNKIlEGtdRPD9moxrhBb1nkgLvvFnAgBIFATHO3k5EqUWQcBPY53WMCOKA51lC28O6AMSgMTL\/+yN9tPIEtNfuidnd+S06e7WrAg6vHD+E+H6wj8V3MAjwL0WBEtjSJKdGAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/facebook-dick_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022500\u0022 height=\u0022728\u0022\u003E\u003C\/span\u003E\n                \u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/onsizzle.com\/i\/contentment-facebook-community-facebook-336235\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\n                        \u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E\n                        onsizzle.com\/i\/contentment-facebook-community-facebook-336235\n                    \u003C\/a\u003E\n                \u003C\/figcaption\u003E\n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI used to run a couple of Facebook fanpages. One of them was shut down three times, apparently for being \u003Ca href=\u0022\/tag\/homophobia\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-tag\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E homophobic\u003C\/a\u003E. It was quite the opposite, actually. The name could be confusing, because it was a word play on the Polish word for \u201cfaggot\u201d and a name of a Polish gossip portal. But the content was specifically anti-homophobic! It was a rainbow meme aggregator, basically a gay version of \u003Ca href=\u0022https:\/\/9gag.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E 9gag\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EBut the thing is, I can only assume why did people report my fanpage and why did moderators remove it. Did someone just assume it\u2019s homophobic without actually checking it out? Or quite the opposite: did someone consider homosexuality an abomination and just reported everything that\u2019s even remotely gay? I\u2019ll never know. The only thing Facebook bothered to tell me is that \u201cI\u2019ve abused the \u003Ca href=\u0022https:\/\/www.facebook.com\/communitystandards\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Community Standards\u003C\/a\u003E\u201d. I\u2019ve read them thoroughly and there was no abuse of them from my side.\u003C\/p\u003E\n\u003Cp\u003EThe same thing happened with my other fanpage. This one managed to get quite popular before it was taken down. Sure, it was controversial, poking fun at religion and stuff. But still, without breaching any of the Community Standards.\u003C\/p\u003E\n\u003Cp\u003EAnd that was too much for me. I\u2019ve put so much work into creating all that, and now it gets removed without a warning by some \u003Cstrong\u003Eanonymous\u003C\/strong\u003E guy who doesn\u2019t specify a \u003Cstrong\u003Ereason\u003C\/strong\u003E? How on Earth could I \u003Cstrong\u003Elearn to comply\u003C\/strong\u003E with the Community Standards, when there\u2019s no way to find out what I did wrong? Now, if I start over or start something new, I\u2019ll be writing every new post and creating every new meme under a threat that someone\u2019s \u003Cstrong\u003Ewhim\u003C\/strong\u003E might destroy all that at any moment.\u003C\/p\u003E\n\u003Cp\u003EIf that wasn\u2019t annoying enough, I could always get \u201cconsolation\u201d from checking out all the pages that \u003Cem\u003Edidn\u2019t\u003C\/em\u003E get suspended or removed. Alt-right, nationalists, fascists, racists, haters... Almost all my reports of obvious pedophile dens or of hate speech cases, were answered with \u201csorry, but they didn\u2019t do anything wrong\u201d. At the same time \u003Ca href=\u0022https:\/\/www.facebook.com\/AtheistRepublic\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Atheist Republic\u003C\/a\u003E has been temporarily banned, among with many other pages for atheists and ex-Muslims. Even \u003Ca href=\u0022https:\/\/www.facebook.com\/mycountryeurope\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E My country? Europe.\u003C\/a\u003E, a neutral, positive fanpage, for some reason received that treatment as well. What the fuck, Facebook?\u003C\/p\u003E\n\u003Cp\u003EThis \u003Cstrong\u003Eunpredictability\u003C\/strong\u003E, apparent \u003Cstrong\u003Erandomness\u003C\/strong\u003E, total \u003Cstrong\u003Elack of transparency\u003C\/strong\u003E and plain \u003Cstrong\u003Einjustice\u003C\/strong\u003E are the main reason why I hate Facebook. (And also being a way heavier and slower website\/app than acceptable...)\u003C\/p\u003E\n\u003Cp\u003EBut the problem is, they practically have a monopoly. Most of my friends are on Facebook. Most of my communication goes through Messenger. It\u2019s really hard to boycott that company...\u003C\/p\u003E\n\u003Cp\u003EIt is, however, doable \u003Cstrong\u003Enot to depend\u003C\/strong\u003E on them completely. Whatever I post over there, I would not care losing. The stuff I \u003Cem\u003Edo\u003C\/em\u003E care about, is all on my own server \u2013 with frequent backups, reliability and independence.\u003C\/p\u003E\n\u003Cp\u003EOh Facebook.. I know that for now we are forced to stay together in our toxic relationship. But please know that I hate you.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["ban","censorship","competition","facebook","injustice","monopoly","randomness","social network","suspension","transparency","unpredictability"],"hasMore":true,"image":"https:\/\/avris.it\/image\/facebook-dick_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/facebook-dick_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/facebook-dick_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022349.44\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI used to run a couple of Facebook fanpages. One of them was shut down three times, apparently for being \u003Ca href=\u0022\/tag\/homophobia\u0022\u003E homophobic\u003C\/a\u003E. It was quite the opposite, actually. The name could be confusing, because it was a word play on the Polish word for \u201cfaggot\u201d and a name of a Polish gossip portal. But the content was specifically anti-homophobic! It was a rainbow meme aggregator, basically a gay version of \u003Ca href=\u0022https:\/\/9gag.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E 9gag\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EBut the thing is, I can only assume why did people report my fanpage and why did moderators remove it. Did someone just assume it\u2019s homophobic without actually checking it out? Or quite the opposite: did someone consider homosexuality an abomination and just reported everything that\u2019s even remotely gay? I\u2019ll never know. The only thing Facebook bothered to tell me is that \u201cI\u2019ve abused the \u003Ca href=\u0022https:\/\/www.facebook.com\/communitystandards\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Community Standards\u003C\/a\u003E\u201d. I\u2019ve read them thoroughly and there was no abuse of them from my side.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/facebook-dick_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/facebook-dick_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022349.44\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003Cfigcaption\u003E\n                    \u003Ca href=\u0022https:\/\/onsizzle.com\/i\/contentment-facebook-community-facebook-336235\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csmall\u003Eonsizzle.com\/i\/contentment-facebook-community-facebook-336235\u003C\/small\u003E\u003C\/a\u003E\n                \u003C\/figcaption\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI used to run a couple of Facebook fanpages. One of them was shut down three times, apparently for being \u003Ca href=\u0022\/tag\/homophobia\u0022\u003E homophobic\u003C\/a\u003E. It was quite the opposite, actually. The name could be confusing, because it was a word play on the Polish word for \u201cfaggot\u201d and a name of a Polish gossip portal. But the content was specifically anti-homophobic! It was a rainbow meme aggregator, basically a gay version of \u003Ca href=\u0022https:\/\/9gag.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E 9gag\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EBut the thing is, I can only assume why did people report my fanpage and why did moderators remove it. Did someone just assume it\u2019s homophobic without actually checking it out? Or quite the opposite: did someone consider homosexuality an abomination and just reported everything that\u2019s even remotely gay? I\u2019ll never know. The only thing Facebook bothered to tell me is that \u201cI\u2019ve abused the \u003Ca href=\u0022https:\/\/www.facebook.com\/communitystandards\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Community Standards\u003C\/a\u003E\u201d. I\u2019ve read them thoroughly and there was no abuse of them from my side.\u003C\/p\u003E\n\u003Cp\u003EThe same thing happened with my other fanpage. This one managed to get quite popular before it was taken down. Sure, it was controversial, poking fun at religion and stuff. But still, without breaching any of the Community Standards.\u003C\/p\u003E\n\u003Cp\u003EAnd that was too much for me. I\u2019ve put so much work into creating all that, and now it gets removed without a warning by some \u003Cstrong\u003Eanonymous\u003C\/strong\u003E guy who doesn\u2019t specify a \u003Cstrong\u003Ereason\u003C\/strong\u003E? How on Earth could I \u003Cstrong\u003Elearn to comply\u003C\/strong\u003E with the Community Standards, when there\u2019s no way to find out what I did wrong? Now, if I start over or start something new, I\u2019ll be writing every new post and creating every new meme under a threat that someone\u2019s \u003Cstrong\u003Ewhim\u003C\/strong\u003E might destroy all that at any moment.\u003C\/p\u003E\n\u003Cp\u003EIf that wasn\u2019t annoying enough, I could always get \u201cconsolation\u201d from checking out all the pages that \u003Cem\u003Edidn\u2019t\u003C\/em\u003E get suspended or removed. Alt-right, nationalists, fascists, racists, haters... Almost all my reports of obvious pedophile dens or of hate speech cases, were answered with \u201csorry, but they didn\u2019t do anything wrong\u201d. At the same time \u003Ca href=\u0022https:\/\/www.facebook.com\/AtheistRepublic\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Atheist Republic\u003C\/a\u003E has been temporarily banned, among with many other pages for atheists and ex-Muslims. Even \u003Ca href=\u0022https:\/\/www.facebook.com\/mycountryeurope\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E My country? Europe.\u003C\/a\u003E, a neutral, positive fanpage, for some reason received that treatment as well. What the fuck, Facebook?\u003C\/p\u003E\n\u003Cp\u003EThis \u003Cstrong\u003Eunpredictability\u003C\/strong\u003E, apparent \u003Cstrong\u003Erandomness\u003C\/strong\u003E, total \u003Cstrong\u003Elack of transparency\u003C\/strong\u003E and plain \u003Cstrong\u003Einjustice\u003C\/strong\u003E are the main reason why I hate Facebook. (And also being a way heavier and slower website\/app than acceptable...)\u003C\/p\u003E\n\u003Cp\u003EBut the problem is, they practically have a monopoly. Most of my friends are on Facebook. Most of my communication goes through Messenger. It\u2019s really hard to boycott that company...\u003C\/p\u003E\n\u003Cp\u003EIt is, however, doable \u003Cstrong\u003Enot to depend\u003C\/strong\u003E on them completely. Whatever I post over there, I would not care losing. The stuff I \u003Cem\u003Edo\u003C\/em\u003E care about, is all on my own server \u2013 with frequent backups, reliability and independence.\u003C\/p\u003E\n\u003Cp\u003EOh Facebook.. I know that for now we are forced to stay together in our toxic relationship. But please know that I hate you.\u003C\/p\u003E","words":509,"readTime":3,"lang":"en"}}},"blog\/technology\/brand-new-blog":{"key":"blog\/technology\/brand-new-blog","type":"article","published":true,"meta":{"createdAt":"2017-04-30T21:22:09+02:00","publishedAt":"2017-04-30T21:05:00+02:00","group":"redesign","category":"blog","subcategory":"technology","slug":"brand-new-blog"},"content":{"en":{"slug":"brand-new-blog","title":"Brand new blog","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/new-avris_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022250.4347826087\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFD0lEQVRIia2Wz4tdWRHHP1Xn3Pt+dNuvO+m0GY2jOATHzDBmoy5E3Sgogrh14d6\/wIUr3fgfjBtBXLgRN6OIIDKIoMK4GCGgTMCJmR9J6CTTmZ5+\/d6995yqcnFfMll0Bgc8m1N1qjj1rTp1v3UlIoIz1u3btymlsFjssru7OMuFo3feISKYb22xXJ6ws7Pg\/v377O\/v8+DBA5qmQVXp+57JZEI66Zg\/tU8\/DMznc0SEiEBEAEb5Z7\/8VSAgqogqDogk3J1mOkUF0ASipJSJpIgIWRKBsLkLBUISouOBANRKRECAh1PKAEkJq4RV3AyvhbAAN1RApp96LnQ6JU1mpJRxnEDI0zm5acnTGeRMmswgNaTpjEYSOSlIptpAAhRBRGimc6pVdOgRB\/ERTB06hnDCg269xLolpe\/x9Ql1tcLLwEQSudVEO5mRZ9tIkxmGNeHBpG1xTeCG9IaKItMM3Sky3xkhWCEVw1QgTVE3ymqF1YqaM53vUK0Q3QohoUOHu6MB7qC1UiUhzYTkguPkWh1fvsd2bmjaltUwYC6gKyqJlBs8KU1AUwvNdI6dntBOJ1goeWvB1myHWn2s4HrN0o8xK1z5+AVidcxr12\/RVwerDH2PheOrY7wMYAbmuBsaTrYQwhPH7x4jqzWqiUgN666gjRJiaG759le\/RDuZ8cdXr\/GtL36Ol\/7yDybbC2S+YN1sEQyIKLu7mY\/plJyE1eoU6QuXLh4gAsuTJW++fQdD8DzFhop7hWqEGR6Q8s6FH3kYooJ5ECi+adRmOqfZ3uP5z1zm1z\/5AQh892tf5sXf\/ol3B6NPE8pg9N0pw9DRrU+o61PObc2IqLQ5oznhtdJKcOvOIe91A1EGrFSslBGQVbwWkkD2cNAGcxAFs0pKCXKLaSIi+PrnX+D1t+\/wr\/+8xYsvvcxyqGhqiG6NJSMINAIPo20yxbbAjW4oZAlKGejNKO50\/Rpxx6oRCBGCx1gIEKS5+NkgJyQl0AbJCZl9hDTbxsNA4MrlZ7h0YZ\/ejINze\/zmb69iCJoTmltAUDNwx7xyaW9BrRW8kiLACtTK4eFd+m5FVAeCqAPhPtJAKbSayBEOoeCBpA2X1Ep0HSEBqtw7vIfUyt3jJSdPnRLrDgS8aYhhQDSBCF7HJn3r9ilujoYRpRJWEDe8VsKciAJDIawiHkQ4EgJhSDp4NiQlIo3ZelJSnoxfl8jIcAJoi6SM5rw5UzSN\/aYBgcOGZ3AjfHzGsIJbRZ1Nr9gIxHrCIGwgzBCEVgX5819fCUR4RLmim10eUTpsgG2YOZCHLgRAvC\/LRg8CiRif5uFwCh89wkfnx3VARJC+7+Oh8nCuPL4\/vs6y\/b\/lfObUBG7evEnOmel0SkSwWCxo2\/aR\/caNG+zt7VFrRVU5f\/78k676UOuJgI4Ob3Jut+V0DZNJw9Jakiqq0M4OODg4IKWRFh5m+XhF\/xf5QwH6xc9\/zNVn3yU5\/O73d7m4P+M739hnZydx\/pnv8emr36dpGgBevnaXi3sdz31iB4BSCsAj+\/VbJxwe93zlyj4AtVbc\/cy4+iRAR1Wwy3v84e8d33z+C5R7c3740zd4bfccw+KFMXB1+mJsTzOTrPTFqPZ+oIigmpOTMMlKN9gHVucDK3S07Hnlnys+Wc9x\/c271GIcHxauvX7E6Rv\/5umPXsVC6Abj0gJg4N7RwKxN5E2aKSXWgzFX5+k9pesHlPFfS\/XsWvwX97wRJTQmN3gAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/new-avris_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022250.4347826087\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFinally. I got to work and rewrote the code of my sweet blog. Brand new design, new framework, \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus\u003C\/a\u003E, better support for language versions, a couple of new features in the admin panel, ditching custom comments for the awesomeness of \u003Ca href=\u0022https:\/\/disqus.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Disqus\u003C\/a\u003E, ditching TinyMCE for the beauty and simplicity of Markdown. It was a lot of work, but it was definitely worth it!\u003C\/p\u003E\n\u003Cp\u003EHope you like it! :)\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/new-avris_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022500.86956521739\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFD0lEQVRIia2Wz4tdWRHHP1Xn3Pt+dNuvO+m0GY2jOATHzDBmoy5E3Sgogrh14d6\/wIUr3fgfjBtBXLgRN6OIIDKIoMK4GCGgTMCJmR9J6CTTmZ5+\/d6995yqcnFfMll0Bgc8m1N1qjj1rTp1v3UlIoIz1u3btymlsFjssru7OMuFo3feISKYb22xXJ6ws7Pg\/v377O\/v8+DBA5qmQVXp+57JZEI66Zg\/tU8\/DMznc0SEiEBEAEb5Z7\/8VSAgqogqDogk3J1mOkUF0ASipJSJpIgIWRKBsLkLBUISouOBANRKRECAh1PKAEkJq4RV3AyvhbAAN1RApp96LnQ6JU1mpJRxnEDI0zm5acnTGeRMmswgNaTpjEYSOSlIptpAAhRBRGimc6pVdOgRB\/ERTB06hnDCg269xLolpe\/x9Ql1tcLLwEQSudVEO5mRZ9tIkxmGNeHBpG1xTeCG9IaKItMM3Sky3xkhWCEVw1QgTVE3ymqF1YqaM53vUK0Q3QohoUOHu6MB7qC1UiUhzYTkguPkWh1fvsd2bmjaltUwYC6gKyqJlBs8KU1AUwvNdI6dntBOJ1goeWvB1myHWn2s4HrN0o8xK1z5+AVidcxr12\/RVwerDH2PheOrY7wMYAbmuBsaTrYQwhPH7x4jqzWqiUgN666gjRJiaG759le\/RDuZ8cdXr\/GtL36Ol\/7yDybbC2S+YN1sEQyIKLu7mY\/plJyE1eoU6QuXLh4gAsuTJW++fQdD8DzFhop7hWqEGR6Q8s6FH3kYooJ5ECi+adRmOqfZ3uP5z1zm1z\/5AQh892tf5sXf\/ol3B6NPE8pg9N0pw9DRrU+o61PObc2IqLQ5oznhtdJKcOvOIe91A1EGrFSslBGQVbwWkkD2cNAGcxAFs0pKCXKLaSIi+PrnX+D1t+\/wr\/+8xYsvvcxyqGhqiG6NJSMINAIPo20yxbbAjW4oZAlKGejNKO50\/Rpxx6oRCBGCx1gIEKS5+NkgJyQl0AbJCZl9hDTbxsNA4MrlZ7h0YZ\/ejINze\/zmb69iCJoTmltAUDNwx7xyaW9BrRW8kiLACtTK4eFd+m5FVAeCqAPhPtJAKbSayBEOoeCBpA2X1Ep0HSEBqtw7vIfUyt3jJSdPnRLrDgS8aYhhQDSBCF7HJn3r9ilujoYRpRJWEDe8VsKciAJDIawiHkQ4EgJhSDp4NiQlIo3ZelJSnoxfl8jIcAJoi6SM5rw5UzSN\/aYBgcOGZ3AjfHzGsIJbRZ1Nr9gIxHrCIGwgzBCEVgX5819fCUR4RLmim10eUTpsgG2YOZCHLgRAvC\/LRg8CiRif5uFwCh89wkfnx3VARJC+7+Oh8nCuPL4\/vs6y\/b\/lfObUBG7evEnOmel0SkSwWCxo2\/aR\/caNG+zt7VFrRVU5f\/78k676UOuJgI4Ob3Jut+V0DZNJw9Jakiqq0M4OODg4IKWRFh5m+XhF\/xf5QwH6xc9\/zNVn3yU5\/O73d7m4P+M739hnZydx\/pnv8emr36dpGgBevnaXi3sdz31iB4BSCsAj+\/VbJxwe93zlyj4AtVbc\/cy4+iRAR1Wwy3v84e8d33z+C5R7c3740zd4bfccw+KFMXB1+mJsTzOTrPTFqPZ+oIigmpOTMMlKN9gHVucDK3S07Hnlnys+Wc9x\/c271GIcHxauvX7E6Rv\/5umPXsVC6Abj0gJg4N7RwKxN5E2aKSXWgzFX5+k9pesHlPFfS\/XsWvwX97wRJTQmN3gAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/new-avris_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022500.86956521739\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFinally. I got to work and rewrote the code of my sweet blog. Brand new design, new framework, \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus\u003C\/a\u003E, better support for language versions, a couple of new features in the admin panel, ditching custom comments for the awesomeness of \u003Ca href=\u0022https:\/\/disqus.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Disqus\u003C\/a\u003E, ditching TinyMCE for the beauty and simplicity of Markdown. It was a lot of work, but it was definitely worth it!\u003C\/p\u003E\n\u003Cp\u003EHope you like it! :)\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["blog","comments","design","disqus","framework","markdown","php","programming","redesign","tinymce","work"],"hasMore":false,"image":"https:\/\/avris.it\/image\/new-avris_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/new-avris_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/new-avris_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022125.21739130435\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFinally. I got to work and rewrote the code of my sweet blog. Brand new design, new framework, \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework.lite\u0022\u003E Micrus\u003C\/a\u003E, better support for language versions, a couple of new features in the admin panel, ditching custom comments for the awesomeness of \u003Ca href=\u0022https:\/\/disqus.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Disqus\u003C\/a\u003E, ditching TinyMCE for the beauty and simplicity of Markdown. It was a lot of work, but it was definitely worth it!\u003C\/p\u003E\n\u003Cp\u003EHope you like it! :)\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/new-avris_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/new-avris_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022125.21739130435\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EFinally. I got to work and rewrote the code of my sweet blog. Brand new design, new framework, \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework.lite\u0022\u003E Micrus\u003C\/a\u003E, better support for language versions, a couple of new features in the admin panel, ditching custom comments for the awesomeness of \u003Ca href=\u0022https:\/\/disqus.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Disqus\u003C\/a\u003E, ditching TinyMCE for the beauty and simplicity of Markdown. It was a lot of work, but it was definitely worth it!\u003C\/p\u003E\n\u003Cp\u003EHope you like it! :)\u003C\/p\u003E","words":66,"readTime":null,"lang":"en"},"pl":{"slug":"nowiutki-blog","title":"Nowiutki blog","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/new-avris_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022250.4347826087\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFD0lEQVRIia2Wz4tdWRHHP1Xn3Pt+dNuvO+m0GY2jOATHzDBmoy5E3Sgogrh14d6\/wIUr3fgfjBtBXLgRN6OIIDKIoMK4GCGgTMCJmR9J6CTTmZ5+\/d6995yqcnFfMll0Bgc8m1N1qjj1rTp1v3UlIoIz1u3btymlsFjssru7OMuFo3feISKYb22xXJ6ws7Pg\/v377O\/v8+DBA5qmQVXp+57JZEI66Zg\/tU8\/DMznc0SEiEBEAEb5Z7\/8VSAgqogqDogk3J1mOkUF0ASipJSJpIgIWRKBsLkLBUISouOBANRKRECAh1PKAEkJq4RV3AyvhbAAN1RApp96LnQ6JU1mpJRxnEDI0zm5acnTGeRMmswgNaTpjEYSOSlIptpAAhRBRGimc6pVdOgRB\/ERTB06hnDCg269xLolpe\/x9Ql1tcLLwEQSudVEO5mRZ9tIkxmGNeHBpG1xTeCG9IaKItMM3Sky3xkhWCEVw1QgTVE3ymqF1YqaM53vUK0Q3QohoUOHu6MB7qC1UiUhzYTkguPkWh1fvsd2bmjaltUwYC6gKyqJlBs8KU1AUwvNdI6dntBOJ1goeWvB1myHWn2s4HrN0o8xK1z5+AVidcxr12\/RVwerDH2PheOrY7wMYAbmuBsaTrYQwhPH7x4jqzWqiUgN666gjRJiaG759le\/RDuZ8cdXr\/GtL36Ol\/7yDybbC2S+YN1sEQyIKLu7mY\/plJyE1eoU6QuXLh4gAsuTJW++fQdD8DzFhop7hWqEGR6Q8s6FH3kYooJ5ECi+adRmOqfZ3uP5z1zm1z\/5AQh892tf5sXf\/ol3B6NPE8pg9N0pw9DRrU+o61PObc2IqLQ5oznhtdJKcOvOIe91A1EGrFSslBGQVbwWkkD2cNAGcxAFs0pKCXKLaSIi+PrnX+D1t+\/wr\/+8xYsvvcxyqGhqiG6NJSMINAIPo20yxbbAjW4oZAlKGejNKO50\/Rpxx6oRCBGCx1gIEKS5+NkgJyQl0AbJCZl9hDTbxsNA4MrlZ7h0YZ\/ejINze\/zmb69iCJoTmltAUDNwx7xyaW9BrRW8kiLACtTK4eFd+m5FVAeCqAPhPtJAKbSayBEOoeCBpA2X1Ep0HSEBqtw7vIfUyt3jJSdPnRLrDgS8aYhhQDSBCF7HJn3r9ilujoYRpRJWEDe8VsKciAJDIawiHkQ4EgJhSDp4NiQlIo3ZelJSnoxfl8jIcAJoi6SM5rw5UzSN\/aYBgcOGZ3AjfHzGsIJbRZ1Nr9gIxHrCIGwgzBCEVgX5819fCUR4RLmim10eUTpsgG2YOZCHLgRAvC\/LRg8CiRif5uFwCh89wkfnx3VARJC+7+Oh8nCuPL4\/vs6y\/b\/lfObUBG7evEnOmel0SkSwWCxo2\/aR\/caNG+zt7VFrRVU5f\/78k676UOuJgI4Ob3Jut+V0DZNJw9Jakiqq0M4OODg4IKWRFh5m+XhF\/xf5QwH6xc9\/zNVn3yU5\/O73d7m4P+M739hnZydx\/pnv8emr36dpGgBevnaXi3sdz31iB4BSCsAj+\/VbJxwe93zlyj4AtVbc\/cy4+iRAR1Wwy3v84e8d33z+C5R7c3740zd4bfccw+KFMXB1+mJsTzOTrPTFqPZ+oIigmpOTMMlKN9gHVucDK3S07Hnlnys+Wc9x\/c271GIcHxauvX7E6Rv\/5umPXsVC6Abj0gJg4N7RwKxN5E2aKSXWgzFX5+k9pesHlPFfS\/XsWvwX97wRJTQmN3gAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/new-avris_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022250.4347826087\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWreszcie. Wzi\u0105\u0142em si\u0119 do roboty i przepisa\u0142em od zera kod mojego blogaska. Zupe\u0142nie nowy design, nowy framework, \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus\u003C\/a\u003E, lepsze wsparcie dla wersji j\u0119zykowych, par\u0119 nowych ficzer\u00f3w w panelu administracyjnym, rzucenie w\u0142asnego systemu komentarzy na rzecz zajebisto\u015bci \u003Ca href=\u0022https:\/\/disqus.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Disqusa\u003C\/a\u003E, rzucenie TinyMCE dla pi\u0119kna i prostoty Markdownu. Zaj\u0119\u0142o to sporo pracy, ale zdecydowanie by\u0142o warto!\u003C\/p\u003E\n\u003Cp\u003EMam nadziej\u0119, \u017ce si\u0119 spodoba! :)\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/new-avris_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022500.86956521739\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAFD0lEQVRIia2Wz4tdWRHHP1Xn3Pt+dNuvO+m0GY2jOATHzDBmoy5E3Sgogrh14d6\/wIUr3fgfjBtBXLgRN6OIIDKIoMK4GCGgTMCJmR9J6CTTmZ5+\/d6995yqcnFfMll0Bgc8m1N1qjj1rTp1v3UlIoIz1u3btymlsFjssru7OMuFo3feISKYb22xXJ6ws7Pg\/v377O\/v8+DBA5qmQVXp+57JZEI66Zg\/tU8\/DMznc0SEiEBEAEb5Z7\/8VSAgqogqDogk3J1mOkUF0ASipJSJpIgIWRKBsLkLBUISouOBANRKRECAh1PKAEkJq4RV3AyvhbAAN1RApp96LnQ6JU1mpJRxnEDI0zm5acnTGeRMmswgNaTpjEYSOSlIptpAAhRBRGimc6pVdOgRB\/ERTB06hnDCg269xLolpe\/x9Ql1tcLLwEQSudVEO5mRZ9tIkxmGNeHBpG1xTeCG9IaKItMM3Sky3xkhWCEVw1QgTVE3ymqF1YqaM53vUK0Q3QohoUOHu6MB7qC1UiUhzYTkguPkWh1fvsd2bmjaltUwYC6gKyqJlBs8KU1AUwvNdI6dntBOJ1goeWvB1myHWn2s4HrN0o8xK1z5+AVidcxr12\/RVwerDH2PheOrY7wMYAbmuBsaTrYQwhPH7x4jqzWqiUgN666gjRJiaG759le\/RDuZ8cdXr\/GtL36Ol\/7yDybbC2S+YN1sEQyIKLu7mY\/plJyE1eoU6QuXLh4gAsuTJW++fQdD8DzFhop7hWqEGR6Q8s6FH3kYooJ5ECi+adRmOqfZ3uP5z1zm1z\/5AQh892tf5sXf\/ol3B6NPE8pg9N0pw9DRrU+o61PObc2IqLQ5oznhtdJKcOvOIe91A1EGrFSslBGQVbwWkkD2cNAGcxAFs0pKCXKLaSIi+PrnX+D1t+\/wr\/+8xYsvvcxyqGhqiG6NJSMINAIPo20yxbbAjW4oZAlKGejNKO50\/Rpxx6oRCBGCx1gIEKS5+NkgJyQl0AbJCZl9hDTbxsNA4MrlZ7h0YZ\/ejINze\/zmb69iCJoTmltAUDNwx7xyaW9BrRW8kiLACtTK4eFd+m5FVAeCqAPhPtJAKbSayBEOoeCBpA2X1Ep0HSEBqtw7vIfUyt3jJSdPnRLrDgS8aYhhQDSBCF7HJn3r9ilujoYRpRJWEDe8VsKciAJDIawiHkQ4EgJhSDp4NiQlIo3ZelJSnoxfl8jIcAJoi6SM5rw5UzSN\/aYBgcOGZ3AjfHzGsIJbRZ1Nr9gIxHrCIGwgzBCEVgX5819fCUR4RLmim10eUTpsgG2YOZCHLgRAvC\/LRg8CiRif5uFwCh89wkfnx3VARJC+7+Oh8nCuPL4\/vs6y\/b\/lfObUBG7evEnOmel0SkSwWCxo2\/aR\/caNG+zt7VFrRVU5f\/78k676UOuJgI4Ob3Jut+V0DZNJw9Jakiqq0M4OODg4IKWRFh5m+XhF\/xf5QwH6xc9\/zNVn3yU5\/O73d7m4P+M739hnZydx\/pnv8emr36dpGgBevnaXi3sdz31iB4BSCsAj+\/VbJxwe93zlyj4AtVbc\/cy4+iRAR1Wwy3v84e8d33z+C5R7c3740zd4bfccw+KFMXB1+mJsTzOTrPTFqPZ+oIigmpOTMMlKN9gHVucDK3S07Hnlnys+Wc9x\/c271GIcHxauvX7E6Rv\/5umPXsVC6Abj0gJg4N7RwKxN5E2aKSXWgzFX5+k9pesHlPFfS\/XsWvwX97wRJTQmN3gAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/new-avris_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022500.86956521739\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWreszcie. Wzi\u0105\u0142em si\u0119 do roboty i przepisa\u0142em od zera kod mojego blogaska. Zupe\u0142nie nowy design, nowy framework, \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-cogs\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Micrus\u003C\/a\u003E, lepsze wsparcie dla wersji j\u0119zykowych, par\u0119 nowych ficzer\u00f3w w panelu administracyjnym, rzucenie w\u0142asnego systemu komentarzy na rzecz zajebisto\u015bci \u003Ca href=\u0022https:\/\/disqus.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Disqusa\u003C\/a\u003E, rzucenie TinyMCE dla pi\u0119kna i prostoty Markdownu. Zaj\u0119\u0142o to sporo pracy, ale zdecydowanie by\u0142o warto!\u003C\/p\u003E\n\u003Cp\u003EMam nadziej\u0119, \u017ce si\u0119 spodoba! :)\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["design","framework","komentarz","markdown","php","praca","programowanie","redesign","tinymce"],"hasMore":false,"image":"https:\/\/avris.it\/image\/new-avris_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/new-avris_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/new-avris_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022125.21739130435\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWreszcie. Wzi\u0105\u0142em si\u0119 do roboty i przepisa\u0142em od zera kod mojego blogaska. Zupe\u0142nie nowy design, nowy framework, \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework.lite\u0022\u003E Micrus\u003C\/a\u003E, lepsze wsparcie dla wersji j\u0119zykowych, par\u0119 nowych ficzer\u00f3w w panelu administracyjnym, rzucenie w\u0142asnego systemu komentarzy na rzecz zajebisto\u015bci \u003Ca href=\u0022https:\/\/disqus.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Disqusa\u003C\/a\u003E, rzucenie TinyMCE dla pi\u0119kna i prostoty Markdownu. Zaj\u0119\u0142o to sporo pracy, ale zdecydowanie by\u0142o warto!\u003C\/p\u003E\n\u003Cp\u003EMam nadziej\u0119, \u017ce si\u0119 spodoba! :)\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/new-avris_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/new-avris_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022125.21739130435\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EWreszcie. Wzi\u0105\u0142em si\u0119 do roboty i przepisa\u0142em od zera kod mojego blogaska. Zupe\u0142nie nowy design, nowy framework, \u003Ca href=\u0022\/projects\/micrus-tiny-yet-powerful-php-framework.lite\u0022\u003E Micrus\u003C\/a\u003E, lepsze wsparcie dla wersji j\u0119zykowych, par\u0119 nowych ficzer\u00f3w w panelu administracyjnym, rzucenie w\u0142asnego systemu komentarzy na rzecz zajebisto\u015bci \u003Ca href=\u0022https:\/\/disqus.com\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Disqusa\u003C\/a\u003E, rzucenie TinyMCE dla pi\u0119kna i prostoty Markdownu. Zaj\u0119\u0142o to sporo pracy, ale zdecydowanie by\u0142o warto!\u003C\/p\u003E\n\u003Cp\u003EMam nadziej\u0119, \u017ce si\u0119 spodoba! :)\u003C\/p\u003E","words":67,"readTime":null,"lang":"pl"}}},"blog\/technology\/rewarding-for-loc":{"key":"blog\/technology\/rewarding-for-loc","type":"article","published":true,"meta":{"createdAt":"2017-04-28T19:44:05+02:00","publishedAt":"2016-12-30T17:43:00+01:00","group":null,"category":"blog","subcategory":"technology","slug":"rewarding-for-loc"},"content":{"pl":{"slug":"rewarding-for-loc","title":"Rewarding for LOC","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/rewarding-for-loc_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270.14492753623\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHX0lEQVRIiY2WyZIcSRGGv4iMjFxqX7q6epHUUksjYZqBMU5cuGCceBoegRtPwLtw4sCFA4yxDEhCJqkldVV3115ZWZmVW2Rw6GEwwwwzfr95mJu7\/x4Rv4vf\/u4P1grFdpeSpAc8z6csShylUEoipYMVMI9KytKAFSAAQEoH13WQUoIQWBwKY9COQ1mWaM8DoLZQ5DnW1mBrHCmpa3MfBwTa4YvzFh9nbxHv\/vzemsBS1zlJusPEEUG7jxASISy1yACF67pUdY\/z8xFZVvDx3QeOxyNWm5LxcUCRzwnKIUVQ02y3SdOSdRKxKWc8O3qGpxQAnz7NOTnp0e22yKqS608Tmjrk+OyIyWaFGp2OqNwKK2qyyscrj+mPLwDYbla0wpDlbI4OXIwRNEOF5xqO+g3y3LKzM7x1k22U4OsMk2nE9RppD7T7bV74l0z\/eoXUNVIF2KBCOgOCIEBWLuvlhiquaCYNOoGPmryfYjuC1WpGud0yHnfIapeqMnh+g\/1kha0kdW2ZzWNMJSiKktnccPmsiWd80uiawDZ5fHHCbBkzPJMo5aFcgVR7VH\/LsD\/A5AeurqZEWnPz5jM4Au369J922SYLOmqAOjobMNvNsMbQ8xPGp8\/xQo\/lOmZ5s+TiYkyj2wGge5zxpz++gSqidz7E2BLPr8ndAbtNwaubiHK3Y\/CowXwyhVJR1xWjB0fc7SOO2scIf8T15J8cjx4R5JrheQsrgV2OdQrUPDE8ubyk0+2w241Y\/u2OxlEKwqMfdqgPKZnrYmpJmWW8\/OohWRzz7dVbZp2aYhvzw4sxxK9Y46MOhux9i\/7JBYG3JhYNeicvaWyu+cs3M\/D2fPHFC\/bJlpQdvXwEStPohmw3K0SW59bTGoAiL1gsFwQkbKMlRVHi7Ftk4oAcjOg2KrK6xlawXN8wO\/T50YMG7bDDzce\/MzOWPFnz9dPnbNZ3KFOQVpCWNcNxQLKxxFnG04uXtAYj\/jGZcHl8wqg\/AOD2wxRlsVhrAYj3Mbc3N6hojdSCoH2C8MFruVgyZpuIB09esJ5OaLpndJsw6B0xvfoGLeCnX31JnlYICfkBTBah8g2HOMcdDmi2Okw+3TJ3b2mGfX589gQhJMW+wFQVyT5DvZp+y8htcDQ8Q5qI8bCBOh2SRDPId+zWJc2wjzEZN29vMUnKbudz3qvJhOZ6WqOLLcJo3rxfEO1jai\/lotMjy3eUVLx4dkqvP2Q3n\/DkicPx4Clew8VSck8FLDZL9jpBvRj\/AFfeux2lCIIAnJDcSGpjiPIEIkF\/OKIXNnjU\/ZppeodulJhsx2r1AV1bQmnodpc0m5pW4OA4CZ2TPnd3U+r9lOtoh8p6bNI7un5Cqw74N2xd8XZyy1HYwfnFz37+q26vQVUZQCEdF+lAuk8RtUszbJBXht0mJi23RGFKoBykU1PLBp7XZjB6gVFtDkFI0WiRCIgLidRtev0T0D1m0zmL0kF6bUbtkEZLIG2JxJDsEyhTmn4PdbNRuB8W7KI1Ub3jrDVEBy2yIsfRGaetMeW+RFYOgQ6RWqK0RBwSRGHw0awXr0mKjNZowHK\/ZtAcAIJVFDOvSqqqIjMuoeeQ7JfI8CVue\/A9Q\/2WpXl0zrs3rxFperCedu+p416mLFAWFVW+Y3E1IRUJySFC5pbTB8\/JDgfmsyk4bQBurhf0Rj2Czn\/G8L8gBFyePGXwoPdfJ5bbyTXi7sPEald9VwYI5SOEQ1UZsizBHip09z5xst+g8NgsIhKxoSoclMoYui3c74T0\/4H0A4QvwUKn1\/leZOM0Q6Tx2mrtcjP5jKddesMxjm7w+dMKXxY4VY3bvf+nPn\/+SCfsMj4dk+UFlZV4dUQtuyjtYKuc\/ewTm0gimoKHj55jqpx4u8IN+tRWU5clDfcOG55TFgVKuaRZQpoeEEKipA4pS8t+EbAiJdpck+aa5cLw+MJl1O7i+vcMSimoiwVZ1Wd\/KNDCcLXc0ejmhLpLGHh0nnxJ\/P4jvcDh3etXQMLJ+BQrLMtVTJVk+He\/x3v+E1wdsN+n4PdQQrHd7BA312urXUW02lLHGbmTE+9iRg+OOBqfIQ\/3o3SV4na1xDsYrM7IipQtS8IiRLRqtPbxgybau79HWZTzcfqGRtNjNDqjyA7Euxm+bpFuE1S7R5lUmIODdB32RYp0DGK9jq3WijwvkHvYbucEA0WVLajdJsq6xKni5GzE9e1ndF1RS4lgwPAoIPAVWSFZXmfE0RS\/aTg9vgQlcHyLcu4bqqoa5Up28zmvkyte9B5iCsXJwwvquma73VJVBnHIcutplzQ5cHN7SxbP6R6dY21BuQZdpwyeP6auHRbRHRIfIWqMkYClMjXJ\/kCytwRhjVICgaS2NbayhIEPCLIyx7ElMksZXDwGBFJYBoP\/PP8kSRG\/\/PVvbEe6SC8kEBXznWWbugS+piwMQoDn+9jvTGof5dxvkxiLqSxlXoIAIQRlZRBWYK1BOwqhJIcqJS9LsAIpaqTjEgQernIQJsXXYKoKY2r+BZhY4dSc6tPoAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/rewarding-for-loc_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022270.14492753623\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI stumbled upon a company that rewards their developers for the number of committed lines of code, and generally for the number of commits. What an utterly idiotic idea!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/rewarding-for-loc_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540.28985507246\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHX0lEQVRIiY2WyZIcSRGGv4iMjFxqX7q6epHUUksjYZqBMU5cuGCceBoegRtPwLtw4sCFA4yxDEhCJqkldVV3115ZWZmVW2Rw6GEwwwwzfr95mJu7\/x4Rv4vf\/u4P1grFdpeSpAc8z6csShylUEoipYMVMI9KytKAFSAAQEoH13WQUoIQWBwKY9COQ1mWaM8DoLZQ5DnW1mBrHCmpa3MfBwTa4YvzFh9nbxHv\/vzemsBS1zlJusPEEUG7jxASISy1yACF67pUdY\/z8xFZVvDx3QeOxyNWm5LxcUCRzwnKIUVQ02y3SdOSdRKxKWc8O3qGpxQAnz7NOTnp0e22yKqS608Tmjrk+OyIyWaFGp2OqNwKK2qyyscrj+mPLwDYbla0wpDlbI4OXIwRNEOF5xqO+g3y3LKzM7x1k22U4OsMk2nE9RppD7T7bV74l0z\/eoXUNVIF2KBCOgOCIEBWLuvlhiquaCYNOoGPmryfYjuC1WpGud0yHnfIapeqMnh+g\/1kha0kdW2ZzWNMJSiKktnccPmsiWd80uiawDZ5fHHCbBkzPJMo5aFcgVR7VH\/LsD\/A5AeurqZEWnPz5jM4Au369J922SYLOmqAOjobMNvNsMbQ8xPGp8\/xQo\/lOmZ5s+TiYkyj2wGge5zxpz++gSqidz7E2BLPr8ndAbtNwaubiHK3Y\/CowXwyhVJR1xWjB0fc7SOO2scIf8T15J8cjx4R5JrheQsrgV2OdQrUPDE8ubyk0+2w241Y\/u2OxlEKwqMfdqgPKZnrYmpJmWW8\/OohWRzz7dVbZp2aYhvzw4sxxK9Y46MOhux9i\/7JBYG3JhYNeicvaWyu+cs3M\/D2fPHFC\/bJlpQdvXwEStPohmw3K0SW59bTGoAiL1gsFwQkbKMlRVHi7Ftk4oAcjOg2KrK6xlawXN8wO\/T50YMG7bDDzce\/MzOWPFnz9dPnbNZ3KFOQVpCWNcNxQLKxxFnG04uXtAYj\/jGZcHl8wqg\/AOD2wxRlsVhrAYj3Mbc3N6hojdSCoH2C8MFruVgyZpuIB09esJ5OaLpndJsw6B0xvfoGLeCnX31JnlYICfkBTBah8g2HOMcdDmi2Okw+3TJ3b2mGfX589gQhJMW+wFQVyT5DvZp+y8htcDQ8Q5qI8bCBOh2SRDPId+zWJc2wjzEZN29vMUnKbudz3qvJhOZ6WqOLLcJo3rxfEO1jai\/lotMjy3eUVLx4dkqvP2Q3n\/DkicPx4Clew8VSck8FLDZL9jpBvRj\/AFfeux2lCIIAnJDcSGpjiPIEIkF\/OKIXNnjU\/ZppeodulJhsx2r1AV1bQmnodpc0m5pW4OA4CZ2TPnd3U+r9lOtoh8p6bNI7un5Cqw74N2xd8XZyy1HYwfnFz37+q26vQVUZQCEdF+lAuk8RtUszbJBXht0mJi23RGFKoBykU1PLBp7XZjB6gVFtDkFI0WiRCIgLidRtev0T0D1m0zmL0kF6bUbtkEZLIG2JxJDsEyhTmn4PdbNRuB8W7KI1Ub3jrDVEBy2yIsfRGaetMeW+RFYOgQ6RWqK0RBwSRGHw0awXr0mKjNZowHK\/ZtAcAIJVFDOvSqqqIjMuoeeQ7JfI8CVue\/A9Q\/2WpXl0zrs3rxFperCedu+p416mLFAWFVW+Y3E1IRUJySFC5pbTB8\/JDgfmsyk4bQBurhf0Rj2Czn\/G8L8gBFyePGXwoPdfJ5bbyTXi7sPEald9VwYI5SOEQ1UZsizBHip09z5xst+g8NgsIhKxoSoclMoYui3c74T0\/4H0A4QvwUKn1\/leZOM0Q6Tx2mrtcjP5jKddesMxjm7w+dMKXxY4VY3bvf+nPn\/+SCfsMj4dk+UFlZV4dUQtuyjtYKuc\/ewTm0gimoKHj55jqpx4u8IN+tRWU5clDfcOG55TFgVKuaRZQpoeEEKipA4pS8t+EbAiJdpck+aa5cLw+MJl1O7i+vcMSimoiwVZ1Wd\/KNDCcLXc0ejmhLpLGHh0nnxJ\/P4jvcDh3etXQMLJ+BQrLMtVTJVk+He\/x3v+E1wdsN+n4PdQQrHd7BA312urXUW02lLHGbmTE+9iRg+OOBqfIQ\/3o3SV4na1xDsYrM7IipQtS8IiRLRqtPbxgybau79HWZTzcfqGRtNjNDqjyA7Euxm+bpFuE1S7R5lUmIODdB32RYp0DGK9jq3WijwvkHvYbucEA0WVLajdJsq6xKni5GzE9e1ndF1RS4lgwPAoIPAVWSFZXmfE0RS\/aTg9vgQlcHyLcu4bqqoa5Up28zmvkyte9B5iCsXJwwvquma73VJVBnHIcutplzQ5cHN7SxbP6R6dY21BuQZdpwyeP6auHRbRHRIfIWqMkYClMjXJ\/kCytwRhjVICgaS2NbayhIEPCLIyx7ElMksZXDwGBFJYBoP\/PP8kSRG\/\/PVvbEe6SC8kEBXznWWbugS+piwMQoDn+9jvTGof5dxvkxiLqSxlXoIAIQRlZRBWYK1BOwqhJIcqJS9LsAIpaqTjEgQernIQJsXXYKoKY2r+BZhY4dSc6tPoAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/rewarding-for-loc_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022540.28985507246\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI stumbled upon a company that rewards their developers for the number of committed lines of code, and generally for the number of commits. What an utterly idiotic idea!\u003C\/p\u003E\n\u003Cp\u003EThe thing is, it\u2019s \u003Cstrong\u003Enot that hard to write a code that works\u003C\/strong\u003E. It\u2019s not hard to write \u003Cem\u003Ea lot\u003C\/em\u003E. With enough hard work and enough attempts everybody can achieve it. But the true skill, and the reason that qualified programmers are so well-paid, lies in the ability to write \u003Cstrong\u003Egood code\u003C\/strong\u003E. Clear, simple, short, without duplication, understandable without any comments or introductions.\u003C\/p\u003E\n\u003Cp\u003EWriting some repeatable code in ten places makes you earn 10x more LOC than just wrapping it in a reusable function. But if you ever need to come back to that code, understand it and modify it, having it abstracted to a function makes it 10x faster and easier.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EGood design and maintainability\u003C\/strong\u003E are worth so much more than just a sheer number of lines.\u003C\/p\u003E\n\u003Cp\u003EAnother example: every serious developer knows that dependencies shouldn\u2019t be included in the repo. We have Composer, Bower, NPM, Gem and so many others to handle the dependencies! But imagine your boss pays you for LOC, and you could \u201cearn\u201d millions of them just by commiting all the external libraries to the repo... Could you resist?\u003C\/p\u003E\n\u003Cp\u003EIn the and, the \u201cmost active\u201d programmer in that company turned out... not to be a programmer at all! He just set up all the new projects with bootstrap code. Surprise, isn\u2019t it?\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["code quality","developer","experience","lines of code","loc","motivation","programmer","programming","spaghetti code"],"hasMore":true,"image":"https:\/\/avris.it\/image\/rewarding-for-loc_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/rewarding-for-loc_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/rewarding-for-loc_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135.07246376812\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI stumbled upon a company that rewards their developers for the number of committed lines of code, and generally for the number of commits. What an utterly idiotic idea!\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/rewarding-for-loc_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/rewarding-for-loc_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022135.07246376812\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EI stumbled upon a company that rewards their developers for the number of committed lines of code, and generally for the number of commits. What an utterly idiotic idea!\u003C\/p\u003E\n\u003Cp\u003EThe thing is, it\u2019s \u003Cstrong\u003Enot that hard to write a code that works\u003C\/strong\u003E. It\u2019s not hard to write \u003Cem\u003Ea lot\u003C\/em\u003E. With enough hard work and enough attempts everybody can achieve it. But the true skill, and the reason that qualified programmers are so well-paid, lies in the ability to write \u003Cstrong\u003Egood code\u003C\/strong\u003E. Clear, simple, short, without duplication, understandable without any comments or introductions.\u003C\/p\u003E\n\u003Cp\u003EWriting some repeatable code in ten places makes you earn 10x more LOC than just wrapping it in a reusable function. But if you ever need to come back to that code, understand it and modify it, having it abstracted to a function makes it 10x faster and easier.\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003EGood design and maintainability\u003C\/strong\u003E are worth so much more than just a sheer number of lines.\u003C\/p\u003E\n\u003Cp\u003EAnother example: every serious developer knows that dependencies shouldn\u2019t be included in the repo. We have Composer, Bower, NPM, Gem and so many others to handle the dependencies! But imagine your boss pays you for LOC, and you could \u201cearn\u201d millions of them just by commiting all the external libraries to the repo... Could you resist?\u003C\/p\u003E\n\u003Cp\u003EIn the and, the \u201cmost active\u201d programmer in that company turned out... not to be a programmer at all! He just set up all the new projects with bootstrap code. Surprise, isn\u2019t it?\u003C\/p\u003E","words":250,"readTime":null,"lang":"pl"}}},"blog\/technology\/exporting-playlists-from-google-play-music-to-spotify":{"key":"blog\/technology\/exporting-playlists-from-google-play-music-to-spotify","type":"article","published":true,"meta":{"createdAt":"2017-04-28T19:43:58+02:00","publishedAt":"2016-08-10T22:33:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"exporting-playlists-from-google-play-music-to-spotify"},"content":{"en":{"slug":"exporting-playlists-from-google-play-music-to-spotify","title":"Exporting playlists from Google Play Music to Spotify","intro":"\u003Cp\u003ESpotify is so much better than Google Play Music! Whether it\u2019s in the field of cool features (like using your smartphone to control the music on your computer) or just basic user experience (like ability to filter songs inside a playlist) \u2013 Spotify wins by far!\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cp\u003ESpotify is so much better than Google Play Music! Whether it\u2019s in the field of cool features (like using your smartphone to control the music on your computer) or just basic user experience (like ability to filter songs inside a playlist) \u2013 Spotify wins by far!\u003C\/p\u003E\n\u003Cp\u003EThere\u2019s just one thing that for the past two months was stopping me from migrating to Spotify. Neither in Spotify nor in GPM can you export or import a list of songs. Really! And I really don\u2019t have time to search for all my songs again...\u003C\/p\u003E\n\u003Cp\u003EFortunately, there\u2019s \u003Ca href=\u0022https:\/\/soundiiz.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Soundiiz\u003C\/a\u003E! This fancy tool allows you to migrate playlists between different streaming services. Among which... there\u2019s no GPM, because of course there isn\u2019t. Oh, damn you, Google!\u003C\/p\u003E\n\u003Cp\u003EWe can however upload a text file (in format \u003Ccode\u003EArtist\u00a0-\u00a0Title\u003C\/code\u003E for each line) to Soundiiz and it will automatically find our songs in the Spotify database, creating a playlist. Cool! So now we only have to create such file.\u003C\/p\u003E\n\u003Cp\u003EWe might just scrape the data from GPM\u2019s HTML, couldn\u2019t we? Well, Google doesn\u2019t make it easy. It loads the list of songs dynamically while you\u2019re scrolling... Oh, damn you, Google!\u003C\/p\u003E\n\u003Cp\u003EAnyways, my solution is:\u003C\/p\u003E\n\u003Col\u003E\n\u003Cli\u003EOpen GPM, chose the playlist in that you\u2019d like to export.\u003C\/li\u003E\n\u003Cli\u003EOpen the JavaScript console (in Chrome it\u2019s \u003Ccode\u003ECtrl+Alt+J\u003C\/code\u003E, in Firefox \u003Ccode\u003ECtrl+Alt+K\u003C\/code\u003E).\u003C\/li\u003E\n\u003Cli\u003EPaste the following code:\u003C\/li\u003E\n\u003C\/ol\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E fetched = [];\n\u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Efetch\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003E\u003C\/span\u003E) \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E playlist = \u003Cspan class=\u0022hljs-built_in\u0022\u003Edocument\u003C\/span\u003E.querySelectorAll(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.song-table tr.song-row\u0027\u003C\/span\u003E);\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Efor\u003C\/span\u003E(\u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E i = \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E; i \u0026lt; playlist.length; i++) {\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E title = playlist[i].querySelectorAll(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027td[data-col=\u0022title\u0022] .column-content\u0027\u003C\/span\u003E)[\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E].textContent;\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E artist = playlist[i].querySelectorAll(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027td[data-col=\u0022artist\u0022] .column-content\u0027\u003C\/span\u003E)[\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E].textContent;\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E row = artist + \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027 - \u0027\u003C\/span\u003E + title;\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (fetched.indexOf(row) == \u003Cspan class=\u0022hljs-number\u0022\u003E-1\u003C\/span\u003E) {\n            fetched.push(row);\n        }\n    }\n    \u003Cspan class=\u0022hljs-built_in\u0022\u003Econsole\u003C\/span\u003E.log(fetched.length);\n}\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Evar\u003C\/span\u003E interval = setInterval(fetch, \u003Cspan class=\u0022hljs-number\u0022\u003E100\u003C\/span\u003E);\n\u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Edone\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003E\u003C\/span\u003E) \u003C\/span\u003E{\n    clearInterval(interval);\n    \u003Cspan class=\u0022hljs-built_in\u0022\u003Econsole\u003C\/span\u003E.log(fetched.join(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022\\n\u0022\u003C\/span\u003E));\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Col start=\u00224\u0022\u003E\n\u003Cli\u003EScroll down through your playlist. You should see growing numbers appearing in the console. When you\u2019re done scrolling, this number should be equal to the number of songs in the playlist.\u003C\/li\u003E\n\u003Cli\u003EType \u003Ccode\u003Edone();\u003C\/code\u003E and you should see the list of your songs.\u003C\/li\u003E\n\u003Cli\u003ENow just copy-paste it to a file and save it.\u003C\/li\u003E\n\u003Cli\u003EGo to \u003Ca href=\u0022https:\/\/soundiiz.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Soundiiz\u003C\/a\u003E and connect with your Spotify account.\u003C\/li\u003E\n\u003Cli\u003EUpload the file.\u003C\/li\u003E\n\u003Cli\u003ERelax ;-)\u003C\/li\u003E\n\u003C\/ol\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["export","google play music","javascript","music","playlist","spotify","streaming"],"hasMore":true,"image":null,"introLite":"\u003Cp\u003ESpotify is so much better than Google Play Music! Whether it\u2019s in the field of cool features (like using your smartphone to control the music on your computer) or just basic user experience (like ability to filter songs inside a playlist) \u2013 Spotify wins by far!\u003C\/p\u003E","contentLite":"\u003Cp\u003ESpotify is so much better than Google Play Music! Whether it\u2019s in the field of cool features (like using your smartphone to control the music on your computer) or just basic user experience (like ability to filter songs inside a playlist) \u2013 Spotify wins by far!\u003C\/p\u003E\n\u003Cp\u003EThere\u2019s just one thing that for the past two months was stopping me from migrating to Spotify. Neither in Spotify nor in GPM can you export or import a list of songs. Really! And I really don\u2019t have time to search for all my songs again...\u003C\/p\u003E\n\u003Cp\u003EFortunately, there\u2019s \u003Ca href=\u0022https:\/\/soundiiz.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Soundiiz\u003C\/a\u003E! This fancy tool allows you to migrate playlists between different streaming services. Among which... there\u2019s no GPM, because of course there isn\u2019t. Oh, damn you, Google!\u003C\/p\u003E\n\u003Cp\u003EWe can however upload a text file (in format \u003Ccode\u003EArtist\u00a0-\u00a0Title\u003C\/code\u003E for each line) to Soundiiz and it will automatically find our songs in the Spotify database, creating a playlist. Cool! So now we only have to create such file.\u003C\/p\u003E\n\u003Cp\u003EWe might just scrape the data from GPM\u2019s HTML, couldn\u2019t we? Well, Google doesn\u2019t make it easy. It loads the list of songs dynamically while you\u2019re scrolling... Oh, damn you, Google!\u003C\/p\u003E\n\u003Cp\u003EAnyways, my solution is:\u003C\/p\u003E\n\u003Col\u003E\n\u003Cli\u003EOpen GPM, chose the playlist in that you\u2019d like to export.\u003C\/li\u003E\n\u003Cli\u003EOpen the JavaScript console (in Chrome it\u2019s \u003Ccode\u003ECtrl+Alt+J\u003C\/code\u003E, in Firefox \u003Ccode\u003ECtrl+Alt+K\u003C\/code\u003E).\u003C\/li\u003E\n\u003Cli\u003EPaste the following code:\u003C\/li\u003E\n\u003C\/ol\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-js\u0022\u003Evar fetched = [];\nfunction fetch() {\n    var playlist = document.querySelectorAll(\u0027.song-table tr.song-row\u0027);\n    for(var i = 0; i \u0026lt; playlist.length; i++) {\n        var title = playlist[i].querySelectorAll(\u0027td[data-col=\u0022title\u0022] .column-content\u0027)[0].textContent;\n        var artist = playlist[i].querySelectorAll(\u0027td[data-col=\u0022artist\u0022] .column-content\u0027)[0].textContent;\n        var row = artist + \u0027 - \u0027 + title;\n        if (fetched.indexOf(row) == -1) {\n            fetched.push(row);\n        }\n    }\n    console.log(fetched.length);\n}\nvar interval = setInterval(fetch, 100);\nfunction done() {\n    clearInterval(interval);\n    console.log(fetched.join(\u0022\\n\u0022));\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Col start=\u00224\u0022\u003E\n\u003Cli\u003EScroll down through your playlist. You should see growing numbers appearing in the console. When you\u2019re done scrolling, this number should be equal to the number of songs in the playlist.\u003C\/li\u003E\n\u003Cli\u003EType \u003Ccode\u003Edone();\u003C\/code\u003E and you should see the list of your songs.\u003C\/li\u003E\n\u003Cli\u003ENow just copy-paste it to a file and save it.\u003C\/li\u003E\n\u003Cli\u003EGo to \u003Ca href=\u0022https:\/\/soundiiz.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Soundiiz\u003C\/a\u003E and connect with your Spotify account.\u003C\/li\u003E\n\u003Cli\u003EUpload the file.\u003C\/li\u003E\n\u003Cli\u003ERelax ;-)\u003C\/li\u003E\n\u003C\/ol\u003E","words":377,"readTime":2,"lang":"en"}}},"blog\/technology\/avris-can-into-https":{"key":"blog\/technology\/avris-can-into-https","type":"article","published":true,"meta":{"createdAt":"2017-04-28T19:43:50+02:00","publishedAt":"2016-04-22T10:30:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"avris-can-into-https"},"content":{"pl":{"slug":"avris-can-into-https","title":"Avris can into HTTPS!","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-can-into-https_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022244.52830188679\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADQklEQVRIic2Wy24cVRCGv3Pr6e6ZjGdsy+NLjJ0FUlZeseMNeBhYIFaI52DHig0PwDOwRggJSJAviUKM7zOame4+fU6x6MnYsS3sEEuhNtVdqq7z11\/Vf7c6\/PoLUcGj+PAWWxn21aefcfrtdzz65kuUUnQ6HcqypNvt0v\/riGRpkcPE8PzZM1YGA3Z2dt7pkIODAxb7fYqyZDQcsrq2xtnZGd57tNZsbm6yv7ePSxyD1VXU7s+\/yIvvf+DpV58zmUzodDrEGMmyDDuZolCMNNR1TZIk9Pt9lFKICEo1vIoIwFvx2\/xdOSEEVFl5+fvwNQA6SamiJQo4A2Ut1CKkVtPWnjRNyfMcUIDMPLNrrsVv8\/+eEyRitdYURcHy8jInJ8cNM85R+xpdTOnlOYOVAaBu7eohGSIIFsB7z+npKc4ljMcT8jynKAqMMYzHE04uxvgIITYF1xfb77RH12049ewdTkisxteRiNBvWzaW8gbQ4+3tGZsKZp10r7x3USImRqI0KeOyfC9AIQSyVsRowZqGHa0jABaE34ZDjDGICC93dzHasL699V6Hjkcjzo6PqauKjSdPcEkCcDmeBHZ\/\/4O802awsUEMFWt0UL6uZf9iSOIsUQRBUDeWsGGmubufYkURtHo7V2aArscBqtqz1V1oAFV1jQGsc\/z40x4frXYZFZFHmUUEiiqAgqePu\/TayeVo3xSejflq\/Pz8nLIoKMsSYy1aKaxz9Ps9rLGg4NXkOYN0C6Mc06oksa4BVHpPmiREAV+VOOfQWt9\/PjdMURQFvqpwiUNEMMaQJMmtzAFMq4rUuWaplVIgoBX8+nJMVYNIpGUtn3zcnx9ySfzdOiQxIBIZzfYzxog2hl5vAa0toKjihERnc3KBBhBAWRa00pQeZywsLSAitNvJZc9XpnPXxFDNDnnvcc7N2cmyjDjXI2FUn7DgVrAqmbemfB1kXExx1iIixBjQ2sxF77\/aVeG8T9zXNe00bRgKZYmfTnHOYa0lb7VuVeGrBR9aqfNWixACVsGND+abhz+E2RAj\/C\/+hiBEwdah5ujoFFDEGDDGcBFSUqfJKAghEEXIs4xer\/egAP58fYHRmjpEWtawvpTzDwD\/5hoCfecpAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-can-into-https_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022244.52830188679\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003E\u003Ca href=\u0022https:\/\/letsencrypt.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Let\u2019s encrypt\u003C\/a\u003E\u003C\/strong\u003E jest projektem d\u0105\u017c\u0105cym do maksymalizacji dost\u0119pno\u015bci do certyfikat\u00f3w SSL \u2013 i chyba najlepsz\u0105 rzecz\u0105, jaka mnie ostatnio spotka\u0142a.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-can-into-https_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022489.05660377358\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAASCAYAAAAzI3woAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADQklEQVRIic2Wy24cVRCGv3Pr6e6ZjGdsy+NLjJ0FUlZeseMNeBhYIFaI52DHig0PwDOwRggJSJAviUKM7zOame4+fU6x6MnYsS3sEEuhNtVdqq7z11\/Vf7c6\/PoLUcGj+PAWWxn21aefcfrtdzz65kuUUnQ6HcqypNvt0v\/riGRpkcPE8PzZM1YGA3Z2dt7pkIODAxb7fYqyZDQcsrq2xtnZGd57tNZsbm6yv7ePSxyD1VXU7s+\/yIvvf+DpV58zmUzodDrEGMmyDDuZolCMNNR1TZIk9Pt9lFKICEo1vIoIwFvx2\/xdOSEEVFl5+fvwNQA6SamiJQo4A2Ut1CKkVtPWnjRNyfMcUIDMPLNrrsVv8\/+eEyRitdYURcHy8jInJ8cNM85R+xpdTOnlOYOVAaBu7eohGSIIFsB7z+npKc4ljMcT8jynKAqMMYzHE04uxvgIITYF1xfb77RH12049ewdTkisxteRiNBvWzaW8gbQ4+3tGZsKZp10r7x3USImRqI0KeOyfC9AIQSyVsRowZqGHa0jABaE34ZDjDGICC93dzHasL699V6Hjkcjzo6PqauKjSdPcEkCcDmeBHZ\/\/4O802awsUEMFWt0UL6uZf9iSOIsUQRBUDeWsGGmubufYkURtHo7V2aArscBqtqz1V1oAFV1jQGsc\/z40x4frXYZFZFHmUUEiiqAgqePu\/TayeVo3xSejflq\/Pz8nLIoKMsSYy1aKaxz9Ps9rLGg4NXkOYN0C6Mc06oksa4BVHpPmiREAV+VOOfQWt9\/PjdMURQFvqpwiUNEMMaQJMmtzAFMq4rUuWaplVIgoBX8+nJMVYNIpGUtn3zcnx9ySfzdOiQxIBIZzfYzxog2hl5vAa0toKjihERnc3KBBhBAWRa00pQeZywsLSAitNvJZc9XpnPXxFDNDnnvcc7N2cmyjDjXI2FUn7DgVrAqmbemfB1kXExx1iIixBjQ2sxF77\/aVeG8T9zXNe00bRgKZYmfTnHOYa0lb7VuVeGrBR9aqfNWixACVsGND+abhz+E2RAj\/C\/+hiBEwdah5ujoFFDEGDDGcBFSUqfJKAghEEXIs4xer\/egAP58fYHRmjpEWtawvpTzDwD\/5hoCfecpAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/avris-can-into-https_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022489.05660377358\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003E\u003Ca href=\u0022https:\/\/letsencrypt.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Let\u2019s encrypt\u003C\/a\u003E\u003C\/strong\u003E jest projektem d\u0105\u017c\u0105cym do maksymalizacji dost\u0119pno\u015bci do certyfikat\u00f3w SSL \u2013 i chyba najlepsz\u0105 rzecz\u0105, jaka mnie ostatnio spotka\u0142a.\u003C\/p\u003E\n\u003Cp\u003ES\u0105 dwa powody, dla kt\u00f3rych nigdy nie zg\u0142\u0119bi\u0142em tematu szyfrowania po\u0142\u0105cze\u0144 HTTP: \u003Cstrong\u003Ewysoka cena\u003C\/strong\u003E certyfikat\u00f3w oraz \u003Cstrong\u003Ekoszmarna konfiguracja\u003C\/strong\u003E serwera. Szczerze m\u00f3wi\u0105c, nie wiem jak bardzo wysoka, bo w zale\u017cno\u015bci od wielu czynnik\u00f3w ceny r\u00f3\u017cni\u0105 si\u0119 nawet o dwa rz\u0119dy wielko\u015bci, ani jak bardzo koszmarna, bo jedna kr\u00f3tka przygoda z konfiguracj\u0105 certyfikat\u00f3w zdo\u0142a\u0142a skutecznie odstraszy\u0107 mnie od tematu.\u003C\/p\u003E\n\u003Cp\u003EA to bardzo niedobrze. Je\u015bli \u0142\u0105czysz si\u0119 z ze stron\u0105, kt\u00f3ra nie szyfruje ruchu, to nie do\u015b\u0107, ze nie masz poj\u0119cia, czy dane z \u003Cem\u003Eexample.com\u003C\/em\u003E rzeczywi\u015bcie pochodz\u0105 z \u003Cem\u003Eexample.com\u003C\/em\u003E, czy tylko kto\u015b si\u0119 pod nich podszy\u0142, to jeszcze wszystkie dane, kt\u00f3re mi\u0119dzy sob\u0105 wymieniacie (w\u0142\u0105cznie z has\u0142ami), lataj\u0105 sobie po sieci zapisane czystym tekstem!\u003C\/p\u003E\n\u003Cp\u003EInternet chce z tym walczy\u0107. Mam nieoficjalne informacje, \u017ce Google chc\u0105 \u201cwkr\u00f3tce\u201d przestawi\u0107 Chrome na tryb \u201ctylko HTTPS\u201d. P\u00f3ki co, strony z poprawnym certyfikatem s\u0105 oznaczane zielon\u0105 k\u0142\u00f3dk\u0105 przy adresie, te z niepoprawnym \u2013 czerwon\u0105, a te bez certyfikatu \u2013 wcale. Aby zach\u0119ci\u0107 ludzi do u\u017cywania HTTPS, te ostatnie nied\u0142ugo r\u00f3wnie\u017c b\u0119d\u0105 czerwone. Dla w\u0142a\u015bcicieli stron nie jest to przyjemna perspektywa.\u003C\/p\u003E\n\u003Cp\u003EWtem, na ratunek przybywa Let\u2019s encrypt. Dzi\u0119ki sponsoringowi wielkich firm, oferuj\u0105 certyfikaty \u003Cstrong\u003Ezupe\u0142nie za darmo.\u003C\/strong\u003E A do tego udost\u0119pniaj\u0105 narz\u0119dzie, dzi\u0119ki kt\u00f3remu konfiguracja certyfikatu na serwerze Apache pod Debianem to \u003Cstrong\u003Eraptem jedno polecenie w konsoli!\u003C\/strong\u003E (pod innymi platformami jest ciut gorzej, ale wci\u0105\u017c o wiele \u0142atwiej ni\u017c w przypadku r\u0119cznej konfiguracji).\u003C\/p\u003E\n\u003Cp\u003EMinusy? Projekt dopiero co wyszed\u0142 z bety, wi\u0119c nie ma co oczekiwa\u0107 fajerwerk\u00f3w takich jak \u003Ca href=\u0022https:\/\/github.com\/letsencrypt\/letsencrypt\/issues\/66\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E wildcards\u003C\/a\u003E (kt\u00f3re akruat bardzo by mi si\u0119 przyda\u0142y). No i wiadomo, \u017ce za darmo nigdy nie dostaniemy certyfikatu potwierdzaj\u0105cego nasz\u0105 to\u017csamo\u015b\u0107, lecz tylko domen\u0119. To znaczy, \u017ce dzi\u0119ki certyfikatom od Let\u2019s encrypt mo\u017cemy zapewni\u0107 u\u017cytkownik\u00f3w, \u017ce naprawd\u0119 rozmawiaj\u0105 z \u003Cem\u003Eexample.com\u003C\/em\u003E i \u017ce nikt ich nie mo\u017ce przy tym pods\u0142ucha\u0107, ale ju\u017c nie o tym, \u017ce \u003Cem\u003Eexample.com\u003C\/em\u003E jest zarz\u0105dzane przez \u003Cem\u003EExample sp. z o.o.\u003C\/em\u003E Czyli wystarczaj\u0105co dobrze dla zdecydowanej wi\u0119kszo\u015bci zastosowa\u0144.\u003C\/p\u003E\n\u003Cp\u003ENie mam \u017cadnych w\u0105tpliwo\u015bci, \u017ce Let\u2019s encrypt zrewolucjonizuje bezpiecze\u0144stwo w sieci.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["bezpiecze\u0144stwo","https","konfiguracja","serwer","szyfrowanie"],"hasMore":true,"image":"https:\/\/avris.it\/image\/avris-can-into-https_small.jpeg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-can-into-https_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-can-into-https_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022122.2641509434\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003E\u003Ca href=\u0022https:\/\/letsencrypt.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Let\u2019s encrypt\u003C\/a\u003E\u003C\/strong\u003E jest projektem d\u0105\u017c\u0105cym do maksymalizacji dost\u0119pno\u015bci do certyfikat\u00f3w SSL \u2013 i chyba najlepsz\u0105 rzecz\u0105, jaka mnie ostatnio spotka\u0142a.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/avris-can-into-https_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/avris-can-into-https_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022122.2641509434\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003E\u003Cstrong\u003E\u003Ca href=\u0022https:\/\/letsencrypt.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Let\u2019s encrypt\u003C\/a\u003E\u003C\/strong\u003E jest projektem d\u0105\u017c\u0105cym do maksymalizacji dost\u0119pno\u015bci do certyfikat\u00f3w SSL \u2013 i chyba najlepsz\u0105 rzecz\u0105, jaka mnie ostatnio spotka\u0142a.\u003C\/p\u003E\n\u003Cp\u003ES\u0105 dwa powody, dla kt\u00f3rych nigdy nie zg\u0142\u0119bi\u0142em tematu szyfrowania po\u0142\u0105cze\u0144 HTTP: \u003Cstrong\u003Ewysoka cena\u003C\/strong\u003E certyfikat\u00f3w oraz \u003Cstrong\u003Ekoszmarna konfiguracja\u003C\/strong\u003E serwera. Szczerze m\u00f3wi\u0105c, nie wiem jak bardzo wysoka, bo w zale\u017cno\u015bci od wielu czynnik\u00f3w ceny r\u00f3\u017cni\u0105 si\u0119 nawet o dwa rz\u0119dy wielko\u015bci, ani jak bardzo koszmarna, bo jedna kr\u00f3tka przygoda z konfiguracj\u0105 certyfikat\u00f3w zdo\u0142a\u0142a skutecznie odstraszy\u0107 mnie od tematu.\u003C\/p\u003E\n\u003Cp\u003EA to bardzo niedobrze. Je\u015bli \u0142\u0105czysz si\u0119 z ze stron\u0105, kt\u00f3ra nie szyfruje ruchu, to nie do\u015b\u0107, ze nie masz poj\u0119cia, czy dane z \u003Cem\u003Eexample.com\u003C\/em\u003E rzeczywi\u015bcie pochodz\u0105 z \u003Cem\u003Eexample.com\u003C\/em\u003E, czy tylko kto\u015b si\u0119 pod nich podszy\u0142, to jeszcze wszystkie dane, kt\u00f3re mi\u0119dzy sob\u0105 wymieniacie (w\u0142\u0105cznie z has\u0142ami), lataj\u0105 sobie po sieci zapisane czystym tekstem!\u003C\/p\u003E\n\u003Cp\u003EInternet chce z tym walczy\u0107. Mam nieoficjalne informacje, \u017ce Google chc\u0105 \u201cwkr\u00f3tce\u201d przestawi\u0107 Chrome na tryb \u201ctylko HTTPS\u201d. P\u00f3ki co, strony z poprawnym certyfikatem s\u0105 oznaczane zielon\u0105 k\u0142\u00f3dk\u0105 przy adresie, te z niepoprawnym \u2013 czerwon\u0105, a te bez certyfikatu \u2013 wcale. Aby zach\u0119ci\u0107 ludzi do u\u017cywania HTTPS, te ostatnie nied\u0142ugo r\u00f3wnie\u017c b\u0119d\u0105 czerwone. Dla w\u0142a\u015bcicieli stron nie jest to przyjemna perspektywa.\u003C\/p\u003E\n\u003Cp\u003EWtem, na ratunek przybywa Let\u2019s encrypt. Dzi\u0119ki sponsoringowi wielkich firm, oferuj\u0105 certyfikaty \u003Cstrong\u003Ezupe\u0142nie za darmo.\u003C\/strong\u003E A do tego udost\u0119pniaj\u0105 narz\u0119dzie, dzi\u0119ki kt\u00f3remu konfiguracja certyfikatu na serwerze Apache pod Debianem to \u003Cstrong\u003Eraptem jedno polecenie w konsoli!\u003C\/strong\u003E (pod innymi platformami jest ciut gorzej, ale wci\u0105\u017c o wiele \u0142atwiej ni\u017c w przypadku r\u0119cznej konfiguracji).\u003C\/p\u003E\n\u003Cp\u003EMinusy? Projekt dopiero co wyszed\u0142 z bety, wi\u0119c nie ma co oczekiwa\u0107 fajerwerk\u00f3w takich jak \u003Ca href=\u0022https:\/\/github.com\/letsencrypt\/letsencrypt\/issues\/66\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E wildcards\u003C\/a\u003E (kt\u00f3re akruat bardzo by mi si\u0119 przyda\u0142y). No i wiadomo, \u017ce za darmo nigdy nie dostaniemy certyfikatu potwierdzaj\u0105cego nasz\u0105 to\u017csamo\u015b\u0107, lecz tylko domen\u0119. To znaczy, \u017ce dzi\u0119ki certyfikatom od Let\u2019s encrypt mo\u017cemy zapewni\u0107 u\u017cytkownik\u00f3w, \u017ce naprawd\u0119 rozmawiaj\u0105 z \u003Cem\u003Eexample.com\u003C\/em\u003E i \u017ce nikt ich nie mo\u017ce przy tym pods\u0142ucha\u0107, ale ju\u017c nie o tym, \u017ce \u003Cem\u003Eexample.com\u003C\/em\u003E jest zarz\u0105dzane przez \u003Cem\u003EExample sp. z o.o.\u003C\/em\u003E Czyli wystarczaj\u0105co dobrze dla zdecydowanej wi\u0119kszo\u015bci zastosowa\u0144.\u003C\/p\u003E\n\u003Cp\u003ENie mam \u017cadnych w\u0105tpliwo\u015bci, \u017ce Let\u2019s encrypt zrewolucjonizuje bezpiecze\u0144stwo w sieci.\u003C\/p\u003E","words":411,"readTime":2,"lang":"pl"}}},"blog\/technology\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji":{"key":"blog\/technology\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji","type":"article","published":true,"meta":{"createdAt":"2017-04-28T19:43:44+02:00","publishedAt":"2015-11-15T00:07:00+01:00","group":null,"category":"blog","subcategory":"technology","slug":"proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji"},"content":{"pl":{"slug":"proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji","title":"Proste potwierdzenie w JavaScripcie, a rozdzielenie warstw aplikacji","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022268.48780487805\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEo0lEQVRIib2WS4\/l1BGAvzoP2\/f6PvtB98AwPfRoIkE2JLCJlCChSInEht+BWOVPBGUb\/k8UKSEPokiwIauMEMOgnu5hOt3X9vXj+FQWvj28pi\/DIqnNsc+pcn1Vripbfvve7zRNE1AFEVClrCrycQ4oddOSZSn\/L3F\/\/\/BDfnT3Dvfvf07oOkZ5TuharHVEhXVRcPv4mPliwXSS\/++B3vjFzwE4PLzxncO+D\/S9kiT+mR7W1GsuLgsmk5wYIwKIsaRZyrqqEAEwm1XxPqUsVozGOXW9Zjqd4rY5sNZh7bNH533Czs4OqnHYUEUBI0KWZWhUEJCNvrGGfDLBGoubTBAR3D\/+9tfBuULcaJorDwoIqAxnUUGu9vQrXQWuuFWGjat1swxgQA9Y73n9tdcHe\/PEGwDus3v\/xhhD3zb4xBNjjxXLYr5gthyi7bqAEWgZgORrEBFFjWA2sBHdAAkRMKpMFgsenpzw+IsHmDSjaOonQN8W18UGgxAk0MUeEyImNfzq7bd4593fPPv7+h5569dvQmjIkpQQr9dzl7Ma3yghF9QprhaCV2o6ROR6y6eIql5rU60uKLVnVZwzdePrgUaXyqhSnEInytopgqAtVGXJ6dkjUKVeVxjryVJP0wacH6om9pG2bTEiQ0d5S90FVJVRlqIi3D46Iu2hFEgEvlU23wQyZWSthpeWMy7WNbkKJ21NH2Gc5xyNh2hEBN1U8g+9Bug3iUsjX7XZ04AEw2KSMZ5mHN3a53HVkdYtUSMhhOstf6CsDIwFlledeh2Qc5bjecLB7ojRfM7zLx\/zyccfYVSpqmqrk3uPalQjsgl5MnLMffxGZpxzOOdAYF+HDG0bbe6Vg5y9vRliDX3XEpuanfmCw9nse4v6wZcrZqbh4dkZL968SdGkuHHg9OEJRbFmb3+f\/f1dvPfkEVzYzLJ+C1AbIYSeto2Uj1aEk3Pu3H2Z3cViKwzAz+7uo8Ard24CYAUEZblcPtG5CkoiBB2yc7klRa5qAqfnNYk1PH\/4Aqo9jsg\/\/\/gH3n\/\/99jNuA0GWrEoCQZBVJl0HWrCMMUjdAa6ONSsN4NNzZCVplqRCSQKflsNjZ1jb+xIfMK6uKBtwTlLJynPzRbc\/+wehkgwsLaGQmBaK8tG6YAygcoPTjvAINRWEYVmc69RsYCYIUPzbW1\/9p+CxAi7S8fqvMBYR914Znu7\/OSXr3F8fsr64jFdH9jdP2Bdlnzwpz\/TdJc4gWBhbcFESKLQGMUgmKjc6KAwyjoRrCqjCJlu7XpMsA69cYtV78lmjmziKC4r6qpEtGM2TZn5hqUPjLxl9\/CQn776KohQGFgLjOPwRceCNeCBpRpmETKBnQh7CDvRMFYIW5DcWW9xnz\/AWOU5C8XlJc5Y0r2K9qO\/YAj0XY1NUtqmJ5\/kHEwNx3du8vGn9wk99D2MRDBGGFnDCEsOnNqWqUvotcfHSOYcKw+1vf6dOQ0N2XjJ8e0Dvvj0hLotufvj28xvHZFmGesvH\/Hgk3+Rj5RYPqQrcyS07IwMdpJRNjX0YH3CC9mYPRU6oPeKj54XJzNWdU1Jj7eOcYwM\/wpPl\/8CWIcTbntq1pMAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022268.48780487805\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EProste zadanie: umie\u015bci\u0107 na stronie przycisk, kt\u00f3ry przekieruje nas do usuwania jakiego\u015b obiektu z bazy, ale zanim to zrobi, spyta, czy na pewno tego chcemy.\u003C\/p\u003E\n\u003Cp\u003EStandardowa cz\u0119\u015b\u0107 interfejsu, mo\u017cliwa do zrealizowania w webie na wiele r\u00f3\u017cnych sposob\u00f3w. Najprostszym z nich jest zwyk\u0142e okienko \u003Ccode\u003Econfirm()\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EW wersji najbardziej prymitywnej wykonanie zadania wygl\u0105da mniej wi\u0119cej tak:\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022615\u0022 height=\u0022344\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAUCAYAAADlep81AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEo0lEQVRIib2WS4\/l1BGAvzoP2\/f6PvtB98AwPfRoIkE2JLCJlCChSInEht+BWOVPBGUb\/k8UKSEPokiwIauMEMOgnu5hOt3X9vXj+FQWvj28pi\/DIqnNsc+pcn1Vripbfvve7zRNE1AFEVClrCrycQ4oddOSZSn\/L3F\/\/\/BDfnT3Dvfvf07oOkZ5TuharHVEhXVRcPv4mPliwXSS\/++B3vjFzwE4PLzxncO+D\/S9kiT+mR7W1GsuLgsmk5wYIwKIsaRZyrqqEAEwm1XxPqUsVozGOXW9Zjqd4rY5sNZh7bNH533Czs4OqnHYUEUBI0KWZWhUEJCNvrGGfDLBGoubTBAR3D\/+9tfBuULcaJorDwoIqAxnUUGu9vQrXQWuuFWGjat1swxgQA9Y73n9tdcHe\/PEGwDus3v\/xhhD3zb4xBNjjxXLYr5gthyi7bqAEWgZgORrEBFFjWA2sBHdAAkRMKpMFgsenpzw+IsHmDSjaOonQN8W18UGgxAk0MUeEyImNfzq7bd4593fPPv7+h5569dvQmjIkpQQr9dzl7Ma3yghF9QprhaCV2o6ROR6y6eIql5rU60uKLVnVZwzdePrgUaXyqhSnEInytopgqAtVGXJ6dkjUKVeVxjryVJP0wacH6om9pG2bTEiQ0d5S90FVJVRlqIi3D46Iu2hFEgEvlU23wQyZWSthpeWMy7WNbkKJ21NH2Gc5xyNh2hEBN1U8g+9Bug3iUsjX7XZ04AEw2KSMZ5mHN3a53HVkdYtUSMhhOstf6CsDIwFlledeh2Qc5bjecLB7ojRfM7zLx\/zyccfYVSpqmqrk3uPalQjsgl5MnLMffxGZpxzOOdAYF+HDG0bbe6Vg5y9vRliDX3XEpuanfmCw9nse4v6wZcrZqbh4dkZL968SdGkuHHg9OEJRbFmb3+f\/f1dvPfkEVzYzLJ+C1AbIYSeto2Uj1aEk3Pu3H2Z3cViKwzAz+7uo8Ard24CYAUEZblcPtG5CkoiBB2yc7klRa5qAqfnNYk1PH\/4Aqo9jsg\/\/\/gH3n\/\/99jNuA0GWrEoCQZBVJl0HWrCMMUjdAa6ONSsN4NNzZCVplqRCSQKflsNjZ1jb+xIfMK6uKBtwTlLJynPzRbc\/+wehkgwsLaGQmBaK8tG6YAygcoPTjvAINRWEYVmc69RsYCYIUPzbW1\/9p+CxAi7S8fqvMBYR914Znu7\/OSXr3F8fsr64jFdH9jdP2Bdlnzwpz\/TdJc4gWBhbcFESKLQGMUgmKjc6KAwyjoRrCqjCJlu7XpMsA69cYtV78lmjmziKC4r6qpEtGM2TZn5hqUPjLxl9\/CQn776KohQGFgLjOPwRceCNeCBpRpmETKBnQh7CDvRMFYIW5DcWW9xnz\/AWOU5C8XlJc5Y0r2K9qO\/YAj0XY1NUtqmJ5\/kHEwNx3du8vGn9wk99D2MRDBGGFnDCEsOnNqWqUvotcfHSOYcKw+1vf6dOQ0N2XjJ8e0Dvvj0hLotufvj28xvHZFmGesvH\/Hgk3+Rj5RYPqQrcyS07IwMdpJRNjX0YH3CC9mYPRU6oPeKj54XJzNWdU1Jj7eOcYwM\/wpPl\/8CWIcTbntq1pMAAAAASUVORK5CYII=\u0022 data-src=\u0022https:\/\/avris.it\/image\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022615\u0022 height=\u0022344\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EProste zadanie: umie\u015bci\u0107 na stronie przycisk, kt\u00f3ry przekieruje nas do usuwania jakiego\u015b obiektu z bazy, ale zanim to zrobi, spyta, czy na pewno tego chcemy.\u003C\/p\u003E\n\u003Cp\u003EStandardowa cz\u0119\u015b\u0107 interfejsu, mo\u017cliwa do zrealizowania w webie na wiele r\u00f3\u017cnych sposob\u00f3w. Najprostszym z nich jest zwyk\u0142e okienko \u003Ccode\u003Econfirm()\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EW wersji najbardziej prymitywnej wykonanie zadania wygl\u0105da mniej wi\u0119cej tak:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs xml border\u0022\u003E\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Ea\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Ehref\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022{{ route(\u0027product_delete\u0027, {id: product.id}) }}\u0022\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-attr\u0022\u003Eonclick\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022return confirm(\u0027{{ \u0027delete.confirm\u0027|l|e }}\u0027)\u0022\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n    {{ \u0027delete\u0027|l }}\n\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Ea\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EProsta sprawa \u2013 linkujemy do adresu, kt\u00f3ry usunie produkt z bazy, ale przy klikni\u0119ciu pytamy u\u017cytkownika, czy na pewno chce to zrobi\u0107. Je\u015bli nie chce, wtedy \u003Ccode\u003Econfirm()\u003C\/code\u003E zwr\u00f3ci \u003Ccode\u003Efalse\u003C\/code\u003E, a wi\u0119c wykonanie przekierowania zostanie zablokowane.\u003C\/p\u003E\n\u003Cp\u003EJest z tym kodem tylko jeden problem \u2013 mieszamy ze sob\u0105 HTML i JS. A to nie tak powinny dzia\u0142a\u0107 internety.\u003C\/p\u003E\n\u003Cp\u003EPoprawnie napisana strona internetowa sk\u0142ada si\u0119 (oczywi\u015bcie w cz\u0119\u015bci frontendowej) z trzech warstw:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ew HTML-u umieszczamy \u003Cstrong\u003Eustrukturyzowane dane\u003C\/strong\u003E,\u003C\/li\u003E\n\u003Cli\u003Ew CSS-ach definiujemy, jak te dane maj\u0105 by\u0107 \u003Cstrong\u003Eprezentowane\u003C\/strong\u003E,\u003C\/li\u003E\n\u003Cli\u003Ea w JS-ie dodajemy wszystkie te \u003Cstrong\u003Efajerwerki\u003C\/strong\u003E i \u015bwiecide\u0142ka, dzi\u0119ki kt\u00f3rym strona jest dynamiczniejsza i atrakcyjniejsza.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003ENajlepiej, gdyby warstwy te w og\u00f3le si\u0119 ze sob\u0105 nie miesza\u0142y. Dzi\u0119ki temu kod jest czystszy, a warstwy mog\u0105 by\u0107 u\u017cywane i modyfikowane niezale\u017cnie od siebie. Mo\u017cna na przyk\u0142ad w banalnie prosty spos\u00f3b zaimplementowa\u0107 r\u00f3\u017cne sk\u00f3rki na stronie, po prostu podmieniaj\u0105c u\u017cywany akrusz styl\u00f3w na inny. Je\u015bli w HTML-u nie umie\u015bcimy \u017cadnych styl\u00f3w inline (mam nadziej\u0119, \u017ce nikomu cho\u0107 troch\u0119 znaj\u0105cemu temat nie trzeba t\u0142umaczy\u0107, jak z\u0142y jest to pomys\u0142), lecz tylko dane oraz struktur\u0119, w jakiej s\u0105 u\u0142o\u017cone, to ca\u0142kowita zmiana wygl\u0105du strony jest nadzwyczaj \u0142atwa. (Dla przyk\u0142adu cho\u0107by \u003Ca href=\u0022http:\/\/bootswatch.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E bootswatch.com\u003C\/a\u003E albo \u003Ca href=\u0022http:\/\/www.csszengarden.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E csszengarden.com\u003C\/a\u003E \u2013 wszystkie podstrony w dziale \u201cthemes\u201d r\u00f3\u017cni\u0105 si\u0119 tylko jedn\u0105 rzecz\u0105: nazw\u0105 pliku .css)\u003C\/p\u003E\n\u003Cp\u003EDok\u0142adnie to samo tyczy si\u0119 JavaScriptu. Je\u015bli kod wykonywalny umie\u015bcimy bezpo\u015brednio wewn\u0105trz znacznika HTML, nasz kod staje si\u0119 zdecydowanie mniej czytelny i bardziej nara\u017cony na powtarzalno\u015b\u0107. Wprowadzanie w nim potem zmian mo\u017ce si\u0119 okaza\u0107 drog\u0105 przez m\u0119k\u0119. Powiedzmy, \u017ce po jakim\u015b czasie zechcemy zmieni\u0107 to brzydkie okienko \u003Ccode\u003Econfirm()\u003C\/code\u003E na przyk\u0142ad na bootstrapowy \u003Ca href=\u0022http:\/\/getbootstrap.com\/javascript\/#modals\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E modal\u003C\/a\u003E. B\u0119dziemy wtedy musieli znale\u017a\u0107 wszystkie u\u017cycia podobnego kodu w naszym projekcie i przerobi\u0107 ka\u017cde z nich. Po co si\u0119 tak m\u0119czy\u0107?\u003C\/p\u003E\n\u003Cp\u003ENatkn\u0105\u0142em si\u0119 ostatnio na taki oto kod, maj\u0105cy wykona\u0107 nasze proste zadanie bez mieszania ze sob\u0105 warstw aplikacji:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs xml border\u0022\u003E\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Ea\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Eclass\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022js-delete-event\u0022\u003C\/span\u003E \n    \u003Cspan class=\u0022hljs-attr\u0022\u003Ehref\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022javascript:void(0)\u0022\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-attr\u0022\u003Edata-delete-url\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022{{ route(\u0027product_delete\u0027, {id: product.id}) }}\u0022\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-attr\u0022\u003Edata-confirm-message\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022{{ \u0027delete.confirm\u0027|l|e }}\u0022\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n    {{ \u0027delete\u0027|l }}\n\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Ea\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ENatomiast w pliku JavaScriptu:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E$(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.js-delete-event\u0027\u003C\/span\u003E).on(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027click\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003E\u003C\/span\u003E) \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (\u003Cspan class=\u0022hljs-literal\u0022\u003Etrue\u003C\/span\u003E == confirm($(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E).data(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027confirm-message\u0027\u003C\/span\u003E))) {\n        \u003Cspan class=\u0022hljs-built_in\u0022\u003Ewindow\u003C\/span\u003E.location.href = $(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E).data(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027delete-url\u0027\u003C\/span\u003E);\n    }\n});\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWygl\u0105da na zdecydowanie bardziej skomplikowany ni\u017c powien by\u0107... Niby jest w porz\u0105dku: w HTML-u nie mamy skrypt\u00f3w, a jedno z drugim komunikuje si\u0119 za pomoc\u0105 klas i atrybut\u00f3w \u003Ccode\u003Edata\u003C\/code\u003E, tak jak powinno by\u0107. HTML definiuje, \u017ce link jest klasy \u003Ccode\u003Ejs-delete-event\u003C\/code\u003E, dok\u0105d powinien kierowa\u0107 i jak brzmi przet\u0142umaczona pro\u015bba o potwierdzenie, natomiast JS szuka wszystkich element\u00f3w z klas\u0105 \u003Ccode\u003Ejs-delete-event\u003C\/code\u003E i podpina pod nie listenera, kt\u00f3ry o potwierdzenie faktycznie spyta, i w zale\u017cno\u015bci od odpowiedzi, przekierowuje u\u017cytkownika do strony usuwaj\u0105cej, b\u0105d\u017a te\u017c nie.\u003C\/p\u003E\n\u003Cp\u003EA jednak JS w tym HTML-owym kodzie si\u0119 pojawia, i to w swojej najbrzydszej formie: jako pseudoprotok\u00f3\u0142. Link, zamiast kierowa\u0107 nas do rzeczywistej strony, odsy\u0142a nas do jakiego\u015b \u003Ccode\u003Evoid(0)\u003C\/code\u003E przez nieistniej\u0105cy protok\u00f3\u0142 \u003Ccode\u003Ejavascript\u003C\/code\u003E... Jest to zwyk\u0142y zabieg maj\u0105cy na celu zablokowanie linka, skierowanie go donik\u0105d, ale jak\u017ce strasznie psuje semantyk\u0119 strony...\u003C\/p\u003E\n\u003Cp\u003EI ma w dupie \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Progressive_enhancement\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Progressive enhancement\u003C\/a\u003E. A to bardzo \u017ale, mie\u0107 go w dupie...\u003C\/p\u003E\n\u003Cp\u003EW progressive enhancement chodzi mniej wi\u0119cej o to, aby zapewni\u0107 dost\u0119p do wszystkich podstawowych danych na stronie oraz do wszystkich podstawowych funkcji naszej aplikacji dla \u003Cstrong\u003Eka\u017cdego\u003C\/strong\u003E u\u017cytkownika. Nawet je\u015bli u\u017cywa IE6 albo nie daj bogini jakiego\u015b lynxa czy innej wy\u0142\u0105cznie tekstowej przegl\u0105darki. Natomiast im jego przegl\u0105darka jest lepsza, nowocze\u015bniejsza i zgodniejsza ze standardami, tym wi\u0119cej deweloper mo\u017ce zaszale\u0107 z \u0142adnym wygl\u0105dem i wodotryskami.\u003C\/p\u003E\n\u003Cp\u003ENie zawsze u\u017cytkownikowi zadzia\u0142aj\u0105 skrypty. Mo\u017ce CDN z jak\u0105\u015b bibliotek\u0105 zaszwankuje, mo\u017ce user jedzie poci\u0105giem i mu net przerywa, a mo\u017ce po prostu sam je wy\u0142\u0105czy\u0142 (tak, niekt\u00f3rzy to robi\u0105).\u003C\/p\u003E\n\u003Cp\u003EJak w takim przypadku zadzia\u0142a powy\u017cszy kod? Ano w\u0142a\u015bnie, nie zadzia\u0142a w og\u00f3le. Chyba \u017ce user zajrzy w \u017ar\u00f3d\u0142o strony, domy\u015bli si\u0119, o co chodzi, i r\u0119cznie przejdzie do URL-a podanego w atrybucie \u003Ccode\u003Edata-delete-url\u003C\/code\u003E. Powodzenia.\u003C\/p\u003E\n\u003Cp\u003EA wi\u0119c progressive enhancement le\u017cy. Dla pewnej grupy u\u017cytkownik\u00f3w dost\u0119p do wa\u017cnej funkcjonalno\u015bci jest niemo\u017cliwy.\u003C\/p\u003E\n\u003Cp\u003ESp\u00f3jrzmy teraz na inny kod:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs xml border\u0022\u003E\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\u003Cspan class=\u0022hljs-name\u0022\u003Ea\u003C\/span\u003E \u003Cspan class=\u0022hljs-attr\u0022\u003Ehref\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022{{ route(\u0027product_delete\u0027, {id: product.id}) }}\u0022\u003C\/span\u003E \n    \u003Cspan class=\u0022hljs-attr\u0022\u003Edata-confirm\u003C\/span\u003E=\u003Cspan class=\u0022hljs-string\u0022\u003E\u0022{{ \u0027delete.confirm\u0027|l|e }}\u0022\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n    {{ \u0027delete\u0027|l }}\n\u003Cspan class=\u0022hljs-tag\u0022\u003E\u0026lt;\/\u003Cspan class=\u0022hljs-name\u0022\u003Ea\u003C\/span\u003E\u0026gt;\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003E$(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027a[data-confirm]\u0027\u003C\/span\u003E).click(\u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003E\u003C\/span\u003E) \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E confirm($(\u003Cspan class=\u0022hljs-keyword\u0022\u003Ethis\u003C\/span\u003E).data(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027confirm\u0027\u003C\/span\u003E));\n});\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETutaj mamy w HTML-u najzwyczajniejszy w \u015bwiecie link, po prostu z jednym dodatkowym atrybutem. Gdyby z jakiego\u015b powodu nie za\u0142adowa\u0142 si\u0119 skypt, \u015bwiat si\u0119 nie zawali. U\u017cytkownik dalej ma mo\u017cliwo\u015b\u0107 usuni\u0119cia elementu, po prostu jest bardziej nara\u017cony na zrobienie tego przez przypadek, bo nie zobaczy potwierdzenia.\u003C\/p\u003E\n\u003Cp\u003EJe\u015bli natomiast JS dzia\u0142a, skrypt znajdzie wszystkie elementy posiadaj\u0105ce atrybut \u003Ccode\u003Edata-confirm\u003C\/code\u003E i podepnie pod nie listenera, zadaj\u0105cego u\u017cytkownikowi pytanie, kt\u00f3re si\u0119 w tym atrybucie znajduje.\u003C\/p\u003E\n\u003Cp\u003ETen kod jest o wiele lepszy od poprzedniego nie tylko ze wzgl\u0119du na respektowanie progressive enhancement:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EElement A zosta\u0142 odchudzony ze wszystkich zb\u0119dnych atrybut\u00f3w (czyli po\u0142owy!). W poprzednim kodzie jego autor uda\u0142, \u017ce link donik\u0105d nie kieruje, tylko po to, by p\u00f3\u017aniej przekaza\u0107 odpowiedni URL w osbobnym atrybucie. U\u017cy\u0142 te\u017c specjalnej klasy, po kt\u00f3rej JS mia\u0142 rozpozna\u0107 interesuj\u0105ce go elementy, mimo \u017ce sam fakt posiadania tekstu potwierdzenia ju\u017c dostatecznie jasno identyfikuje elementy, kt\u00f3re powinny wy\u015bwietli\u0107 potwierdzenie.\u003C\/li\u003E\n\u003Cli\u003EWykorzystanli\u015bmy \u015bwietnego ficzera jQuery \u2013 to, \u017ce zwr\u00f3cenie \u003Ccode\u003Efalse\u003C\/code\u003E w event hadlerze automatycznie zatrzymuje propagacj\u0119 zdarzenia. W bardzo elegancki i zwi\u0119z\u0142y spos\u00f3b zatrzymali\u015bmy przekierowanie po klikni\u0119ciu, bez potrzeby uciekania si\u0119 do pseudoprotoko\u0142\u00f3w ani \u003Ccode\u003Eevent.stoppropagation(); event.preventdefault();\u003C\/code\u003E, przy okazji jeszcze pytaj\u0105c o zgod\u0119 u\u017cytkownika \u2013 w jednej prostej linijce!\u003C\/li\u003E\n\u003Cli\u003ENie u\u017cywamy okropnego \u003Ccode\u003Ewindow.location.href\u003C\/code\u003E. Pozwalamy na zwyczajn\u0105 obs\u0142ug\u0119 operacji przekierowania po klikni\u0119ciu w link, po prostu rozszerzaj\u0105c j\u0105 o mo\u017cliwo\u015b\u0107 warunkowego przerwania, zamiast sztucznie i nieelegancko blokowa\u0107 przekierowanie tylko po to, by potem jeszcze sztuczniej wywo\u0142a\u0107 je od nowa...\u003C\/li\u003E\n\u003C\/ul\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["html","javascript","js","programowanie","progressive enhancement","warstwy abstracji","web"],"hasMore":true,"image":"https:\/\/avris.it\/image\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022134.24390243902\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EProste zadanie: umie\u015bci\u0107 na stronie przycisk, kt\u00f3ry przekieruje nas do usuwania jakiego\u015b obiektu z bazy, ale zanim to zrobi, spyta, czy na pewno tego chcemy.\u003C\/p\u003E\n\u003Cp\u003EStandardowa cz\u0119\u015b\u0107 interfejsu, mo\u017cliwa do zrealizowania w webie na wiele r\u00f3\u017cnych sposob\u00f3w. Najprostszym z nich jest zwyk\u0142e okienko \u003Ccode\u003Econfirm()\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EW wersji najbardziej prymitywnej wykonanie zadania wygl\u0105da mniej wi\u0119cej tak:\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/proste-potwierdzenie-w-javascripcie-a-rozdzielenie-warstw-aplikacji_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022134.24390243902\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EProste zadanie: umie\u015bci\u0107 na stronie przycisk, kt\u00f3ry przekieruje nas do usuwania jakiego\u015b obiektu z bazy, ale zanim to zrobi, spyta, czy na pewno tego chcemy.\u003C\/p\u003E\n\u003Cp\u003EStandardowa cz\u0119\u015b\u0107 interfejsu, mo\u017cliwa do zrealizowania w webie na wiele r\u00f3\u017cnych sposob\u00f3w. Najprostszym z nich jest zwyk\u0142e okienko \u003Ccode\u003Econfirm()\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EW wersji najbardziej prymitywnej wykonanie zadania wygl\u0105da mniej wi\u0119cej tak:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;a href=\u0022{{ route(\u0027product_delete\u0027, {id: product.id}) }}\u0022\n    onclick=\u0022return confirm(\u0027{{ \u0027delete.confirm\u0027|l|e }}\u0027)\u0022\u0026gt;\n    {{ \u0027delete\u0027|l }}\n\u0026lt;\/a\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EProsta sprawa \u2013 linkujemy do adresu, kt\u00f3ry usunie produkt z bazy, ale przy klikni\u0119ciu pytamy u\u017cytkownika, czy na pewno chce to zrobi\u0107. Je\u015bli nie chce, wtedy \u003Ccode\u003Econfirm()\u003C\/code\u003E zwr\u00f3ci \u003Ccode\u003Efalse\u003C\/code\u003E, a wi\u0119c wykonanie przekierowania zostanie zablokowane.\u003C\/p\u003E\n\u003Cp\u003EJest z tym kodem tylko jeden problem \u2013 mieszamy ze sob\u0105 HTML i JS. A to nie tak powinny dzia\u0142a\u0107 internety.\u003C\/p\u003E\n\u003Cp\u003EPoprawnie napisana strona internetowa sk\u0142ada si\u0119 (oczywi\u015bcie w cz\u0119\u015bci frontendowej) z trzech warstw:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003Ew HTML-u umieszczamy \u003Cstrong\u003Eustrukturyzowane dane\u003C\/strong\u003E,\u003C\/li\u003E\n\u003Cli\u003Ew CSS-ach definiujemy, jak te dane maj\u0105 by\u0107 \u003Cstrong\u003Eprezentowane\u003C\/strong\u003E,\u003C\/li\u003E\n\u003Cli\u003Ea w JS-ie dodajemy wszystkie te \u003Cstrong\u003Efajerwerki\u003C\/strong\u003E i \u015bwiecide\u0142ka, dzi\u0119ki kt\u00f3rym strona jest dynamiczniejsza i atrakcyjniejsza.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003ENajlepiej, gdyby warstwy te w og\u00f3le si\u0119 ze sob\u0105 nie miesza\u0142y. Dzi\u0119ki temu kod jest czystszy, a warstwy mog\u0105 by\u0107 u\u017cywane i modyfikowane niezale\u017cnie od siebie. Mo\u017cna na przyk\u0142ad w banalnie prosty spos\u00f3b zaimplementowa\u0107 r\u00f3\u017cne sk\u00f3rki na stronie, po prostu podmieniaj\u0105c u\u017cywany akrusz styl\u00f3w na inny. Je\u015bli w HTML-u nie umie\u015bcimy \u017cadnych styl\u00f3w inline (mam nadziej\u0119, \u017ce nikomu cho\u0107 troch\u0119 znaj\u0105cemu temat nie trzeba t\u0142umaczy\u0107, jak z\u0142y jest to pomys\u0142), lecz tylko dane oraz struktur\u0119, w jakiej s\u0105 u\u0142o\u017cone, to ca\u0142kowita zmiana wygl\u0105du strony jest nadzwyczaj \u0142atwa. (Dla przyk\u0142adu cho\u0107by \u003Ca href=\u0022http:\/\/bootswatch.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E bootswatch.com\u003C\/a\u003E albo \u003Ca href=\u0022http:\/\/www.csszengarden.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E csszengarden.com\u003C\/a\u003E \u2013 wszystkie podstrony w dziale \u201cthemes\u201d r\u00f3\u017cni\u0105 si\u0119 tylko jedn\u0105 rzecz\u0105: nazw\u0105 pliku .css)\u003C\/p\u003E\n\u003Cp\u003EDok\u0142adnie to samo tyczy si\u0119 JavaScriptu. Je\u015bli kod wykonywalny umie\u015bcimy bezpo\u015brednio wewn\u0105trz znacznika HTML, nasz kod staje si\u0119 zdecydowanie mniej czytelny i bardziej nara\u017cony na powtarzalno\u015b\u0107. Wprowadzanie w nim potem zmian mo\u017ce si\u0119 okaza\u0107 drog\u0105 przez m\u0119k\u0119. Powiedzmy, \u017ce po jakim\u015b czasie zechcemy zmieni\u0107 to brzydkie okienko \u003Ccode\u003Econfirm()\u003C\/code\u003E na przyk\u0142ad na bootstrapowy \u003Ca href=\u0022http:\/\/getbootstrap.com\/javascript\/#modals\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E modal\u003C\/a\u003E. B\u0119dziemy wtedy musieli znale\u017a\u0107 wszystkie u\u017cycia podobnego kodu w naszym projekcie i przerobi\u0107 ka\u017cde z nich. Po co si\u0119 tak m\u0119czy\u0107?\u003C\/p\u003E\n\u003Cp\u003ENatkn\u0105\u0142em si\u0119 ostatnio na taki oto kod, maj\u0105cy wykona\u0107 nasze proste zadanie bez mieszania ze sob\u0105 warstw aplikacji:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;a class=\u0022js-delete-event\u0022 \n    href=\u0022javascript:void(0)\u0022\n    data-delete-url=\u0022{{ route(\u0027product_delete\u0027, {id: product.id}) }}\u0022\n    data-confirm-message=\u0022{{ \u0027delete.confirm\u0027|l|e }}\u0022\u0026gt;\n    {{ \u0027delete\u0027|l }}\n\u0026lt;\/a\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ENatomiast w pliku JavaScriptu:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$(\u0027.js-delete-event\u0027).on(\u0027click\u0027, function() {\n    if (true == confirm($(this).data(\u0027confirm-message\u0027))) {\n        window.location.href = $(this).data(\u0027delete-url\u0027);\n    }\n});\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWygl\u0105da na zdecydowanie bardziej skomplikowany ni\u017c powien by\u0107... Niby jest w porz\u0105dku: w HTML-u nie mamy skrypt\u00f3w, a jedno z drugim komunikuje si\u0119 za pomoc\u0105 klas i atrybut\u00f3w \u003Ccode\u003Edata\u003C\/code\u003E, tak jak powinno by\u0107. HTML definiuje, \u017ce link jest klasy \u003Ccode\u003Ejs-delete-event\u003C\/code\u003E, dok\u0105d powinien kierowa\u0107 i jak brzmi przet\u0142umaczona pro\u015bba o potwierdzenie, natomiast JS szuka wszystkich element\u00f3w z klas\u0105 \u003Ccode\u003Ejs-delete-event\u003C\/code\u003E i podpina pod nie listenera, kt\u00f3ry o potwierdzenie faktycznie spyta, i w zale\u017cno\u015bci od odpowiedzi, przekierowuje u\u017cytkownika do strony usuwaj\u0105cej, b\u0105d\u017a te\u017c nie.\u003C\/p\u003E\n\u003Cp\u003EA jednak JS w tym HTML-owym kodzie si\u0119 pojawia, i to w swojej najbrzydszej formie: jako pseudoprotok\u00f3\u0142. Link, zamiast kierowa\u0107 nas do rzeczywistej strony, odsy\u0142a nas do jakiego\u015b \u003Ccode\u003Evoid(0)\u003C\/code\u003E przez nieistniej\u0105cy protok\u00f3\u0142 \u003Ccode\u003Ejavascript\u003C\/code\u003E... Jest to zwyk\u0142y zabieg maj\u0105cy na celu zablokowanie linka, skierowanie go donik\u0105d, ale jak\u017ce strasznie psuje semantyk\u0119 strony...\u003C\/p\u003E\n\u003Cp\u003EI ma w dupie \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Progressive_enhancement\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Progressive enhancement\u003C\/a\u003E. A to bardzo \u017ale, mie\u0107 go w dupie...\u003C\/p\u003E\n\u003Cp\u003EW progressive enhancement chodzi mniej wi\u0119cej o to, aby zapewni\u0107 dost\u0119p do wszystkich podstawowych danych na stronie oraz do wszystkich podstawowych funkcji naszej aplikacji dla \u003Cstrong\u003Eka\u017cdego\u003C\/strong\u003E u\u017cytkownika. Nawet je\u015bli u\u017cywa IE6 albo nie daj bogini jakiego\u015b lynxa czy innej wy\u0142\u0105cznie tekstowej przegl\u0105darki. Natomiast im jego przegl\u0105darka jest lepsza, nowocze\u015bniejsza i zgodniejsza ze standardami, tym wi\u0119cej deweloper mo\u017ce zaszale\u0107 z \u0142adnym wygl\u0105dem i wodotryskami.\u003C\/p\u003E\n\u003Cp\u003ENie zawsze u\u017cytkownikowi zadzia\u0142aj\u0105 skrypty. Mo\u017ce CDN z jak\u0105\u015b bibliotek\u0105 zaszwankuje, mo\u017ce user jedzie poci\u0105giem i mu net przerywa, a mo\u017ce po prostu sam je wy\u0142\u0105czy\u0142 (tak, niekt\u00f3rzy to robi\u0105).\u003C\/p\u003E\n\u003Cp\u003EJak w takim przypadku zadzia\u0142a powy\u017cszy kod? Ano w\u0142a\u015bnie, nie zadzia\u0142a w og\u00f3le. Chyba \u017ce user zajrzy w \u017ar\u00f3d\u0142o strony, domy\u015bli si\u0119, o co chodzi, i r\u0119cznie przejdzie do URL-a podanego w atrybucie \u003Ccode\u003Edata-delete-url\u003C\/code\u003E. Powodzenia.\u003C\/p\u003E\n\u003Cp\u003EA wi\u0119c progressive enhancement le\u017cy. Dla pewnej grupy u\u017cytkownik\u00f3w dost\u0119p do wa\u017cnej funkcjonalno\u015bci jest niemo\u017cliwy.\u003C\/p\u003E\n\u003Cp\u003ESp\u00f3jrzmy teraz na inny kod:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;a href=\u0022{{ route(\u0027product_delete\u0027, {id: product.id}) }}\u0022 \n    data-confirm=\u0022{{ \u0027delete.confirm\u0027|l|e }}\u0022\u0026gt;\n    {{ \u0027delete\u0027|l }}\n\u0026lt;\/a\u0026gt;\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cpre\u003E\u003Ccode\u003E$(\u0027a[data-confirm]\u0027).click(function() {\n    return confirm($(this).data(\u0027confirm\u0027));\n});\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETutaj mamy w HTML-u najzwyczajniejszy w \u015bwiecie link, po prostu z jednym dodatkowym atrybutem. Gdyby z jakiego\u015b powodu nie za\u0142adowa\u0142 si\u0119 skypt, \u015bwiat si\u0119 nie zawali. U\u017cytkownik dalej ma mo\u017cliwo\u015b\u0107 usuni\u0119cia elementu, po prostu jest bardziej nara\u017cony na zrobienie tego przez przypadek, bo nie zobaczy potwierdzenia.\u003C\/p\u003E\n\u003Cp\u003EJe\u015bli natomiast JS dzia\u0142a, skrypt znajdzie wszystkie elementy posiadaj\u0105ce atrybut \u003Ccode\u003Edata-confirm\u003C\/code\u003E i podepnie pod nie listenera, zadaj\u0105cego u\u017cytkownikowi pytanie, kt\u00f3re si\u0119 w tym atrybucie znajduje.\u003C\/p\u003E\n\u003Cp\u003ETen kod jest o wiele lepszy od poprzedniego nie tylko ze wzgl\u0119du na respektowanie progressive enhancement:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003EElement A zosta\u0142 odchudzony ze wszystkich zb\u0119dnych atrybut\u00f3w (czyli po\u0142owy!). W poprzednim kodzie jego autor uda\u0142, \u017ce link donik\u0105d nie kieruje, tylko po to, by p\u00f3\u017aniej przekaza\u0107 odpowiedni URL w osbobnym atrybucie. U\u017cy\u0142 te\u017c specjalnej klasy, po kt\u00f3rej JS mia\u0142 rozpozna\u0107 interesuj\u0105ce go elementy, mimo \u017ce sam fakt posiadania tekstu potwierdzenia ju\u017c dostatecznie jasno identyfikuje elementy, kt\u00f3re powinny wy\u015bwietli\u0107 potwierdzenie.\u003C\/li\u003E\n\u003Cli\u003EWykorzystanli\u015bmy \u015bwietnego ficzera jQuery \u2013 to, \u017ce zwr\u00f3cenie \u003Ccode\u003Efalse\u003C\/code\u003E w event hadlerze automatycznie zatrzymuje propagacj\u0119 zdarzenia. W bardzo elegancki i zwi\u0119z\u0142y spos\u00f3b zatrzymali\u015bmy przekierowanie po klikni\u0119ciu, bez potrzeby uciekania si\u0119 do pseudoprotoko\u0142\u00f3w ani \u003Ccode\u003Eevent.stoppropagation(); event.preventdefault();\u003C\/code\u003E, przy okazji jeszcze pytaj\u0105c o zgod\u0119 u\u017cytkownika \u2013 w jednej prostej linijce!\u003C\/li\u003E\n\u003Cli\u003ENie u\u017cywamy okropnego \u003Ccode\u003Ewindow.location.href\u003C\/code\u003E. Pozwalamy na zwyczajn\u0105 obs\u0142ug\u0119 operacji przekierowania po klikni\u0119ciu w link, po prostu rozszerzaj\u0105c j\u0105 o mo\u017cliwo\u015b\u0107 warunkowego przerwania, zamiast sztucznie i nieelegancko blokowa\u0107 przekierowanie tylko po to, by potem jeszcze sztuczniej wywo\u0142a\u0107 je od nowa...\u003C\/li\u003E\n\u003C\/ul\u003E","words":1140,"readTime":5,"lang":"pl"}}},"blog\/technology\/php-aspectmock-fa\u0142szowanie-czasu":{"key":"blog\/technology\/php-aspectmock-fa\u0142szowanie-czasu","type":"article","published":true,"meta":{"createdAt":"2017-04-28T19:43:40+02:00","publishedAt":"2015-07-30T09:25:00+02:00","group":"mocks","category":"blog","subcategory":"technology","slug":"php-aspectmock-fa\u0142szowanie-czasu"},"content":{"pl":{"slug":"php-aspectmock-fa\u0142szowanie-czasu","title":"PHP + AspectMock \u2013 fa\u0142szowanie czasu","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/php-aspectmock-fa\u0142szowanie-czasu_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022291.32075471698\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAVCAYAAAAuJkyQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGw0lEQVRIic2Wy45kRxGGv8jMc6s6dev73DxjM5ZBBgkhIbAsC5Y8Fk\/FIyB5hWBjyx7beKZ7erqnq7su534yM1jUvAEsiH1Iv\/6IL+IXQPk\/KpdYhw8B6yxpkoIaxAgigggoiqCAIAhRQFAEi2oEFBEBBFRRAYNBAdWICIhw6I9KFEUVRAVEMSKItUBk7AfcMit46GqmecGTk1PmQ0s+LYkacRjqcaCdLCiGlqWziEQqD8NyhSiY4Jk93DJdHBFiZO0D9vgEo5HolWJzyzQriAG8RqqjY+Lde05dggI7Y8kfP0Fix7t3VxgVxYghhkAzdFR1D80D435D4XcsGQm+x8fIi2RPX+\/5OB+IwdNcX7HYvOU477mQW1z9Dt3f86vqFXr7lt9+MufYRZ4Pa769fM1YrVH1ZGPNWb\/mm+tL0maLH0ZMkpO6FBNi\/GA5VPua0FV8VozMQ8unhefXZU1dNZxKx1hV3N7cs3u4x6iFpmbJHtO2vLmtOEkDj01Dv69p+5Hb6x3PJLLZN4xtw4WJ\/PH357y0I5t9zVBVPE4CUSO+6xmHHhdVESBxjtw5vriYsvOe81nCq03HdlTIhWlmuX6IDEa48w4xiiQTsqzldSV8tjJc14AVHqKlSwpe3+84SzLSPCedwJtguP9uwy\/yCW82I8VkypvR4tWTmuSwv6vJRLvRk2U5F48e4axBfEASizEOjMEmDosBDP1Qs1yt6AcljCNp7jCA9540z7m+umK1XJDnU7bbLcdHpwxjTz4piRpw1jKOAY0BMYIVgyikNnJ78xaHQlQlSRLKyQxrDRoi1hqisQe+RLBWIEb8mLDdVgjgQ2AYhBgVJ4a2HZjkE8ZupGs3RInsdvcA9H2LNe4DtYKooubAb55kJKmiUXHNOOJjZDad4TcbynKCOksaA2Fo6b0SFwuy+zVZWTALPY1N0OmcqIprKqZJxCUZMQw0OGK5OIjfPXDhBygmhBCpdxvqxYqyqpjM5kQ\/sI2R8uiEodkTQ8T1PmCNIfiRne+RuUcHh7UGEWj7nqxP6GdKOvfstx3GwbQI7Ko92teEJynN\/XvKk4LdemCyLJhdNyyKhHc09GZPt+7J84zMGKpTofJb7NyiQ46xjnGsUVEMH0YSYqT8\/BQ+WTD9wznfXF4xPM354fYGgNukpn7pyf5SULuartnz49Ur+s8j3RcZ4U85w5cp7qucG3dJPLKk5wuql8L9ccv32xv0dzmzTwte2wdujmt+Mvf4J2AQQlQUcxB0OKVKsUhYnc7IEotzDrrA0IxYk\/D4y1Pe\/P2G\/Cjl7IsLJEmRRIj7yI9\/uyK1GU7h56\/fcvJ8zsPlhvXllunJBHFgjUHriI97zn9zxObnisWzKXf\/3KAaiUER6xAwmmcZZ6slRVkimSWOHqMOYywalfl8Sqc9BMUbJfSRIsloupYQI6IQ8WSzCbGPiI1M3JxyWhAN+MET\/EjiUlQVSQwaI9EoGSllOePh5g1N3+MAVqsj8mLKJC+x1hIkYKwlzVJi9ABMzBRjDf04MNpAnhWsFitCGBmD8nC\/RrrI0WIOCE1VY01BIgl5liKFQQU0xIMTqhhr8MEz9iNt1SAWHChN23C0WCJDj6KkenilcaiILgURDBCx5NbgsgSItF2Ljh2zEJlmOYjSGUeMkVlZ0lUV0yFgrCAmoZGIphlpWyNiiAJ+MmO5PCaqYjEHh4a+xYllpiPLskAx6BjwfUc1yRmCZ1ZvyPOSpm7ZTpdY4iG39CPWGoyFEDx+6BFVpgjqPVaVEAURf3BFDLYfsVlO7Fp8NiFGTzGdMA7jYamjKtv9hlm553hV8dGLgX+8\/YmPXni+\/enfoJ7584ifPvD97SVdu2f38J7u9hVPTmqePW9xxR2nZxXzeEm4\/5mnzyZIblm92CPFmm9ff8fzT0rKGYT0jsnqjkef9jx9DF3X0PUdyAfKVBVVpakDPgpf\/2vNzX3LD+8GRt\/x+NwRhxFrAn\/+6hwjhjJLWC5S3r7Z4YwwSS3TSUpbR375csn9ZUseYHM3EBQmuaPdbDjNe55eZITR8\/66ZbuNDEPPtCwxzmJB\/mqMYbVY8nSVsO89F6uMd5UyRpBkSjEtMUZ4+74HcWyblKjKvvZU3nJ1NzIMsGsCKo51FbhqA41JeXQ+5f1aISl5aCzbGk7Olly+E86eHnNzD30\/MnQN9oA9aq3l2aMnGGuIAD5inCGqkqYpqLDbbxErnByf0LQ9282G1XJJVhSs12suzs4JYSSEQ4IMwRNipK5rFvMZziUYsYx+JE1TQvAgMPQDfhzAe4ZhOAj6H8fi\/6r+A3A83c4qjf3rAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/php-aspectmock-fa\u0142szowanie-czasu_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022291.32075471698\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EW pewnym projekcie operuj\u0119 poprzez API na li\u015bcie wyda\u0144 produktu: zamykam wydania, kt\u00f3rych czas ju\u017c min\u0105\u0142, i tworz\u0119 nowe na osiem tygodni naprz\u00f3d. Moimi punktami odniesienia w czasie s\u0105:\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/php-aspectmock-fa\u0142szowanie-czasu_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022636\u0022 height=\u0022386\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAVCAYAAAAuJkyQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAGw0lEQVRIic2Wy45kRxGGv8jMc6s6dev73DxjM5ZBBgkhIbAsC5Y8Fk\/FIyB5hWBjyx7beKZ7erqnq7su534yM1jUvAEsiH1Iv\/6IL+IXQPk\/KpdYhw8B6yxpkoIaxAgigggoiqCAIAhRQFAEi2oEFBEBBFRRAYNBAdWICIhw6I9KFEUVRAVEMSKItUBk7AfcMit46GqmecGTk1PmQ0s+LYkacRjqcaCdLCiGlqWziEQqD8NyhSiY4Jk93DJdHBFiZO0D9vgEo5HolWJzyzQriAG8RqqjY+Lde05dggI7Y8kfP0Fix7t3VxgVxYghhkAzdFR1D80D435D4XcsGQm+x8fIi2RPX+\/5OB+IwdNcX7HYvOU477mQW1z9Dt3f86vqFXr7lt9+MufYRZ4Pa769fM1YrVH1ZGPNWb\/mm+tL0maLH0ZMkpO6FBNi\/GA5VPua0FV8VozMQ8unhefXZU1dNZxKx1hV3N7cs3u4x6iFpmbJHtO2vLmtOEkDj01Dv69p+5Hb6x3PJLLZN4xtw4WJ\/PH357y0I5t9zVBVPE4CUSO+6xmHHhdVESBxjtw5vriYsvOe81nCq03HdlTIhWlmuX6IDEa48w4xiiQTsqzldSV8tjJc14AVHqKlSwpe3+84SzLSPCedwJtguP9uwy\/yCW82I8VkypvR4tWTmuSwv6vJRLvRk2U5F48e4axBfEASizEOjMEmDosBDP1Qs1yt6AcljCNp7jCA9540z7m+umK1XJDnU7bbLcdHpwxjTz4piRpw1jKOAY0BMYIVgyikNnJ78xaHQlQlSRLKyQxrDRoi1hqisQe+RLBWIEb8mLDdVgjgQ2AYhBgVJ4a2HZjkE8ZupGs3RInsdvcA9H2LNe4DtYKooubAb55kJKmiUXHNOOJjZDad4TcbynKCOksaA2Fo6b0SFwuy+zVZWTALPY1N0OmcqIprKqZJxCUZMQw0OGK5OIjfPXDhBygmhBCpdxvqxYqyqpjM5kQ\/sI2R8uiEodkTQ8T1PmCNIfiRne+RuUcHh7UGEWj7nqxP6GdKOvfstx3GwbQI7Ko92teEJynN\/XvKk4LdemCyLJhdNyyKhHc09GZPt+7J84zMGKpTofJb7NyiQ46xjnGsUVEMH0YSYqT8\/BQ+WTD9wznfXF4xPM354fYGgNukpn7pyf5SULuartnz49Ur+s8j3RcZ4U85w5cp7qucG3dJPLKk5wuql8L9ccv32xv0dzmzTwte2wdujmt+Mvf4J2AQQlQUcxB0OKVKsUhYnc7IEotzDrrA0IxYk\/D4y1Pe\/P2G\/Cjl7IsLJEmRRIj7yI9\/uyK1GU7h56\/fcvJ8zsPlhvXllunJBHFgjUHriI97zn9zxObnisWzKXf\/3KAaiUER6xAwmmcZZ6slRVkimSWOHqMOYywalfl8Sqc9BMUbJfSRIsloupYQI6IQ8WSzCbGPiI1M3JxyWhAN+MET\/EjiUlQVSQwaI9EoGSllOePh5g1N3+MAVqsj8mLKJC+x1hIkYKwlzVJi9ABMzBRjDf04MNpAnhWsFitCGBmD8nC\/RrrI0WIOCE1VY01BIgl5liKFQQU0xIMTqhhr8MEz9iNt1SAWHChN23C0WCJDj6KkenilcaiILgURDBCx5NbgsgSItF2Ljh2zEJlmOYjSGUeMkVlZ0lUV0yFgrCAmoZGIphlpWyNiiAJ+MmO5PCaqYjEHh4a+xYllpiPLskAx6BjwfUc1yRmCZ1ZvyPOSpm7ZTpdY4iG39CPWGoyFEDx+6BFVpgjqPVaVEAURf3BFDLYfsVlO7Fp8NiFGTzGdMA7jYamjKtv9hlm553hV8dGLgX+8\/YmPXni+\/enfoJ7584ifPvD97SVdu2f38J7u9hVPTmqePW9xxR2nZxXzeEm4\/5mnzyZIblm92CPFmm9ff8fzT0rKGYT0jsnqjkef9jx9DF3X0PUdyAfKVBVVpakDPgpf\/2vNzX3LD+8GRt\/x+NwRhxFrAn\/+6hwjhjJLWC5S3r7Z4YwwSS3TSUpbR375csn9ZUseYHM3EBQmuaPdbDjNe55eZITR8\/66ZbuNDEPPtCwxzmJB\/mqMYbVY8nSVsO89F6uMd5UyRpBkSjEtMUZ4+74HcWyblKjKvvZU3nJ1NzIMsGsCKo51FbhqA41JeXQ+5f1aISl5aCzbGk7Olly+E86eHnNzD30\/MnQN9oA9aq3l2aMnGGuIAD5inCGqkqYpqLDbbxErnByf0LQ9282G1XJJVhSs12suzs4JYSSEQ4IMwRNipK5rFvMZziUYsYx+JE1TQvAgMPQDfhzAe4ZhOAj6H8fi\/6r+A3A83c4qjf3rAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/php-aspectmock-fa\u0142szowanie-czasu_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022636\u0022 height=\u0022386\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EW pewnym projekcie operuj\u0119 poprzez API na li\u015bcie wyda\u0144 produktu: zamykam wydania, kt\u00f3rych czas ju\u017c min\u0105\u0142, i tworz\u0119 nowe na osiem tygodni naprz\u00f3d. Moimi punktami odniesienia w czasie s\u0105:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003Enew \\DateTime\u003C\/code\u003E \u2013 dzi\u015b,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Enew \\DateTime(\u0027+8 weeks\u0027)\u003C\/code\u003E \u2013 koniec okresu, w kt\u00f3rym tworz\u0119 wydania,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Enew \\DateTime(\u0027last friday\u0027)\u003C\/code\u003E \u2013 bo cykl ka\u017cdego wydania ko\u0144czy si\u0119 w pi\u0105tek, od tej daty iteruj\u0119 \u003Ccode\u003E+1 week\u003C\/code\u003E tworz\u0105c nowe wydania.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EDwie sprawy komplikuj\u0105 nam \u017cycie, je\u015bli chcemy stworzy\u0107 testy jednostkowe do tej klasy: po pierwsze nie powinni\u015bmy \u003Cem\u003Enaprawd\u0119\u003C\/em\u003E odwo\u0142ywa\u0107 si\u0119 do API, a jedynie uda\u0107 zapytania, a po drugie powinni\u015bmy uda\u0107 \u017ce \u003Cem\u003Edzisiaj\u003C\/em\u003E jest kt\u00f3ry\u015btam, jaka\u015b sta\u0142a data, do kt\u00f3rej b\u0119d\u0105 dostosowane nasze przypadki testowe.\u003C\/p\u003E\n\u003Cp\u003EMusimy zatem stworzy\u0107 par\u0119 dubli \u2013 klas, kt\u00f3re \u201cprzys\u0142oni\u0105\u201d swoje pierwowzory, podmieniaj\u0105c niekt\u00f3re ich metody na swoje. \u015awietnym narz\u0119dziem do tego celu jest biblioteka \u003Ca href=\u0022https:\/\/github.com\/Codeception\/AspectMock\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E AspectMock\u003C\/a\u003E, potrafi\u0105ca stworzy\u0107 takie duble, kt\u00f3re wszystkim innym nawet si\u0119 nie \u015bni\u0142y (np. duble metod statycznych czy funkcji systemowych).\u003C\/p\u003E\n\u003Cp\u003ENiestety, cho\u0107 AspectMock potrafi \u201cnadpisa\u0107\u201d funkcj\u0119 \u003Ccode\u003Etime()\u003C\/code\u003E, na nic to si\u0119 zda, je\u015bli u\u017cywamy \u003Ccode\u003EDateTime\u003C\/code\u003E (a kto nie u\u017cywa?), a j\u0105 nadpisa\u0107 jest ju\u017c ci\u0119\u017cej. Na szcz\u0119\u015bcie da si\u0119 to zrobi\u0107 za pomoc\u0105 pewnej sztuczki:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Enamespace\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EVR\u003C\/span\u003E\\\u003Cspan class=\u0022hljs-title\u0022\u003ERedmine\u003C\/span\u003E;\n\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EVersionsHandler\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-comment\u0022\u003E\/** \u003Cspan class=\u0022hljs-doctag\u0022\u003E@var\u003C\/span\u003E Api *\/\u003C\/span\u003E\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $api;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $now;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $until;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003E__construct\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E(Api $api)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;api = $api;\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;now = TimeProvider::getDateTimeFormatted();\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;until = TimeProvider::getDateTimeFormatted(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027+8 weeks\u0027\u003C\/span\u003E);\n    }\n\n    \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ (...)\u003C\/span\u003E\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EgetToBeCreated\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E\n    \u003C\/span\u003E{\n        $current = TimeProvider::getDateTime(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027last friday\u0027\u003C\/span\u003E);\n        \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ (...)\u003C\/span\u003E\n    }\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EJak wida\u0107, we wszystkich miejscach, gdzie normalnie u\u017cy\u0142bym \u003Ccode\u003EDateTime\u003C\/code\u003E, ja korzystam z klasy \u003Ccode\u003ETimeProvider\u003C\/code\u003E. Jest ona bardzo pro\u015bciutka:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Enamespace\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EVR\u003C\/span\u003E\\\u003Cspan class=\u0022hljs-title\u0022\u003ERedmine\u003C\/span\u003E;\n\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ETimeProvider\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Estatic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EgetDateTime\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($time = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027now\u0027\u003C\/span\u003E)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E \\DateTime($time);\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Estatic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EgetDateTimeFormatted\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($time = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027now\u0027\u003C\/span\u003E)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        $datetime = \u003Cspan class=\u0022hljs-keyword\u0022\u003Eself\u003C\/span\u003E::getDateTime($time);\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $datetime-\u0026gt;format(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Y.\\WW\u0027\u003C\/span\u003E);\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EI istnieje tylko po to, by m\u00f3c j\u0105 zdublowa\u0107 w nast\u0119puj\u0105cy spos\u00f3b:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$timeProxy = Test::double(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027VR\\\\Redmine\\\\TimeProvider\u0027\u003C\/span\u003E, [\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027getDateTime\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($time)\u003C\/span\u003E \u003C\/span\u003E{\n    $dt = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E \\DateTime(\u003Cspan class=\u0022hljs-string\u0022\u003E\u00272015-01-14\u0027\u003C\/span\u003E);\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $dt-\u0026gt;modify($time);\n}]);\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EA zatem podczas normalnego uruchomienia aplikacji, \u003Ccode\u003ETimeProvider\u003C\/code\u003E dzia\u0142a po prostu jak nicnierobi\u0105ca fabryka \u003Ccode\u003EDateTime\u003C\/code\u003E\u2019\u00f3w. W czasie test\u00f3w jednak obiera ona za punkt odniesienia arbitraln\u0105 dat\u0119 \u003Ccode\u003E2015-01-04\u003C\/code\u003E, a potem modyfikuje j\u0105 o to, co podamy jej w parametrze, jak jakby dzi\u015b by\u0142 \u003Ccode\u003E2015-01-04\u003C\/code\u003E. Zawsze, niezale\u017cnie kiedy uruchomimy test.\u003C\/p\u003E\n\u003Cp\u003ETeraz wystarczy tylko zdublowa\u0107 funkcj\u0119 odwo\u0142uj\u0105c\u0105 si\u0119 do API i przeprowadzi\u0107 testy:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E$apiProxy = Test::double(\n  \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027VR\\\\Redmine\\\\Api\u0027\u003C\/span\u003E,\n  [\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027curl\u0027\u003C\/span\u003E =\u0026gt; \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($url, $method = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027GET\u0027\u003C\/span\u003E, $data = [])\u003C\/span\u003E \u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E ($method != \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027GET\u0027\u003C\/span\u003E) { \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Enull\u003C\/span\u003E; }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E json_encode(\u003Cspan class=\u0022hljs-comment\u0022\u003E\/* mocked api response *\/\u003C\/span\u003E);\n}]);\n\n$handler = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E VersionsHandler(\u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Api);\n\n\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;assertEquals(\u003Cspan class=\u0022hljs-comment\u0022\u003E\/* expected output *\/\u003C\/span\u003E, $handler-\u0026gt;handle());\n\u003C\/code\u003E\u003C\/pre\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["aop","aspectmock","czas","datetime","php","programowanie"],"hasMore":true,"image":"https:\/\/avris.it\/image\/php-aspectmock-fa\u0142szowanie-czasu_small.jpeg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/php-aspectmock-fa\u0142szowanie-czasu_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/php-aspectmock-fa\u0142szowanie-czasu_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022145.66037735849\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EW pewnym projekcie operuj\u0119 poprzez API na li\u015bcie wyda\u0144 produktu: zamykam wydania, kt\u00f3rych czas ju\u017c min\u0105\u0142, i tworz\u0119 nowe na osiem tygodni naprz\u00f3d. Moimi punktami odniesienia w czasie s\u0105:\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/php-aspectmock-fa\u0142szowanie-czasu_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/php-aspectmock-fa\u0142szowanie-czasu_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022145.66037735849\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EW pewnym projekcie operuj\u0119 poprzez API na li\u015bcie wyda\u0144 produktu: zamykam wydania, kt\u00f3rych czas ju\u017c min\u0105\u0142, i tworz\u0119 nowe na osiem tygodni naprz\u00f3d. Moimi punktami odniesienia w czasie s\u0105:\u003C\/p\u003E\n\u003Cul\u003E\n\u003Cli\u003E\u003Ccode\u003Enew \\DateTime\u003C\/code\u003E \u2013 dzi\u015b,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Enew \\DateTime(\u0027+8 weeks\u0027)\u003C\/code\u003E \u2013 koniec okresu, w kt\u00f3rym tworz\u0119 wydania,\u003C\/li\u003E\n\u003Cli\u003E\u003Ccode\u003Enew \\DateTime(\u0027last friday\u0027)\u003C\/code\u003E \u2013 bo cykl ka\u017cdego wydania ko\u0144czy si\u0119 w pi\u0105tek, od tej daty iteruj\u0119 \u003Ccode\u003E+1 week\u003C\/code\u003E tworz\u0105c nowe wydania.\u003C\/li\u003E\n\u003C\/ul\u003E\n\u003Cp\u003EDwie sprawy komplikuj\u0105 nam \u017cycie, je\u015bli chcemy stworzy\u0107 testy jednostkowe do tej klasy: po pierwsze nie powinni\u015bmy \u003Cem\u003Enaprawd\u0119\u003C\/em\u003E odwo\u0142ywa\u0107 si\u0119 do API, a jedynie uda\u0107 zapytania, a po drugie powinni\u015bmy uda\u0107 \u017ce \u003Cem\u003Edzisiaj\u003C\/em\u003E jest kt\u00f3ry\u015btam, jaka\u015b sta\u0142a data, do kt\u00f3rej b\u0119d\u0105 dostosowane nasze przypadki testowe.\u003C\/p\u003E\n\u003Cp\u003EMusimy zatem stworzy\u0107 par\u0119 dubli \u2013 klas, kt\u00f3re \u201cprzys\u0142oni\u0105\u201d swoje pierwowzory, podmieniaj\u0105c niekt\u00f3re ich metody na swoje. \u015awietnym narz\u0119dziem do tego celu jest biblioteka \u003Ca href=\u0022https:\/\/github.com\/Codeception\/AspectMock\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E AspectMock\u003C\/a\u003E, potrafi\u0105ca stworzy\u0107 takie duble, kt\u00f3re wszystkim innym nawet si\u0119 nie \u015bni\u0142y (np. duble metod statycznych czy funkcji systemowych).\u003C\/p\u003E\n\u003Cp\u003ENiestety, cho\u0107 AspectMock potrafi \u201cnadpisa\u0107\u201d funkcj\u0119 \u003Ccode\u003Etime()\u003C\/code\u003E, na nic to si\u0119 zda, je\u015bli u\u017cywamy \u003Ccode\u003EDateTime\u003C\/code\u003E (a kto nie u\u017cywa?), a j\u0105 nadpisa\u0107 jest ju\u017c ci\u0119\u017cej. Na szcz\u0119\u015bcie da si\u0119 to zrobi\u0107 za pomoc\u0105 pewnej sztuczki:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?php\nnamespace VR\\Redmine;\n\nclass VersionsHandler\n{\n    \/** @var Api *\/\n    private $api;\n\n    private $now;\n\n    private $until;\n\n    public function __construct(Api $api)\n    {\n        $this-\u0026gt;api = $api;\n\n        $this-\u0026gt;now = TimeProvider::getDateTimeFormatted();\n\n        $this-\u0026gt;until = TimeProvider::getDateTimeFormatted(\u0027+8 weeks\u0027);\n    }\n\n    \/\/ (...)\n\n    private function getToBeCreated()\n    {\n        $current = TimeProvider::getDateTime(\u0027last friday\u0027);\n        \/\/ (...)\n    }\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EJak wida\u0107, we wszystkich miejscach, gdzie normalnie u\u017cy\u0142bym \u003Ccode\u003EDateTime\u003C\/code\u003E, ja korzystam z klasy \u003Ccode\u003ETimeProvider\u003C\/code\u003E. Jest ona bardzo pro\u015bciutka:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?php\nnamespace VR\\Redmine;\n\nclass TimeProvider\n{\n    public static function getDateTime($time = \u0027now\u0027)\n    {\n        return new \\DateTime($time);\n    }\n\n    public static function getDateTimeFormatted($time = \u0027now\u0027)\n    {\n        $datetime = self::getDateTime($time);\n\n        return $datetime-\u0026gt;format(\u0027Y.\\WW\u0027);\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EI istnieje tylko po to, by m\u00f3c j\u0105 zdublowa\u0107 w nast\u0119puj\u0105cy spos\u00f3b:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$timeProxy = Test::double(\u0027VR\\\\Redmine\\\\TimeProvider\u0027, [\u0027getDateTime\u0027 =\u0026gt; function($time) {\n    $dt = new \\DateTime(\u00272015-01-14\u0027);\n    return $dt-\u0026gt;modify($time);\n}]);\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EA zatem podczas normalnego uruchomienia aplikacji, \u003Ccode\u003ETimeProvider\u003C\/code\u003E dzia\u0142a po prostu jak nicnierobi\u0105ca fabryka \u003Ccode\u003EDateTime\u003C\/code\u003E\u2019\u00f3w. W czasie test\u00f3w jednak obiera ona za punkt odniesienia arbitraln\u0105 dat\u0119 \u003Ccode\u003E2015-01-04\u003C\/code\u003E, a potem modyfikuje j\u0105 o to, co podamy jej w parametrze, jak jakby dzi\u015b by\u0142 \u003Ccode\u003E2015-01-04\u003C\/code\u003E. Zawsze, niezale\u017cnie kiedy uruchomimy test.\u003C\/p\u003E\n\u003Cp\u003ETeraz wystarczy tylko zdublowa\u0107 funkcj\u0119 odwo\u0142uj\u0105c\u0105 si\u0119 do API i przeprowadzi\u0107 testy:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E$apiProxy = Test::double(\n  \u0027VR\\\\Redmine\\\\Api\u0027,\n  [\u0027curl\u0027 =\u0026gt; function($url, $method = \u0027GET\u0027, $data = []) {\n    if ($method != \u0027GET\u0027) { return null; }\n\n    return json_encode(\/* mocked api response *\/);\n}]);\n\n$handler = new VersionsHandler(new Api);\n\n$this-\u0026gt;assertEquals(\/* expected output *\/, $handler-\u0026gt;handle());\u003C\/code\u003E\u003C\/pre\u003E","words":455,"readTime":2,"lang":"pl"}}},"blog\/technology\/frontendowa-magia-coffeescript-sass-scss-less":{"key":"blog\/technology\/frontendowa-magia-coffeescript-sass-scss-less","type":"article","published":true,"meta":{"createdAt":"2017-04-28T19:43:39+02:00","publishedAt":"2015-07-26T18:00:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"frontendowa-magia-coffeescript-sass-scss-less"},"content":{"pl":{"slug":"frontendowa-magia-coffeescript-sass-scss-less","title":"Frontendowa magia: CoffeeScript, Sass, Scss, Less...","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/frontendowa-magia-coffeescript-sass-scss-less_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022364.93358633776\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEuUlEQVRIib2X228UVRzHP2dmdna6l962l+XSLaVeSiFRsoqAQf8A4jvvtn+CzxhjMDHEEJ8MATG+mfiAzz4QTYCk4UExpqlgAxTa0la67exlZs6Zc3woW7f2tqvQbzKZ35mcM9\/f\/M739zu\/EWYNCCEAeNF24x3Y1XbqgzqasVtBfV2zHEJrbf4T0\/9EHMfYtr3pubUX5I1RmJmZ4fz5j7l27ZstI+XshUMAs7OzXLlyFSkl4+NjFAqFLecJU1fVS8Lc3BxXr36N75cZHx9jePjwjnp04MVnFkAQhFy\/\/gMTExOMjX3IkSMjwO5ZJnZK+0YYY4iiiLt37zI7OwcYOju7KBQGKBQK2LaNMQalFE+ezJNwXNLpBK7IYrcLXGEgjhBOeneHmgn9rVu3uXDhM0ql0iZH29raOHbsKMVikePH3ySVSjM0mAMrBWYZVbZY8Vbokg6iEiN6D227bU05pJTi7NkPKJfL68+klERRhDEGy7LWvzCOY3K5borFtzh9+hT9\/XkqlSqO7XDmVDtOIgdEiMQrW3I1nWWWZaG1BkBrTalUeu6QXp+TzXTQ6e0jWx1m9qcuFjs93jlxiGx7llSqjcjSPFA1hkyJ2oIi27eZ3mlmx2zb5uLFz7l06UsmJycRQtDb04sKLOywg5Q8QF\/yCKP73yVccZl\/sohlWaQqefYfyD8P6W\/UghKHvbexsMj0\/qNZaDg6Gs+b+oSt7NHRUS5f\/gqlFN99Osn33\/6IKttYsUfSypJO99A3fJggMkROBks4xKXnOtGr4Izgq18IHldJWR6dA1vX5JYKoxACx3F4FP9M3D2DlejAjjpxSZPJpsn1SGqpgIXgKWX3EU9H7qH0R6hVDy9zn1wiT2ZgGUT\/thybHNrtEDTGML8yTdw3jek1aNsmSCYptbcz90aRimXxV\/sd0rJGWBrCSIfrn\/zOuQuDlJNZMiIAvA3vbZSNVR8YYzZcWhvi2KCkRkYxUaSIIoXvV\/F9H8dx8DyPTDpJPpsi\/16ITC2TTdfYl1OcyXl4lWc48R3OfTGCuXmbvNE0Hp91rrq9ZYSUNIRhRBRJtNYNixQA0\/P3OJD3KZVsnESCXDeUqwZvKUk50iS7F1gopZnKr5B41oHiVRL6GeL9AbAkQng7FsYNyooVVKsB1WoNKSVKqbUrjpEKypFBrUimpta+I5N1kbEAI9jnS9yMICocxdiaP2faSNYqzC8\/xjcGnNeB5LbaWd+yDQN7LcUNawVOKbVWAMOQMAjQQY3FJR+tfQouHHutzGrJxvb7mZrzWFgKcVYWsJTg6KjDH0nwoxhLJP9NtS02pL0QkM64uK5NtRYS1AKiKEJrjZQRYRixtLRIqEC6gpsT4NiSnqEHtLkpDvqrTP+6xODBVe7dt6jVPGLfJm11NuUMNBTGRqUnXJsON0V7ewqtDTrWxDrGX\/VRShFrxcOqJpFIEAt4vAqOlswlKqQti1AKyhWDMWvb3YhGnq3slvshKRU3btxgYmKChw8fsby8TDZrcGybMEriukm6uroYHBzk5MkTFIvFDeu36yTWe+8X0VMHQUAcxziOQzK5u3B3wp40+a38Bu1Jk98KWnao8T+rGbtlh142Qav4G4sUzOeqTN6uAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/frontendowa-magia-coffeescript-sass-scss-less_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022364.93358633776\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ETworz\u0105c kiedy\u015b stron\u0119 internetow\u0105, trzeba by\u0142o si\u0119 nie\u017ale napracowa\u0107, by na ka\u017cdym komputerze wygl\u0105da\u0142a mniej wi\u0119cej tak samo. Ka\u017cda przegl\u0105darka interpretowa\u0142a sobie kod po swojemu. Teraz jednak, gdy wszystkie nowe wersje popularnych przegl\u0105darek trzymaj\u0105 si\u0119 standard\u00f3w (a nawet m\u00f3j \u003Cem\u003Eulubiony\u003C\/em\u003E by\u0142y klient, Santander, przerzuci\u0142 si\u0119 z dinozaur\u00f3w na aktualne wydania), no a zdecydowan\u0105 wi\u0119kszo\u015b\u0107 pozosta\u0142ych jeszcze r\u00f3\u017cnic mi\u0119dzy przegl\u0105darkami mo\u017cna zniwelowa\u0107 u\u017cywaj\u0105c \u003Ca href=\u0022https:\/\/necolas.github.io\/normalize.css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E normalize.css\u003C\/a\u003E oraz \u003Ca href=\u0022https:\/\/jquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E jQuery\u003C\/a\u003E, mog\u0119 z ca\u0142\u0105 stanowczo\u015bci\u0105 uzna\u0107 \u003Cstrong\u003Eprzeno\u015bno\u015b\u0107\u003C\/strong\u003E za najwi\u0119ksz\u0105 zalet\u0119 technologii webowych. Piszesz kod raz, a dzia\u0142a wsz\u0119dzie.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/frontendowa-magia-coffeescript-sass-scss-less_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022729.86717267552\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAbCAYAAAAULC3gAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEuUlEQVRIib2X228UVRzHP2dmdna6l962l+XSLaVeSiFRsoqAQf8A4jvvtn+CzxhjMDHEEJ8MATG+mfiAzz4QTYCk4UExpqlgAxTa0la67exlZs6Zc3woW7f2tqvQbzKZ35mcM9\/f\/M739zu\/EWYNCCEAeNF24x3Y1XbqgzqasVtBfV2zHEJrbf4T0\/9EHMfYtr3pubUX5I1RmJmZ4fz5j7l27ZstI+XshUMAs7OzXLlyFSkl4+NjFAqFLecJU1fVS8Lc3BxXr36N75cZHx9jePjwjnp04MVnFkAQhFy\/\/gMTExOMjX3IkSMjwO5ZJnZK+0YYY4iiiLt37zI7OwcYOju7KBQGKBQK2LaNMQalFE+ezJNwXNLpBK7IYrcLXGEgjhBOeneHmgn9rVu3uXDhM0ql0iZH29raOHbsKMVikePH3ySVSjM0mAMrBWYZVbZY8Vbokg6iEiN6D227bU05pJTi7NkPKJfL68+klERRhDEGy7LWvzCOY3K5borFtzh9+hT9\/XkqlSqO7XDmVDtOIgdEiMQrW3I1nWWWZaG1BkBrTalUeu6QXp+TzXTQ6e0jWx1m9qcuFjs93jlxiGx7llSqjcjSPFA1hkyJ2oIi27eZ3mlmx2zb5uLFz7l06UsmJycRQtDb04sKLOywg5Q8QF\/yCKP73yVccZl\/sohlWaQqefYfyD8P6W\/UghKHvbexsMj0\/qNZaDg6Gs+b+oSt7NHRUS5f\/gqlFN99Osn33\/6IKttYsUfSypJO99A3fJggMkROBks4xKXnOtGr4Izgq18IHldJWR6dA1vX5JYKoxACx3F4FP9M3D2DlejAjjpxSZPJpsn1SGqpgIXgKWX3EU9H7qH0R6hVDy9zn1wiT2ZgGUT\/thybHNrtEDTGML8yTdw3jek1aNsmSCYptbcz90aRimXxV\/sd0rJGWBrCSIfrn\/zOuQuDlJNZMiIAvA3vbZSNVR8YYzZcWhvi2KCkRkYxUaSIIoXvV\/F9H8dx8DyPTDpJPpsi\/16ITC2TTdfYl1OcyXl4lWc48R3OfTGCuXmbvNE0Hp91rrq9ZYSUNIRhRBRJtNYNixQA0\/P3OJD3KZVsnESCXDeUqwZvKUk50iS7F1gopZnKr5B41oHiVRL6GeL9AbAkQng7FsYNyooVVKsB1WoNKSVKqbUrjpEKypFBrUimpta+I5N1kbEAI9jnS9yMICocxdiaP2faSNYqzC8\/xjcGnNeB5LbaWd+yDQN7LcUNawVOKbVWAMOQMAjQQY3FJR+tfQouHHutzGrJxvb7mZrzWFgKcVYWsJTg6KjDH0nwoxhLJP9NtS02pL0QkM64uK5NtRYS1AKiKEJrjZQRYRixtLRIqEC6gpsT4NiSnqEHtLkpDvqrTP+6xODBVe7dt6jVPGLfJm11NuUMNBTGRqUnXJsON0V7ewqtDTrWxDrGX\/VRShFrxcOqJpFIEAt4vAqOlswlKqQti1AKyhWDMWvb3YhGnq3slvshKRU3btxgYmKChw8fsby8TDZrcGybMEriukm6uroYHBzk5MkTFIvFDeu36yTWe+8X0VMHQUAcxziOQzK5u3B3wp40+a38Bu1Jk98KWnao8T+rGbtlh142Qav4G4sUzOeqTN6uAAAAAElFTkSuQmCC\u0022 data-src=\u0022https:\/\/avris.it\/image\/frontendowa-magia-coffeescript-sass-scss-less_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022960\u0022 height=\u0022729.86717267552\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ETworz\u0105c kiedy\u015b stron\u0119 internetow\u0105, trzeba by\u0142o si\u0119 nie\u017ale napracowa\u0107, by na ka\u017cdym komputerze wygl\u0105da\u0142a mniej wi\u0119cej tak samo. Ka\u017cda przegl\u0105darka interpretowa\u0142a sobie kod po swojemu. Teraz jednak, gdy wszystkie nowe wersje popularnych przegl\u0105darek trzymaj\u0105 si\u0119 standard\u00f3w (a nawet m\u00f3j \u003Cem\u003Eulubiony\u003C\/em\u003E by\u0142y klient, Santander, przerzuci\u0142 si\u0119 z dinozaur\u00f3w na aktualne wydania), no a zdecydowan\u0105 wi\u0119kszo\u015b\u0107 pozosta\u0142ych jeszcze r\u00f3\u017cnic mi\u0119dzy przegl\u0105darkami mo\u017cna zniwelowa\u0107 u\u017cywaj\u0105c \u003Ca href=\u0022https:\/\/necolas.github.io\/normalize.css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E normalize.css\u003C\/a\u003E oraz \u003Ca href=\u0022https:\/\/jquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E jQuery\u003C\/a\u003E, mog\u0119 z ca\u0142\u0105 stanowczo\u015bci\u0105 uzna\u0107 \u003Cstrong\u003Eprzeno\u015bno\u015b\u0107\u003C\/strong\u003E za najwi\u0119ksz\u0105 zalet\u0119 technologii webowych. Piszesz kod raz, a dzia\u0142a wsz\u0119dzie.\u003C\/p\u003E\n\u003Cp\u003EZ drugiej jednak strony t\u0119 sam\u0105 przeno\u015bno\u015b\u0107 mo\u017cna te\u017c uzna\u0107 za wad\u0119. Ca\u0142y Internet sprowadza si\u0119 bowiem ostatnio do tej \u015bwi\u0119tej tr\u00f3jcy: \u003Cstrong\u003EHTML5 + CSS3 + JS\u003C\/strong\u003E. Bo skoro te trzy potrafi\u0105 ju\u017c wszystko to, co kiedy\u015b umia\u0142y tylko \u003Ca href=\u0022https:\/\/niebezpiecznik.pl\/tag\/flash\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Flash\u003C\/a\u003E czy aplety \u003Ca href=\u0022https:\/\/niebezpiecznik.pl\/tag\/java\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Javy\u003C\/a\u003E, to po co ryzykowa\u0107 bezpiecze\u0144stwo witryny, zmusza\u0107 u\u017cytkownika do instalowania wtyczek i odbiera\u0107 sobie mo\u017cliwo\u015b\u0107 lepszej integracji element\u00f3w strony? Po prostu \u003Cem\u003Enie ma sensu\u003C\/em\u003E wychodzi\u0107 poza \u015bwi\u0119t\u0105 tr\u00f3jc\u0119. A jej rozw\u00f3j jest niestety ograniczony aktualizacjami przegl\u0105darek. Czy zatem jeste\u015bmy na ni\u0105 \u003Cstrong\u003Eskazani\u003C\/strong\u003E?\u003C\/p\u003E\n\u003Cp\u003ENa szcz\u0119\u015bcie nie! Istnieje ca\u0142a rodzina j\u0119zyk\u00f3w, kt\u00f3re bardzo sprytnie obchodz\u0105 ten problem. Wprowadzaj\u0105 ogromne ulepszenia i u\u0142atwienia, ale bez potrzeby interpretowania ich przez przegl\u0105darki! Po prostu po stronie programisty s\u0105 kompilowane do jednego z tych j\u0119zyk\u00f3w, kt\u00f3re ka\u017cda przegl\u0105darka rozumie.\u003C\/p\u003E\n\u003Cp\u003EPowiedzmy na przyk\u0142ad, \u017ce chcesz stworzy\u0107 w CSS klasy od \u003Ccode\u003Ecol-1\u003C\/code\u003E do \u003Ccode\u003Ecol-12\u003C\/code\u003E, z kt\u00f3rych ka\u017cda b\u0119dzie nadawa\u0142a DIV-owi szeroko\u015b\u0107 r\u00f3wn\u0105 ile\u015btam dwunastych szeroko\u015bci kontenera. W \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/thesassway.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Sass\u003C\/a\u003E\u003C\/strong\u003E zajmuje to trzy linijki:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs scss border\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003E@for\u003C\/span\u003E \u003Cspan class=\u0022hljs-variable\u0022\u003E$i\u003C\/span\u003E from \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E through \u003Cspan class=\u0022hljs-number\u0022\u003E12\u003C\/span\u003E\n  .col-#{\u003Cspan class=\u0022hljs-variable\u0022\u003E$i\u003C\/span\u003E}\n    \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-variable\u0022\u003E$i\u003C\/span\u003E\/\u003Cspan class=\u0022hljs-number\u0022\u003E12\u003C\/span\u003E * \u003Cspan class=\u0022hljs-number\u0022\u003E100%\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EA jest kompilowane do takiego kodu:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs css border\u0022\u003E\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-1\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E8.33333%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-2\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E16.66667%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-3\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E25%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-4\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E33.33333%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-5\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E41.66667%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-6\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E50%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-7\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E58.33333%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-8\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E66.66667%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-9\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E75%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-10\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E83.33333%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-11\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E91.66667%\u003C\/span\u003E; }\n\n\u003Cspan class=\u0022hljs-selector-class\u0022\u003E.col-12\u003C\/span\u003E {\n  \u003Cspan class=\u0022hljs-attribute\u0022\u003Ewidth\u003C\/span\u003E: \u003Cspan class=\u0022hljs-number\u0022\u003E100%\u003C\/span\u003E; }\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EPierwszy z nich jest prosty, kr\u00f3tki i czytelny dla cz\u0142owieka, drugi natomiast zostanie zrozumiany przez wszystkie przegl\u0105darki. I wilk syty i owca ca\u0142a! Sass zawiera wiele element\u00f3w, kt\u00f3rych prostemu CSS-owi brakuje: zmiennych, instrukcji warunkowych, p\u0119tli, funkcji (tzw. mixins), zagnie\u017cd\u017ce\u0144, operacji arytmetycznych... O ile bardziej \u003Cstrong\u003Eelastyczny\u003C\/strong\u003E staje si\u0119 kod, gdy mo\u017cemy zdefiniowa\u0107 na przyk\u0142ad zmienn\u0105 \u003Ccode\u003E$navWidth: 300px\u003C\/code\u003E i u\u017cy\u0107 jej w pi\u0119ciu innych miejscach (r\u00f3wnie\u017c w wyra\u017ceniach arytmetycznych, np. \u003Ccode\u003Ewidth: $navWidth \/ 2 + 16px\u003C\/code\u003E), zamiast wsz\u0119dzie podawa\u0107 j\u0105 wprost. Ka\u017cda zmiana szeroko\u015bci nawigacji jest wtedy po prostu \u003Cstrong\u003Ebanalna\u003C\/strong\u003E, nie wymaga szukania wszystkich zale\u017cno\u015bci. O ile \u003Cstrong\u003Ekr\u00f3tszy i bardziej przejrzysty\u003C\/strong\u003E staje si\u0119 kod, je\u015bli mo\u017cemy cz\u0119sto powtarzaj\u0105ce si\u0119 elementy zamkn\u0105\u0107 w parametryzowane mixiny i po prostu si\u0119 do nich odwo\u0142ywa\u0107? \u015awietn\u0105 list\u0119 sassowych ficzer\u00f3w mo\u017cna znale\u017a\u0107 cho\u0107by na \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Sass_(stylesheet_language)\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Wikipedii\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EPodobnymi do niego j\u0119zykami s\u0105 \u003Cstrong\u003EScss\u003C\/strong\u003E oras \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/lesscss.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Less\u003C\/a\u003E\u003C\/strong\u003E. Wol\u0119 jednak Sassa z jednego powodu \u2013 \u003Cstrong\u003Ebrak klamer\u003C\/strong\u003E. Skoro i tak w ka\u017cdym kodzie powinno si\u0119 stosowa\u0107 odpowiednie wci\u0119cia tabulatorami, to klamry staj\u0105 si\u0119 zwyczajnie zb\u0119dne. J\u0119zyk, kt\u00f3ry wymusza stosowanie wci\u0119\u0107 w kodzie po pierwsze wymaga mniej klepania w klawiatur\u0119, a po drugie daje gwarancj\u0119, \u017ce po kim by\u015bmy kodu nie przej\u0119li, zawsze przynajmniej pod tym wzgl\u0119dem b\u0119dzie on czytelny. Same plusy! Z tego samego za\u0142o\u017cenia wyszli chocia\u017cby tw\u00f3rcy \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/www.ruby-lang.org\/pl\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Rubiego\u003C\/a\u003E\u003C\/strong\u003E, \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/www.python.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Pythona\u003C\/a\u003E\u003C\/strong\u003E czy \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/coffeescript.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E CoffeeScriptu\u003C\/a\u003E\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cp\u003EA no w\u0142a\u015bnie, \u003Cstrong\u003ECoffeeScript\u003C\/strong\u003E. \u017bywy dow\u00f3d, \u017ce nawet tworzenie JavaScript\u00f3w mo\u017ce by\u0107 przyjemne (s\u0142owo daj\u0119, nie uwierzy\u0142bym, gdybym nie spr\u00f3bowa\u0142). W JS to dopiero jest nadmiar nawias\u00f3w i klamer:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003Esse = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E EventSource(Routing.generate(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027conversation_check\u0027\u003C\/span\u003E));\nsse.addEventListener(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027conversation\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003Ee\u003C\/span\u003E) \u003C\/span\u003E{\n  \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (e.data == \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027test\u0027\u003C\/span\u003E || e.data == \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027dev\u0027\u003C\/span\u003E) { \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E; }\n  $.post(Routing.generate(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027conversation_fetch\u0027\u003C\/span\u003E), { \u003Cspan class=\u0022hljs-attr\u0022\u003Eids\u003C\/span\u003E: e.data }, \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E(\u003Cspan class=\u0022hljs-params\u0022\u003Edata\u003C\/span\u003E) \u003C\/span\u003E{\n    conversation.html(data);\n  });\n}, \u003Cspan class=\u0022hljs-literal\u0022\u003Efalse\u003C\/span\u003E);\n\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETa sama funkcjonalno\u015b\u0107 w CoffeeScripcie wygl\u0105da nast\u0119puj\u0105co:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs javascript border\u0022\u003Esse = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E EventSource Routing.generate \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027conversation_check\u0027\u003C\/span\u003E\nsse.addEventListener \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027conversation\u0027\u003C\/span\u003E, (e) -\u0026gt;\n  \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E e.data \u003Cspan class=\u0022hljs-keyword\u0022\u003Ein\u003C\/span\u003E [\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027test\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027dev\u0027\u003C\/span\u003E]\n  $.post(Routing.generate(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027conversation_fetch\u0027\u003C\/span\u003E), { \u003Cspan class=\u0022hljs-attr\u0022\u003Eids\u003C\/span\u003E: e.data }, (data) -\u0026gt;\n    conversation.html(data)\n  )\n, \u003Cspan class=\u0022hljs-literal\u0022\u003Efalse\u003C\/span\u003E\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWystarczy\u0142o zast\u0105pienie sk\u0142adni \u003Ccode\u003Efunction(a) {...}\u003C\/code\u003E prostym \u003Ccode\u003E(a) -\u0026gt; ...\u003C\/code\u003E, zmiana klamer na wci\u0119cia oraz mo\u017cliwo\u015b\u0107 pomini\u0119cia niekt\u00f3rych nawias\u00f3w w parametrach funkcji \u2013 i voil\u00e0! Mniej klepania w klawiatur\u0119 i doszukiwania si\u0119 par nawias\u00f3w, a tre\u015bci tyle samo!\u003C\/p\u003E\n\u003Cp\u003ENie spos\u00f3b si\u0119 nachwali\u0107 wszystkich ficzer\u00f3w CoffeeScriptu... JSON-owe obiekty mo\u017cna w nim definiowa\u0107 podobnie jak w \u003Ca href=\u0022http:\/\/yaml.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E YAML-u\u003C\/a\u003E, p\u0119tl\u0119 mo\u017cna od 1 do 100 zawrze\u0107 w kr\u00f3ciutkim zapisie \u003Ccode\u003E1..100\u003C\/code\u003E, zmiennych nie trzeba deklarowa\u0107, mo\u017cna im przypisywa\u0107 warto\u015bci do wielu na raz (a nawet zamienia\u0107 je warto\u015bciami w jednej linijce: \u003Ccode\u003E[foo, bar] = [bar, foo]\u003C\/code\u003E i tyle!). Najlepiej po prostu przejrze\u0107 jego \u003Ca href=\u0022http:\/\/coffeescript.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E stron\u0119 domow\u0105\u003C\/a\u003E i milcze\u0107 w \u003Cstrong\u003Ezachwycie\u003C\/strong\u003E!\u003C\/p\u003E\n\u003Cp\u003ER\u00f3wnie\u017c w przypadku HTML-a istnieje wiele technologii, kt\u00f3re pozwalaj\u0105 na wygenerowanie go na postawie bardziej wyrafinowanych j\u0119zyk\u00f3w. Lecz tutaj to troch\u0119 co innego. Mowa o template engines takich jak \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/twig.sensiolabs.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Twig\u003C\/a\u003E\u003C\/strong\u003E, \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/www.smarty.net\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Smarty\u003C\/a\u003E\u003C\/strong\u003E, \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/haml.info\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Haml\u003C\/a\u003E\u003C\/strong\u003E czy \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/www.stuartellis.eu\/articles\/erb\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Erb\u003C\/a\u003E\u003C\/strong\u003E \u2013 one jednak s\u0105 kompilowane do j\u0119zyk\u00f3w wykonywanych po stronie serwera (PHP, Ruby, Python...), wi\u0119c niezbyt pasuj\u0105 do mojego zestawienia. (Nota bene w Hamlu jeszcze bardziej zredukowana jest klamrowa redundancja: z \u003Ccode\u003E\u0026lt;html\u0026gt;\u0026lt;\/html\u0026gt;\u003C\/code\u003E robi si\u0119 zwyk\u0142e \u003Ccode\u003E%html\u003C\/code\u003E)\u003C\/p\u003E\n\u003Cp\u003EPotrafi\u0119 znale\u017a\u0107 tylko dwie wady ca\u0142ej tej rodziny technologii w por\u00f3wnaniu do \u003Cem\u003E\u015bwi\u0119tej tr\u00f3jcy\u003C\/em\u003E. Po pierwsze, tak jak przegl\u0105darki, tak samo frontendowi programi\u015bci tr\u00f3jc\u0119 znaj\u0105 z ca\u0142\u0105 pewno\u015bci\u0105, czego nie zawsze mo\u017cna powiedzie\u0107 o jej m\u0142odszym rodze\u0144stwie. Wi\u0119c je\u015bli kto\u015b dostanie po tobie projekt, w kt\u00f3rym u\u017cywa\u0142e\u015b Sassa czy CoffeeScriptu, mo\u017ce nie by\u0107 mu zbyt kolorowo. Z drugiej jednak strony, s\u0105 to przecie\u017c technologie \u003Cstrong\u003Ebardzo \u0142atwe do przyswojenia\u003C\/strong\u003E, a zarazem niezmiernie przydatne i wygodne. Wi\u0119c chyba tylko wy\u015bwiadczy\u0142by\u015b mu przys\u0142ug\u0119, prawda?\u003C\/p\u003E\n\u003Cp\u003EPo drugie natomiast, kompilowanie trwa i wymaga zachodu. Wystarczy jednak zainstalowa\u0107 \u003Ca href=\u0022http:\/\/bower.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Bowera\u003C\/a\u003E albo skonfigurowa\u0107 sobie watchera w \u003Ca href=\u0022https:\/\/www.jetbrains.com\/phpstorm\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PhpStormie\u003C\/a\u003E, aby ka\u017cde zapisanie pliku automatycznie uruchamia\u0142o kompilacj\u0119. Naprawd\u0119, wygodniej ju\u017c si\u0119 tego zrobi\u0107 nie da!\u003C\/p\u003E\n\u003Cp\u003EA poza tym \u003Cstrong\u003Esame plusy\u003C\/strong\u003E. Je\u015bli tworzysz strony, a jeszcze nie znasz tych technologii \u2013 \u003Cstrong\u003Ekoniecznie je wypr\u00f3buj!\u003C\/strong\u003E Z odrobin\u0105 wprawy i do\u015bwiadczenia, po\u0142owa twoich frontendowych problem\u00f3w mo\u017ce znikn\u0105\u0107.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["coffeescript","frontend","haml","html","internet","javascript","kompilacja","less","programowanie","sass","scss","twig"],"hasMore":true,"image":"https:\/\/avris.it\/image\/frontendowa-magia-coffeescript-sass-scss-less_small.jpeg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/frontendowa-magia-coffeescript-sass-scss-less_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/frontendowa-magia-coffeescript-sass-scss-less_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022182.46679316888\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ETworz\u0105c kiedy\u015b stron\u0119 internetow\u0105, trzeba by\u0142o si\u0119 nie\u017ale napracowa\u0107, by na ka\u017cdym komputerze wygl\u0105da\u0142a mniej wi\u0119cej tak samo. Ka\u017cda przegl\u0105darka interpretowa\u0142a sobie kod po swojemu. Teraz jednak, gdy wszystkie nowe wersje popularnych przegl\u0105darek trzymaj\u0105 si\u0119 standard\u00f3w (a nawet m\u00f3j \u003Cem\u003Eulubiony\u003C\/em\u003E by\u0142y klient, Santander, przerzuci\u0142 si\u0119 z dinozaur\u00f3w na aktualne wydania), no a zdecydowan\u0105 wi\u0119kszo\u015b\u0107 pozosta\u0142ych jeszcze r\u00f3\u017cnic mi\u0119dzy przegl\u0105darkami mo\u017cna zniwelowa\u0107 u\u017cywaj\u0105c \u003Ca href=\u0022https:\/\/necolas.github.io\/normalize.css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E normalize.css\u003C\/a\u003E oraz \u003Ca href=\u0022https:\/\/jquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E jQuery\u003C\/a\u003E, mog\u0119 z ca\u0142\u0105 stanowczo\u015bci\u0105 uzna\u0107 \u003Cstrong\u003Eprzeno\u015bno\u015b\u0107\u003C\/strong\u003E za najwi\u0119ksz\u0105 zalet\u0119 technologii webowych. Piszesz kod raz, a dzia\u0142a wsz\u0119dzie.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/frontendowa-magia-coffeescript-sass-scss-less_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/frontendowa-magia-coffeescript-sass-scss-less_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022182.46679316888\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003ETworz\u0105c kiedy\u015b stron\u0119 internetow\u0105, trzeba by\u0142o si\u0119 nie\u017ale napracowa\u0107, by na ka\u017cdym komputerze wygl\u0105da\u0142a mniej wi\u0119cej tak samo. Ka\u017cda przegl\u0105darka interpretowa\u0142a sobie kod po swojemu. Teraz jednak, gdy wszystkie nowe wersje popularnych przegl\u0105darek trzymaj\u0105 si\u0119 standard\u00f3w (a nawet m\u00f3j \u003Cem\u003Eulubiony\u003C\/em\u003E by\u0142y klient, Santander, przerzuci\u0142 si\u0119 z dinozaur\u00f3w na aktualne wydania), no a zdecydowan\u0105 wi\u0119kszo\u015b\u0107 pozosta\u0142ych jeszcze r\u00f3\u017cnic mi\u0119dzy przegl\u0105darkami mo\u017cna zniwelowa\u0107 u\u017cywaj\u0105c \u003Ca href=\u0022https:\/\/necolas.github.io\/normalize.css\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E normalize.css\u003C\/a\u003E oraz \u003Ca href=\u0022https:\/\/jquery.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E jQuery\u003C\/a\u003E, mog\u0119 z ca\u0142\u0105 stanowczo\u015bci\u0105 uzna\u0107 \u003Cstrong\u003Eprzeno\u015bno\u015b\u0107\u003C\/strong\u003E za najwi\u0119ksz\u0105 zalet\u0119 technologii webowych. Piszesz kod raz, a dzia\u0142a wsz\u0119dzie.\u003C\/p\u003E\n\u003Cp\u003EZ drugiej jednak strony t\u0119 sam\u0105 przeno\u015bno\u015b\u0107 mo\u017cna te\u017c uzna\u0107 za wad\u0119. Ca\u0142y Internet sprowadza si\u0119 bowiem ostatnio do tej \u015bwi\u0119tej tr\u00f3jcy: \u003Cstrong\u003EHTML5 + CSS3 + JS\u003C\/strong\u003E. Bo skoro te trzy potrafi\u0105 ju\u017c wszystko to, co kiedy\u015b umia\u0142y tylko \u003Ca href=\u0022https:\/\/niebezpiecznik.pl\/tag\/flash\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Flash\u003C\/a\u003E czy aplety \u003Ca href=\u0022https:\/\/niebezpiecznik.pl\/tag\/java\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Javy\u003C\/a\u003E, to po co ryzykowa\u0107 bezpiecze\u0144stwo witryny, zmusza\u0107 u\u017cytkownika do instalowania wtyczek i odbiera\u0107 sobie mo\u017cliwo\u015b\u0107 lepszej integracji element\u00f3w strony? Po prostu \u003Cem\u003Enie ma sensu\u003C\/em\u003E wychodzi\u0107 poza \u015bwi\u0119t\u0105 tr\u00f3jc\u0119. A jej rozw\u00f3j jest niestety ograniczony aktualizacjami przegl\u0105darek. Czy zatem jeste\u015bmy na ni\u0105 \u003Cstrong\u003Eskazani\u003C\/strong\u003E?\u003C\/p\u003E\n\u003Cp\u003ENa szcz\u0119\u015bcie nie! Istnieje ca\u0142a rodzina j\u0119zyk\u00f3w, kt\u00f3re bardzo sprytnie obchodz\u0105 ten problem. Wprowadzaj\u0105 ogromne ulepszenia i u\u0142atwienia, ale bez potrzeby interpretowania ich przez przegl\u0105darki! Po prostu po stronie programisty s\u0105 kompilowane do jednego z tych j\u0119zyk\u00f3w, kt\u00f3re ka\u017cda przegl\u0105darka rozumie.\u003C\/p\u003E\n\u003Cp\u003EPowiedzmy na przyk\u0142ad, \u017ce chcesz stworzy\u0107 w CSS klasy od \u003Ccode\u003Ecol-1\u003C\/code\u003E do \u003Ccode\u003Ecol-12\u003C\/code\u003E, z kt\u00f3rych ka\u017cda b\u0119dzie nadawa\u0142a DIV-owi szeroko\u015b\u0107 r\u00f3wn\u0105 ile\u015btam dwunastych szeroko\u015bci kontenera. W \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/thesassway.com\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Sass\u003C\/a\u003E\u003C\/strong\u003E zajmuje to trzy linijki:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E@for $i from 1 through 12\n  .col-#{$i}\n    width: $i\/12 * 100%\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EA jest kompilowane do takiego kodu:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E.col-1 {\n  width: 8.33333%; }\n\n.col-2 {\n  width: 16.66667%; }\n\n.col-3 {\n  width: 25%; }\n\n.col-4 {\n  width: 33.33333%; }\n\n.col-5 {\n  width: 41.66667%; }\n\n.col-6 {\n  width: 50%; }\n\n.col-7 {\n  width: 58.33333%; }\n\n.col-8 {\n  width: 66.66667%; }\n\n.col-9 {\n  width: 75%; }\n\n.col-10 {\n  width: 83.33333%; }\n\n.col-11 {\n  width: 91.66667%; }\n\n.col-12 {\n  width: 100%; }\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EPierwszy z nich jest prosty, kr\u00f3tki i czytelny dla cz\u0142owieka, drugi natomiast zostanie zrozumiany przez wszystkie przegl\u0105darki. I wilk syty i owca ca\u0142a! Sass zawiera wiele element\u00f3w, kt\u00f3rych prostemu CSS-owi brakuje: zmiennych, instrukcji warunkowych, p\u0119tli, funkcji (tzw. mixins), zagnie\u017cd\u017ce\u0144, operacji arytmetycznych... O ile bardziej \u003Cstrong\u003Eelastyczny\u003C\/strong\u003E staje si\u0119 kod, gdy mo\u017cemy zdefiniowa\u0107 na przyk\u0142ad zmienn\u0105 \u003Ccode\u003E$navWidth: 300px\u003C\/code\u003E i u\u017cy\u0107 jej w pi\u0119ciu innych miejscach (r\u00f3wnie\u017c w wyra\u017ceniach arytmetycznych, np. \u003Ccode\u003Ewidth: $navWidth \/ 2 + 16px\u003C\/code\u003E), zamiast wsz\u0119dzie podawa\u0107 j\u0105 wprost. Ka\u017cda zmiana szeroko\u015bci nawigacji jest wtedy po prostu \u003Cstrong\u003Ebanalna\u003C\/strong\u003E, nie wymaga szukania wszystkich zale\u017cno\u015bci. O ile \u003Cstrong\u003Ekr\u00f3tszy i bardziej przejrzysty\u003C\/strong\u003E staje si\u0119 kod, je\u015bli mo\u017cemy cz\u0119sto powtarzaj\u0105ce si\u0119 elementy zamkn\u0105\u0107 w parametryzowane mixiny i po prostu si\u0119 do nich odwo\u0142ywa\u0107? \u015awietn\u0105 list\u0119 sassowych ficzer\u00f3w mo\u017cna znale\u017a\u0107 cho\u0107by na \u003Ca href=\u0022https:\/\/en.wikipedia.org\/wiki\/Sass_(stylesheet_language)\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Wikipedii\u003C\/a\u003E.\u003C\/p\u003E\n\u003Cp\u003EPodobnymi do niego j\u0119zykami s\u0105 \u003Cstrong\u003EScss\u003C\/strong\u003E oras \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/lesscss.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Less\u003C\/a\u003E\u003C\/strong\u003E. Wol\u0119 jednak Sassa z jednego powodu \u2013 \u003Cstrong\u003Ebrak klamer\u003C\/strong\u003E. Skoro i tak w ka\u017cdym kodzie powinno si\u0119 stosowa\u0107 odpowiednie wci\u0119cia tabulatorami, to klamry staj\u0105 si\u0119 zwyczajnie zb\u0119dne. J\u0119zyk, kt\u00f3ry wymusza stosowanie wci\u0119\u0107 w kodzie po pierwsze wymaga mniej klepania w klawiatur\u0119, a po drugie daje gwarancj\u0119, \u017ce po kim by\u015bmy kodu nie przej\u0119li, zawsze przynajmniej pod tym wzgl\u0119dem b\u0119dzie on czytelny. Same plusy! Z tego samego za\u0142o\u017cenia wyszli chocia\u017cby tw\u00f3rcy \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/www.ruby-lang.org\/pl\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Rubiego\u003C\/a\u003E\u003C\/strong\u003E, \u003Cstrong\u003E\u003Ca href=\u0022https:\/\/www.python.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Pythona\u003C\/a\u003E\u003C\/strong\u003E czy \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/coffeescript.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E CoffeeScriptu\u003C\/a\u003E\u003C\/strong\u003E.\u003C\/p\u003E\n\u003Cp\u003EA no w\u0142a\u015bnie, \u003Cstrong\u003ECoffeeScript\u003C\/strong\u003E. \u017bywy dow\u00f3d, \u017ce nawet tworzenie JavaScript\u00f3w mo\u017ce by\u0107 przyjemne (s\u0142owo daj\u0119, nie uwierzy\u0142bym, gdybym nie spr\u00f3bowa\u0142). W JS to dopiero jest nadmiar nawias\u00f3w i klamer:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Esse = new EventSource(Routing.generate(\u0027conversation_check\u0027));\nsse.addEventListener(\u0027conversation\u0027, function(e) {\n  if (e.data == \u0027test\u0027 || e.data == \u0027dev\u0027) { return; }\n  $.post(Routing.generate(\u0027conversation_fetch\u0027), { ids: e.data }, function(data) {\n    conversation.html(data);\n  });\n}, false);\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETa sama funkcjonalno\u015b\u0107 w CoffeeScripcie wygl\u0105da nast\u0119puj\u0105co:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Esse = new EventSource Routing.generate \u0027conversation_check\u0027\nsse.addEventListener \u0027conversation\u0027, (e) -\u0026gt;\n  return if e.data in [\u0027test\u0027, \u0027dev\u0027]\n  $.post(Routing.generate(\u0027conversation_fetch\u0027), { ids: e.data }, (data) -\u0026gt;\n    conversation.html(data)\n  )\n, false\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWystarczy\u0142o zast\u0105pienie sk\u0142adni \u003Ccode\u003Efunction(a) {...}\u003C\/code\u003E prostym \u003Ccode\u003E(a) -\u0026gt; ...\u003C\/code\u003E, zmiana klamer na wci\u0119cia oraz mo\u017cliwo\u015b\u0107 pomini\u0119cia niekt\u00f3rych nawias\u00f3w w parametrach funkcji \u2013 i voil\u00e0! Mniej klepania w klawiatur\u0119 i doszukiwania si\u0119 par nawias\u00f3w, a tre\u015bci tyle samo!\u003C\/p\u003E\n\u003Cp\u003ENie spos\u00f3b si\u0119 nachwali\u0107 wszystkich ficzer\u00f3w CoffeeScriptu... JSON-owe obiekty mo\u017cna w nim definiowa\u0107 podobnie jak w \u003Ca href=\u0022http:\/\/yaml.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E YAML-u\u003C\/a\u003E, p\u0119tl\u0119 mo\u017cna od 1 do 100 zawrze\u0107 w kr\u00f3ciutkim zapisie \u003Ccode\u003E1..100\u003C\/code\u003E, zmiennych nie trzeba deklarowa\u0107, mo\u017cna im przypisywa\u0107 warto\u015bci do wielu na raz (a nawet zamienia\u0107 je warto\u015bciami w jednej linijce: \u003Ccode\u003E[foo, bar] = [bar, foo]\u003C\/code\u003E i tyle!). Najlepiej po prostu przejrze\u0107 jego \u003Ca href=\u0022http:\/\/coffeescript.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E stron\u0119 domow\u0105\u003C\/a\u003E i milcze\u0107 w \u003Cstrong\u003Ezachwycie\u003C\/strong\u003E!\u003C\/p\u003E\n\u003Cp\u003ER\u00f3wnie\u017c w przypadku HTML-a istnieje wiele technologii, kt\u00f3re pozwalaj\u0105 na wygenerowanie go na postawie bardziej wyrafinowanych j\u0119zyk\u00f3w. Lecz tutaj to troch\u0119 co innego. Mowa o template engines takich jak \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/twig.sensiolabs.org\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Twig\u003C\/a\u003E\u003C\/strong\u003E, \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/www.smarty.net\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Smarty\u003C\/a\u003E\u003C\/strong\u003E, \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/haml.info\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Haml\u003C\/a\u003E\u003C\/strong\u003E czy \u003Cstrong\u003E\u003Ca href=\u0022http:\/\/www.stuartellis.eu\/articles\/erb\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Erb\u003C\/a\u003E\u003C\/strong\u003E \u2013 one jednak s\u0105 kompilowane do j\u0119zyk\u00f3w wykonywanych po stronie serwera (PHP, Ruby, Python...), wi\u0119c niezbyt pasuj\u0105 do mojego zestawienia. (Nota bene w Hamlu jeszcze bardziej zredukowana jest klamrowa redundancja: z \u003Ccode\u003E\u0026lt;html\u0026gt;\u0026lt;\/html\u0026gt;\u003C\/code\u003E robi si\u0119 zwyk\u0142e \u003Ccode\u003E%html\u003C\/code\u003E)\u003C\/p\u003E\n\u003Cp\u003EPotrafi\u0119 znale\u017a\u0107 tylko dwie wady ca\u0142ej tej rodziny technologii w por\u00f3wnaniu do \u003Cem\u003E\u015bwi\u0119tej tr\u00f3jcy\u003C\/em\u003E. Po pierwsze, tak jak przegl\u0105darki, tak samo frontendowi programi\u015bci tr\u00f3jc\u0119 znaj\u0105 z ca\u0142\u0105 pewno\u015bci\u0105, czego nie zawsze mo\u017cna powiedzie\u0107 o jej m\u0142odszym rodze\u0144stwie. Wi\u0119c je\u015bli kto\u015b dostanie po tobie projekt, w kt\u00f3rym u\u017cywa\u0142e\u015b Sassa czy CoffeeScriptu, mo\u017ce nie by\u0107 mu zbyt kolorowo. Z drugiej jednak strony, s\u0105 to przecie\u017c technologie \u003Cstrong\u003Ebardzo \u0142atwe do przyswojenia\u003C\/strong\u003E, a zarazem niezmiernie przydatne i wygodne. Wi\u0119c chyba tylko wy\u015bwiadczy\u0142by\u015b mu przys\u0142ug\u0119, prawda?\u003C\/p\u003E\n\u003Cp\u003EPo drugie natomiast, kompilowanie trwa i wymaga zachodu. Wystarczy jednak zainstalowa\u0107 \u003Ca href=\u0022http:\/\/bower.io\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Bowera\u003C\/a\u003E albo skonfigurowa\u0107 sobie watchera w \u003Ca href=\u0022https:\/\/www.jetbrains.com\/phpstorm\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PhpStormie\u003C\/a\u003E, aby ka\u017cde zapisanie pliku automatycznie uruchamia\u0142o kompilacj\u0119. Naprawd\u0119, wygodniej ju\u017c si\u0119 tego zrobi\u0107 nie da!\u003C\/p\u003E\n\u003Cp\u003EA poza tym \u003Cstrong\u003Esame plusy\u003C\/strong\u003E. Je\u015bli tworzysz strony, a jeszcze nie znasz tych technologii \u2013 \u003Cstrong\u003Ekoniecznie je wypr\u00f3buj!\u003C\/strong\u003E Z odrobin\u0105 wprawy i do\u015bwiadczenia, po\u0142owa twoich frontendowych problem\u00f3w mo\u017ce znikn\u0105\u0107.\u003C\/p\u003E","words":1075,"readTime":5,"lang":"pl"}}},"blog\/technology\/jest\u0119-admin\u0119":{"key":"blog\/technology\/jest\u0119-admin\u0119","type":"article","published":true,"meta":{"createdAt":"2017-04-28T19:43:32+02:00","publishedAt":"2015-05-08T13:39:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"jest\u0119-admin\u0119"},"content":{"pl":{"slug":"jest\u0119-admin\u0119","title":"Jest\u0119 Admin\u0119!","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/jest\u0119-admin\u0119_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022480\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAKJ0lEQVRYhZWXaWxc1RXHf\/fNe7PPvLE99jh2vIzHS0xCHEjACSIFCm2Blg8tUUMrylKp\/VAhVULql35pqSr1UwuqQKioaoWgKmRpUakqFhVaiRRKEoizeImdOONMbMcejz2LZ\/N77\/bDLB57nIiepzvv3aN7z\/nfs9xzRiweHpWN306DkCABISjR5nmFLUFA+aeyEuvp3agprYYv1\/eIylSU9ABIUbdmOXQCEVOuyvN\/PInLrRGbmKJjZz\/ToxP0DO0kOnqRzr4eAMZGzjE4dCuzIxO07R5gZX4Bm8eFz+8jNh1lu2cX6h9sdJzsYPJnk5ifmGQ6MzRtC7LwxgItT7Ygj1jk9+Zx7nBx7XgMY4dBR7iDK2NX6Ni1nfDrn6IkZII7H7kXEdLJhrxYfhdruouMzSKrWJiaDVNVCA30MPTlu4laGZQWndseeYDZ+AKubUGaI50sNC0wG5kl6o9y+4\/3oj6uEvpuK\/m78iw8s8DQj4YYefAs+399gIWuBfI\/LBD+fg93PHsn9m84iCkTeBU7SsVioVCI5XiC7p4eJs+P0tTURFdnJ0rBQCkYNLeGGB8fx9nop729nfm5OYKqi\/xqlrnPxhgcHMTX7IcwjI+P4x\/QMTDQNR0tozE2NoZ\/wI\/NZuP9l99n\/rN5wuFw1WP9+24lZ62tAxofH6e5tYVCNsvQ8D4KhQL+thaktFhZTRNoDuLxeOjt62N0dJT27dtJpJMA9AztZGlpCc9eD\/SA3++nJ9IDAvI\/zTGY24HX66W\/v590Os1Tv3wKvU9nZGSkCkjJmeRUE5ESK3LkwAjZVA7WJJ6Qh6RjDt9hgadgIRRBrlDAsCvk06soDjuWYeB0u\/BbKhlp0OrwMvtOgMaPGlFUhVnfLM6gk3wuT++lXhZbFlmRK9gb7chViWgTMDNFviuGx+8lu5zC06TTOyYRUjFrQr1EprBIPTqFfjhVl2RbkVXOMi1t\/wJrLZKhj\/E1n8eGKCelLKWZlCiS+keRAv\/xXpJv+kscWcJc90bWJO5WkjY+G8FQlS0lpesEUAWiLLb0RXlukwr6sV6STKE\/ltz6uBL+OXaKF949wg7HPlqVbTydeYImswmQiJq7ah3MOWxCVC0iROU+Ks+3ctlGE0uShybRD5dACSFKFhLw0odv8dwbryAUDc3poJjP01+I8E7mH\/gsf80VabES+hh\/8zkUoawLL+NYn9\/AZbWPgJKljuhVxyAEn8cu86vjryIkbGttwSwUyaUznCmc4UXnyxtcuBL6D\/6W89XDVAc132WzKBshUgNZ1HAEgaN9rBzxV2\/7v5z8gGKhyP4776Ap4MdlL0WFaZq8Jl+rRtdy6AT+lgsl90lRKkWVQXkIUVWnCm7ksXp+w9F+lplEP5xi\/HoM1e4kbUJ8JU1HdzeGYZJMrRI1p5nT5nE1TqO3XChddtUauPn8NTEEqHLrVTcACYGjfSTlJJrbjQ2L2\/oirLaFkBZMTUzg8TpIp03ebniBHwQjCClKdbRyxk01tVrAy3jV+pUbEW\/cLRAI9GO9zPcuY0MSDoZI2jV0n4\/P\/R6WMhlSQnDVPoYQkZJlbpo2G9Uqoqpmq3flW1R5IMnYM8SMGbL5PKrTTjgSYXbiIm5NkFrN0a7pPKvfT1Ex64wtZClT60Z5ocL\/QVLCnDbPLwLPYcoiprT44MS\/wa6xYuSYSaRI59Z42L+Ty7vhtOca6QaFj4cLvLr3En8PT7MqisiyUWpHhVRDGF8YUFxbYrdzN6plo9EVJJvJcvnSBG\/99SjjU9PEFldwuz0kG2CkO8We5h7e3JakmF\/FsFxk7BmMGbAsc2sFAtTszlduEsJly5TfMWuR\/HQBp+pEWhZ2TcEmLWYuT3Px8lVUVcNut5Pt9ZHR4BhTyFmLoNuG1+Nn10f7sU0eIHcTjaoXlc2BWx+FJV5OMbAsC8uyyOdz2BUbTiHImxYIgaZpOBx2XC4PK5k8PrebSDhMcXSFg28+RNfl8IZyUn9ygSo29cfrADaT4OLadYQQWJZJPrdKZ5NOS2uQiehcOT3AMtdoa2\/n9j1DLIxfpeOtdva8\/01cRXc5YDfUijpdNWl\/MwuVyOwOYoupGIaBKe0sXc9QWFpjPpNEU1SQkly+QHNTkIWl63T\/7hbuun7vZjNsgrNRt1Kq\/KJmbJ6vjxZHgAbdj9PpoLV3ALsvwJph4vQ4sNs1kGAZkkikh9iVGYaSe6m9ROSmUc8DpT4By0PU874W1bmluZ9QqJVAY5Dt+\/YhXS70liCapmKz2QhHenA6PczHZuCRBFSr2uYE3+yZsstEtWvbgmr4UkLxej+\/yb\/Ef5s+p\/ezCG1mK\/lclifs30NRbNgdCvfd\/wCrmRTCMGj6TpplJgkc7UP5giVK3TqfNn1LSC8N4J07yCAKg8v9G4C+nf8bxovncHg1TntyRKcnyaXSICFwOElSTqIfuxGojVTKDVnxYLnuVOcVMP345g6ilPOk1glCQIsRpNXfiOrQyBYKTE1OEG7uqBZN\/XCS5KFJLKzqvs1yKm+lpJz1sGF9bklJemkA39w95cCUNULkhjlAsphjdnaWmeg0j9xxX1WWEAL9sSTJQ1NYwrqpnHL7UZ\/2UkAmvgPv3EGErPlPfhMK2dz02Lz0DX+doY4BKv15pR3UD6dIMoX\/eC+K3Np9W16MkhIY39zBUtKKuua3bg+AS9V4qH0Q2msa\/E3\/o2pB2aSok6OsKyibTkrSFTCyNgxljXk37qmlSstyIxKiBCr16BTWFjVfNaXFp+4FXFlJ1gOrSS\/NSZ3Vzk\/oi0VoMBs42XyKPYtDfL7tDL60l4wrAwL6lvu45r2GZmqEMmkmMjHEmgGVfyaqjWanl8VsCo\/mIFss4LE7yRRyyGFBbn4M12gQ1bRh2AwGUv3YHu7Y+3Pv7w9xvtfgoeefYXGvjam7LxH5SYQY11j7dI3ce3nO\/uksX7p2D38WbzD82\/20PBNi4p0JCs8XKdxVZNGM4z7Qx9lEjO6De5lX17B3h\/hgcoR7Hv8WJ6LjDH71bi6krxPYFaHv3mFWdmdJfCWB9qRG\/P44a2fWUAyXjUQiQUNDA\/F4nK6uLvSATjQaJRa\/WnWQ2W0QjUbp7O\/E6XQiFEGCBEV3kUJbkeRiHMuyiE\/N4PP5OPvhCXw+H+FwmGQyicfnZXZ2Fq\/XS1dXF4uLiwBYlsXw8DCpVApSoHozkLc7uHDyApZloSgKM+Mz7LlrD8sPrnDq01PoiQBWG8SuxmhoaOD06dMoikLMjHGb53ayIkeGLIqiEGxo5NTJU+y5ZReWZdHQHORaLEYgEMDr9XJpcpLTpkkqlcLj8RCPx3nv3Xe5cuUKfUYvItH+gYzPtdMoG8mRBcCNm0UWSTWk6Ux1UDTX0PGTIUOBImq5h2qkkQQJLGERen2BS4tXCIfaSKRTNPr8XFmYxe\/2IhAUjCICgdfporBWamNNy+JaOoGmqggJ9n918D+7cfvl9qsBqQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/jest\u0119-admin\u0119_small.jpeg\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022480\u0022 height=\u0022480\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMo\u017ce nie napisz\u0119 tu nic ciekawego, ale po prostu musz\u0119 si\u0119 pochwali\u0107 :D Kupi\u0142em sobie wirtualny serwer prywatny. Czy\u015bciutki Linux na nim, do zainstalowania i skonfigurowania wszystko: Apache, PHP, MySQL, SFTP, domeny, maile i ca\u0142a masa innych pierd\u00f3\u0142. W wielu z nich grzeba\u0142em pierwszy raz w \u017cyciu. Ale chyba dogrzeba\u0142em si\u0119 do wszystkiego co trzeba, bo wygl\u0105da na \u015bmigaj\u0105ce \u015blicznie.\u003C\/p\u003E\n\u003Cp\u003EWreszcie mog\u0119 deployowa\u0107 po ludzku, z gitem i composerem, pisa\u0107 w nowszej wersji PHP, skonfigurowa\u0107 sobie, co mi si\u0119 tylko \u017cywnie podoba, nie robi\u0107 r\u0119cznie eksport\u00f3w rozk\u0142adu na \u003Ca href=\u0022http:\/\/bus.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Busa\u003C\/a\u003E, kt\u00f3remu nie starcza\u0142o pami\u0119ci na wsp\u00f3\u0142dzielonym hostingu... Miodzio! :3\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/jest\u0119-admin\u0119_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022625\u0022 height=\u0022625\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAKJ0lEQVRYhZWXaWxc1RXHf\/fNe7PPvLE99jh2vIzHS0xCHEjACSIFCm2Blg8tUUMrylKp\/VAhVULql35pqSr1UwuqQKioaoWgKmRpUakqFhVaiRRKEoizeImdOONMbMcejz2LZ\/N77\/bDLB57nIiepzvv3aN7z\/nfs9xzRiweHpWN306DkCABISjR5nmFLUFA+aeyEuvp3agprYYv1\/eIylSU9ABIUbdmOXQCEVOuyvN\/PInLrRGbmKJjZz\/ToxP0DO0kOnqRzr4eAMZGzjE4dCuzIxO07R5gZX4Bm8eFz+8jNh1lu2cX6h9sdJzsYPJnk5ifmGQ6MzRtC7LwxgItT7Ygj1jk9+Zx7nBx7XgMY4dBR7iDK2NX6Ni1nfDrn6IkZII7H7kXEdLJhrxYfhdruouMzSKrWJiaDVNVCA30MPTlu4laGZQWndseeYDZ+AKubUGaI50sNC0wG5kl6o9y+4\/3oj6uEvpuK\/m78iw8s8DQj4YYefAs+399gIWuBfI\/LBD+fg93PHsn9m84iCkTeBU7SsVioVCI5XiC7p4eJs+P0tTURFdnJ0rBQCkYNLeGGB8fx9nop729nfm5OYKqi\/xqlrnPxhgcHMTX7IcwjI+P4x\/QMTDQNR0tozE2NoZ\/wI\/NZuP9l99n\/rN5wuFw1WP9+24lZ62tAxofH6e5tYVCNsvQ8D4KhQL+thaktFhZTRNoDuLxeOjt62N0dJT27dtJpJMA9AztZGlpCc9eD\/SA3++nJ9IDAvI\/zTGY24HX66W\/v590Os1Tv3wKvU9nZGSkCkjJmeRUE5ESK3LkwAjZVA7WJJ6Qh6RjDt9hgadgIRRBrlDAsCvk06soDjuWYeB0u\/BbKhlp0OrwMvtOgMaPGlFUhVnfLM6gk3wuT++lXhZbFlmRK9gb7chViWgTMDNFviuGx+8lu5zC06TTOyYRUjFrQr1EprBIPTqFfjhVl2RbkVXOMi1t\/wJrLZKhj\/E1n8eGKCelLKWZlCiS+keRAv\/xXpJv+kscWcJc90bWJO5WkjY+G8FQlS0lpesEUAWiLLb0RXlukwr6sV6STKE\/ltz6uBL+OXaKF949wg7HPlqVbTydeYImswmQiJq7ah3MOWxCVC0iROU+Ks+3ctlGE0uShybRD5dACSFKFhLw0odv8dwbryAUDc3poJjP01+I8E7mH\/gsf80VabES+hh\/8zkUoawLL+NYn9\/AZbWPgJKljuhVxyAEn8cu86vjryIkbGttwSwUyaUznCmc4UXnyxtcuBL6D\/6W89XDVAc132WzKBshUgNZ1HAEgaN9rBzxV2\/7v5z8gGKhyP4776Ap4MdlL0WFaZq8Jl+rRtdy6AT+lgsl90lRKkWVQXkIUVWnCm7ksXp+w9F+lplEP5xi\/HoM1e4kbUJ8JU1HdzeGYZJMrRI1p5nT5nE1TqO3XChddtUauPn8NTEEqHLrVTcACYGjfSTlJJrbjQ2L2\/oirLaFkBZMTUzg8TpIp03ebniBHwQjCClKdbRyxk01tVrAy3jV+pUbEW\/cLRAI9GO9zPcuY0MSDoZI2jV0n4\/P\/R6WMhlSQnDVPoYQkZJlbpo2G9Uqoqpmq3flW1R5IMnYM8SMGbL5PKrTTjgSYXbiIm5NkFrN0a7pPKvfT1Ex64wtZClT60Z5ocL\/QVLCnDbPLwLPYcoiprT44MS\/wa6xYuSYSaRI59Z42L+Ty7vhtOca6QaFj4cLvLr3En8PT7MqisiyUWpHhVRDGF8YUFxbYrdzN6plo9EVJJvJcvnSBG\/99SjjU9PEFldwuz0kG2CkO8We5h7e3JakmF\/FsFxk7BmMGbAsc2sFAtTszlduEsJly5TfMWuR\/HQBp+pEWhZ2TcEmLWYuT3Px8lVUVcNut5Pt9ZHR4BhTyFmLoNuG1+Nn10f7sU0eIHcTjaoXlc2BWx+FJV5OMbAsC8uyyOdz2BUbTiHImxYIgaZpOBx2XC4PK5k8PrebSDhMcXSFg28+RNfl8IZyUn9ygSo29cfrADaT4OLadYQQWJZJPrdKZ5NOS2uQiehcOT3AMtdoa2\/n9j1DLIxfpeOtdva8\/01cRXc5YDfUijpdNWl\/MwuVyOwOYoupGIaBKe0sXc9QWFpjPpNEU1SQkly+QHNTkIWl63T\/7hbuun7vZjNsgrNRt1Kq\/KJmbJ6vjxZHgAbdj9PpoLV3ALsvwJph4vQ4sNs1kGAZkkikh9iVGYaSe6m9ROSmUc8DpT4By0PU874W1bmluZ9QqJVAY5Dt+\/YhXS70liCapmKz2QhHenA6PczHZuCRBFSr2uYE3+yZsstEtWvbgmr4UkLxej+\/yb\/Ef5s+p\/ezCG1mK\/lclifs30NRbNgdCvfd\/wCrmRTCMGj6TpplJgkc7UP5giVK3TqfNn1LSC8N4J07yCAKg8v9G4C+nf8bxovncHg1TntyRKcnyaXSICFwOElSTqIfuxGojVTKDVnxYLnuVOcVMP345g6ilPOk1glCQIsRpNXfiOrQyBYKTE1OEG7uqBZN\/XCS5KFJLKzqvs1yKm+lpJz1sGF9bklJemkA39w95cCUNULkhjlAsphjdnaWmeg0j9xxX1WWEAL9sSTJQ1NYwrqpnHL7UZ\/2UkAmvgPv3EGErPlPfhMK2dz02Lz0DX+doY4BKv15pR3UD6dIMoX\/eC+K3Np9W16MkhIY39zBUtKKuua3bg+AS9V4qH0Q2msa\/E3\/o2pB2aSok6OsKyibTkrSFTCyNgxljXk37qmlSstyIxKiBCr16BTWFjVfNaXFp+4FXFlJ1gOrSS\/NSZ3Vzk\/oi0VoMBs42XyKPYtDfL7tDL60l4wrAwL6lvu45r2GZmqEMmkmMjHEmgGVfyaqjWanl8VsCo\/mIFss4LE7yRRyyGFBbn4M12gQ1bRh2AwGUv3YHu7Y+3Pv7w9xvtfgoeefYXGvjam7LxH5SYQY11j7dI3ce3nO\/uksX7p2D38WbzD82\/20PBNi4p0JCs8XKdxVZNGM4z7Qx9lEjO6De5lX17B3h\/hgcoR7Hv8WJ6LjDH71bi6krxPYFaHv3mFWdmdJfCWB9qRG\/P44a2fWUAyXjUQiQUNDA\/F4nK6uLvSATjQaJRa\/WnWQ2W0QjUbp7O\/E6XQiFEGCBEV3kUJbkeRiHMuyiE\/N4PP5OPvhCXw+H+FwmGQyicfnZXZ2Fq\/XS1dXF4uLiwBYlsXw8DCpVApSoHozkLc7uHDyApZloSgKM+Mz7LlrD8sPrnDq01PoiQBWG8SuxmhoaOD06dMoikLMjHGb53ayIkeGLIqiEGxo5NTJU+y5ZReWZdHQHORaLEYgEMDr9XJpcpLTpkkqlcLj8RCPx3nv3Xe5cuUKfUYvItH+gYzPtdMoG8mRBcCNm0UWSTWk6Ux1UDTX0PGTIUOBImq5h2qkkQQJLGERen2BS4tXCIfaSKRTNPr8XFmYxe\/2IhAUjCICgdfporBWamNNy+JaOoGmqggJ9n918D+7cfvl9qsBqQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/jest\u0119-admin\u0119_big.jpeg\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022625\u0022 height=\u0022625\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMo\u017ce nie napisz\u0119 tu nic ciekawego, ale po prostu musz\u0119 si\u0119 pochwali\u0107 :D Kupi\u0142em sobie wirtualny serwer prywatny. Czy\u015bciutki Linux na nim, do zainstalowania i skonfigurowania wszystko: Apache, PHP, MySQL, SFTP, domeny, maile i ca\u0142a masa innych pierd\u00f3\u0142. W wielu z nich grzeba\u0142em pierwszy raz w \u017cyciu. Ale chyba dogrzeba\u0142em si\u0119 do wszystkiego co trzeba, bo wygl\u0105da na \u015bmigaj\u0105ce \u015blicznie.\u003C\/p\u003E\n\u003Cp\u003EWreszcie mog\u0119 deployowa\u0107 po ludzku, z gitem i composerem, pisa\u0107 w nowszej wersji PHP, skonfigurowa\u0107 sobie, co mi si\u0119 tylko \u017cywnie podoba, nie robi\u0107 r\u0119cznie eksport\u00f3w rozk\u0142adu na \u003Ca href=\u0022http:\/\/bus.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E Busa\u003C\/a\u003E, kt\u00f3remu nie starcza\u0142o pami\u0119ci na wsp\u00f3\u0142dzielonym hostingu... Miodzio! :3\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["administracja","apache","konfiguracja","linux","php","serwer","vps"],"hasMore":false,"image":"https:\/\/avris.it\/image\/jest\u0119-admin\u0119_small.jpeg","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/jest\u0119-admin\u0119_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/jest\u0119-admin\u0119_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022240\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMo\u017ce nie napisz\u0119 tu nic ciekawego, ale po prostu musz\u0119 si\u0119 pochwali\u0107 :D Kupi\u0142em sobie wirtualny serwer prywatny. Czy\u015bciutki Linux na nim, do zainstalowania i skonfigurowania wszystko: Apache, PHP, MySQL, SFTP, domeny, maile i ca\u0142a masa innych pierd\u00f3\u0142. W wielu z nich grzeba\u0142em pierwszy raz w \u017cyciu. Ale chyba dogrzeba\u0142em si\u0119 do wszystkiego co trzeba, bo wygl\u0105da na \u015bmigaj\u0105ce \u015blicznie.\u003C\/p\u003E\n\u003Cp\u003EWreszcie mog\u0119 deployowa\u0107 po ludzku, z gitem i composerem, pisa\u0107 w nowszej wersji PHP, skonfigurowa\u0107 sobie, co mi si\u0119 tylko \u017cywnie podoba, nie robi\u0107 r\u0119cznie eksport\u00f3w rozk\u0142adu na \u003Ca href=\u0022http:\/\/bus.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Busa\u003C\/a\u003E, kt\u00f3remu nie starcza\u0142o pami\u0119ci na wsp\u00f3\u0142dzielonym hostingu... Miodzio! :3\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/jest\u0119-admin\u0119_big.jpeg\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/jest\u0119-admin\u0119_mini.jpeg\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022240\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EMo\u017ce nie napisz\u0119 tu nic ciekawego, ale po prostu musz\u0119 si\u0119 pochwali\u0107 :D Kupi\u0142em sobie wirtualny serwer prywatny. Czy\u015bciutki Linux na nim, do zainstalowania i skonfigurowania wszystko: Apache, PHP, MySQL, SFTP, domeny, maile i ca\u0142a masa innych pierd\u00f3\u0142. W wielu z nich grzeba\u0142em pierwszy raz w \u017cyciu. Ale chyba dogrzeba\u0142em si\u0119 do wszystkiego co trzeba, bo wygl\u0105da na \u015bmigaj\u0105ce \u015blicznie.\u003C\/p\u003E\n\u003Cp\u003EWreszcie mog\u0119 deployowa\u0107 po ludzku, z gitem i composerem, pisa\u0107 w nowszej wersji PHP, skonfigurowa\u0107 sobie, co mi si\u0119 tylko \u017cywnie podoba, nie robi\u0107 r\u0119cznie eksport\u00f3w rozk\u0142adu na \u003Ca href=\u0022http:\/\/bus.avris.it\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E Busa\u003C\/a\u003E, kt\u00f3remu nie starcza\u0142o pami\u0119ci na wsp\u00f3\u0142dzielonym hostingu... Miodzio! :3\u003C\/p\u003E","words":112,"readTime":null,"lang":"pl"}}},"blog\/technology\/czysty-kod-w-praktyce-autoloader-w-php":{"key":"blog\/technology\/czysty-kod-w-praktyce-autoloader-w-php","type":"article","published":true,"meta":{"createdAt":"2017-04-28T19:43:30+02:00","publishedAt":"2015-04-06T19:40:00+02:00","group":null,"category":"blog","subcategory":"technology","slug":"czysty-kod-w-praktyce-autoloader-w-php"},"content":{"pl":{"slug":"czysty-kod-w-praktyce-autoloader-w-php","title":"\u201cCzysty kod\u201d w praktyce \u2013 Autoloader w PHP","intro":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022328\u0022 height=\u0022467\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAkCAYAAAB8DZEQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHFUlEQVRIibWWy49dRxHGf9Xd55z7vnfGM\/Z4cCY2xA62ZBCWsyCOxQKRVaygOJHYskAsEH8AOzbAEikII3ZsvGHBBqRIYYEwSBYQSHBisLHj1\/jaM+N53vd5dBeLM7Fn\/AhCiE86On1Kp+urqq6uKnHfeFt1bQkzfxB\/7zbUWojPkFobTSpgE0gzUAURGG5Sfe8c4jPqtRpplpEXBc4YojgiiWI2+30qSUy6vc\/p\/euEpEkoBDnyEhiLOodmOYigkxSptAihJJHWDNmRV4mv\/IajR16gWqmQZhmD0Yg7i3c5+\/oZ7i8tAdC9v8Sly\/9A3LfPq8Yt1FoIigSPisEYwYtgfMCrlp4AxhjwGebBDbQUIKqAAApphsQRr37xAFfvbXH7+m2cDlK0mqG2VEgcEbWraJbjJxmSROyzMC4C3lqsKhEVsr2HUe8ZiAFguuKw1qJZjrOGcXMGpnr4juDoLyNBMTN7UVNu8MMx6gNUYqoGXOyYqQpYQ+6VucQyzDz9UcqgPwExNCJHM7aMKxH1imNrbcDKMMM0azgabUJrD7VKzELFEDYHdG3MkdkW66mnHRuSakwalPupJzfKnSB4DCGK6DSF4ANDHxjnQjCG9VFBOslx1hJZg1NiJMuZiuvkvTG16RbzCHFkmbEGDcok8wRnEQVnDWmAQoSaM4wzaMSOXh4woUzAQVZgnaXICsQ5XNxukC4u0vU59dlpkt6EOLIspgGngbo15AK9AM0kouospvBsjQscSiQQO0MQgxhhmHmMCM5ZPKCbE0x26QLR84eQ6SmGmccHJbOWPARGQRn7gPdKoeBDQADvA5rm6CRHjGGEYK2h4gyRAQ0BP5ogaY5WEwyHThKiGIwgkxStJhRFwOcFVaCKoqoQFFXwWUHIPSioM6gRYiDNCjaGGUXmCapIHKGALq\/iSDOCgq71kHaDce6ZFaVai7F5wUaudKoRFcBZYeADMcpsxZIAq5knUmXWCRpgrLA5yrGRo3AG027iIEdvfowe+hzGe4os455XNPEYlCCG8SiDOEJ9gYiAArkHVQRY8xAmGRoUC9gkIss9OhzB+jqOtbtw9BSSe0LwSF5AFCFrGzDV5qUDDb51aoEPV0a8MFOjGlsu3esTGeFQp8LaOGc4zjn92Sku3+vxzrV1vnKow48u3EGLgOl0MCR1zGgC1sBwBJ1WaWnICCFwtO04\/5cuP7l4l6FX3v79LU4caNFJLO2q43K3x7kLN7m9PuIHv7vFD197kSvdHloENMvQfh\/HaJNggdX7aKONpiniU3ARMpqg6YTaMOd5zZm2cHV9zB9vbPCvpT7v3drg3Nlj\/LO7hRQFk5VNLl9b5td\/uIqiUIxhsoWVhRPf5+b7EEUYiSFLYfVOWeKDZ2VpjTMn9rPQdARjaPiCq0s9ltf6vPGFOcIk5d3371DHs7K6ii0mXOmu47Mhpr8K6QZijn9dw\/Jt5NhpJICONiEdwtxhJB2BceAq6KQPU\/NQiaAINOtVvnzyGNPTbaxA4hQxMXc\/vk67EfPLn\/4Mam2kGOL0yp9gahb92ztoow3DHtRbsLaI5ilUalDkpYd79kEI4BxUEw6ffYVrf77I9NwcqRUa07Nc+tUvePnNN9H71yF4KFIcGmB9pewXw37ZEwY9SnzSJ7ax9eDhUmf3cO3Cb5man2d6bh93\/v5Xqo0Gh459HmdtaSyAAZFon6rKkwrLlrRDtqMxAcY52rN7sVHEzMIC436fraUlOvPzrC0u0l9dLXeL4ngm5Bnf5bsSOb526ksYEbZ6PUyzw6AV0W61eBApFx+sPtzinlSyG85arBVAMEYIIeCDUqtVGA4GLCx8hjxPmZmZpttdYmZPh\/F4vFvH7tA8idOvnOS73\/km\/X4fYyzLy8t8+NEVTp9+mU67Sbfb5fjxo9RrVfI854MPPqLeqLNT7\/aZPDtoRgwilJMKoFpWY4SyjsHDcUmAELSsvqqAIvLQk6cdfGlJUN02KOyQCw+ZdkXi8SQp9bptf0BMeQeeCN3TyXe\/H5fvXpfjyVffglOvlWS6bYHuXPPoe6d818Nj60eelWey8CJsrUJrqrSgUod0BHkOSRWyCRhTeitSPiGAi8B72HgAvU2eBhHdJgnC1FST2ZkOaZpRr1VJ07Ts5aokSYL3Aecsw9GYdqvB+kaPpeW1MpgiqAaedka7SA4e3M\/CgX0kSYwq5HlOUXji2JHEMS5yDPpDKtUKRVEwmUyo1+uEEOh2V5ikOSLC4t0lsrx4uidiSgOsNYRQDlDGSJlEqrjI4QtP0IBsW6zbqWutoch9OT+H3cnwiORT7sn\/CpFPsus\/\/\/pfK3\/uwH7arSbwkGR38XsyFR8n\/JSUFYsA3\/vxOc688TrwRO161iXbiadfOADiGsw8h6YD3j3\/c65fu1FSm3huu5\/8fyCi\/BsCrKXMv6hFYQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_small.png\u0022 alt=\u0022\u0022 class=\u0022border-bottom\u0022 width=\u0022328\u0022 height=\u0022467\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKsi\u0105\u017cka Roberta C. Martina \u003Ca href=\u0022http:\/\/helion.pl\/ksiazki\/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u201cCzysty kod\u201d\u003C\/a\u003E bije rekordy sprzeda\u017cy w\u015br\u00f3d pozycji dotycz\u0105cych szeroko poj\u0119tej informatyki. Wstyd wi\u0119c \u017cebym jej nie przeczyta\u0142, no nie? I zdecydowanie polecam j\u0105 ka\u017cdemu programi\u015bcie, kt\u00f3ry chcia\u0142by by\u0107 jak najlepszy w tym, co robi.\u003C\/p\u003E\n\u003Cp\u003EChcia\u0142bym tutaj pokaza\u0107 na konkretnym fragmencie kodu, jak wiele mo\u017ce zmieni\u0107 stosowanie si\u0119 do zasad przedstawionych przez Martina. Na przyk\u0142adzie autoloadera.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","content":"\u003Cfigure\u003E\n                \u003Cnoscript\u003E\n                    \u003Cimg src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022328\u0022 height=\u0022467\u0022\u003E                \n                \u003C\/noscript\u003E\n                \u003Cspan class=\u0022hide-noscript\u0022\u003E\u003Cimg src=\u0022data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAkCAYAAAB8DZEQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHFUlEQVRIibWWy49dRxHGf9Xd55z7vnfGM\/Z4cCY2xA62ZBCWsyCOxQKRVaygOJHYskAsEH8AOzbAEikII3ZsvGHBBqRIYYEwSBYQSHBisLHj1\/jaM+N53vd5dBeLM7Fn\/AhCiE86On1Kp+urqq6uKnHfeFt1bQkzfxB\/7zbUWojPkFobTSpgE0gzUAURGG5Sfe8c4jPqtRpplpEXBc4YojgiiWI2+30qSUy6vc\/p\/euEpEkoBDnyEhiLOodmOYigkxSptAihJJHWDNmRV4mv\/IajR16gWqmQZhmD0Yg7i3c5+\/oZ7i8tAdC9v8Sly\/9A3LfPq8Yt1FoIigSPisEYwYtgfMCrlp4AxhjwGebBDbQUIKqAAApphsQRr37xAFfvbXH7+m2cDlK0mqG2VEgcEbWraJbjJxmSROyzMC4C3lqsKhEVsr2HUe8ZiAFguuKw1qJZjrOGcXMGpnr4juDoLyNBMTN7UVNu8MMx6gNUYqoGXOyYqQpYQ+6VucQyzDz9UcqgPwExNCJHM7aMKxH1imNrbcDKMMM0azgabUJrD7VKzELFEDYHdG3MkdkW66mnHRuSakwalPupJzfKnSB4DCGK6DSF4ANDHxjnQjCG9VFBOslx1hJZg1NiJMuZiuvkvTG16RbzCHFkmbEGDcok8wRnEQVnDWmAQoSaM4wzaMSOXh4woUzAQVZgnaXICsQ5XNxukC4u0vU59dlpkt6EOLIspgGngbo15AK9AM0kouospvBsjQscSiQQO0MQgxhhmHmMCM5ZPKCbE0x26QLR84eQ6SmGmccHJbOWPARGQRn7gPdKoeBDQADvA5rm6CRHjGGEYK2h4gyRAQ0BP5ogaY5WEwyHThKiGIwgkxStJhRFwOcFVaCKoqoQFFXwWUHIPSioM6gRYiDNCjaGGUXmCapIHKGALq\/iSDOCgq71kHaDce6ZFaVai7F5wUaudKoRFcBZYeADMcpsxZIAq5knUmXWCRpgrLA5yrGRo3AG027iIEdvfowe+hzGe4os455XNPEYlCCG8SiDOEJ9gYiAArkHVQRY8xAmGRoUC9gkIss9OhzB+jqOtbtw9BSSe0LwSF5AFCFrGzDV5qUDDb51aoEPV0a8MFOjGlsu3esTGeFQp8LaOGc4zjn92Sku3+vxzrV1vnKow48u3EGLgOl0MCR1zGgC1sBwBJ1WaWnICCFwtO04\/5cuP7l4l6FX3v79LU4caNFJLO2q43K3x7kLN7m9PuIHv7vFD197kSvdHloENMvQfh\/HaJNggdX7aKONpiniU3ARMpqg6YTaMOd5zZm2cHV9zB9vbPCvpT7v3drg3Nlj\/LO7hRQFk5VNLl9b5td\/uIqiUIxhsoWVhRPf5+b7EEUYiSFLYfVOWeKDZ2VpjTMn9rPQdARjaPiCq0s9ltf6vPGFOcIk5d3371DHs7K6ii0mXOmu47Mhpr8K6QZijn9dw\/Jt5NhpJICONiEdwtxhJB2BceAq6KQPU\/NQiaAINOtVvnzyGNPTbaxA4hQxMXc\/vk67EfPLn\/4Mam2kGOL0yp9gahb92ztoow3DHtRbsLaI5ilUalDkpYd79kEI4BxUEw6ffYVrf77I9NwcqRUa07Nc+tUvePnNN9H71yF4KFIcGmB9pewXw37ZEwY9SnzSJ7ax9eDhUmf3cO3Cb5man2d6bh93\/v5Xqo0Gh459HmdtaSyAAZFon6rKkwrLlrRDtqMxAcY52rN7sVHEzMIC436fraUlOvPzrC0u0l9dLXeL4ngm5Bnf5bsSOb526ksYEbZ6PUyzw6AV0W61eBApFx+sPtzinlSyG85arBVAMEYIIeCDUqtVGA4GLCx8hjxPmZmZpttdYmZPh\/F4vFvH7tA8idOvnOS73\/km\/X4fYyzLy8t8+NEVTp9+mU67Sbfb5fjxo9RrVfI854MPPqLeqLNT7\/aZPDtoRgwilJMKoFpWY4SyjsHDcUmAELSsvqqAIvLQk6cdfGlJUN02KOyQCw+ZdkXi8SQp9bptf0BMeQeeCN3TyXe\/H5fvXpfjyVffglOvlWS6bYHuXPPoe6d818Nj60eelWey8CJsrUJrqrSgUod0BHkOSRWyCRhTeitSPiGAi8B72HgAvU2eBhHdJgnC1FST2ZkOaZpRr1VJ07Ts5aokSYL3Aecsw9GYdqvB+kaPpeW1MpgiqAaedka7SA4e3M\/CgX0kSYwq5HlOUXji2JHEMS5yDPpDKtUKRVEwmUyo1+uEEOh2V5ikOSLC4t0lsrx4uidiSgOsNYRQDlDGSJlEqrjI4QtP0IBsW6zbqWutoch9OT+H3cnwiORT7sn\/CpFPsus\/\/\/pfK3\/uwH7arSbwkGR38XsyFR8n\/JSUFYsA3\/vxOc688TrwRO161iXbiadfOADiGsw8h6YD3j3\/c65fu1FSm3huu5\/8fyCi\/BsCrKXMv6hFYQAAAABJRU5ErkJggg==\u0022 data-src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_big.png\u0022 alt=\u0022\u0022 class=\u0022border\u0022 width=\u0022328\u0022 height=\u0022467\u0022\u003E\u003C\/span\u003E\n                \n            \u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKsi\u0105\u017cka Roberta C. Martina \u003Ca href=\u0022http:\/\/helion.pl\/ksiazki\/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E \u201cCzysty kod\u201d\u003C\/a\u003E bije rekordy sprzeda\u017cy w\u015br\u00f3d pozycji dotycz\u0105cych szeroko poj\u0119tej informatyki. Wstyd wi\u0119c \u017cebym jej nie przeczyta\u0142, no nie? I zdecydowanie polecam j\u0105 ka\u017cdemu programi\u015bcie, kt\u00f3ry chcia\u0142by by\u0107 jak najlepszy w tym, co robi.\u003C\/p\u003E\n\u003Cp\u003EChcia\u0142bym tutaj pokaza\u0107 na konkretnym fragmencie kodu, jak wiele mo\u017ce zmieni\u0107 stosowanie si\u0119 do zasad przedstawionych przez Martina. Na przyk\u0142adzie autoloadera.\u003C\/p\u003E\n\u003Cp\u003ETylko najpierw kr\u00f3tki wst\u0119p, co to w og\u00f3le jest \u201cautoloader\u201d. Ot\u00f3\u017c: przy ka\u017cdym \u017c\u0105daniu do serwera uruchamiana jest nowa instancja interpretera PHP. Aby nie musia\u0142 on \u0142adowa\u0107 wszystkich plik\u00f3w .php obecnych w projekcie (a potrafi\u0105 ich by\u0107 tysi\u0105ce), lecz tylko te, z kt\u00f3rych akurat w tym \u017c\u0105daniu skorzysta, u\u017cywany jest mechanizm auto\u0142adowania. Dzia\u0142a to tak, \u017ce kiedy interpreter PHP trafi na u\u017cycie klasy, kt\u00f3rej nie zna, odpyta o ni\u0105 po kolei autoloadery, kt\u00f3re ma zarejestrowane. Je\u015bli kt\u00f3ry\u015b z nich zwr\u00f3ci true, oznacza to, \u017ce znalaz\u0142 on plik, w kt\u00f3rym dana klasa powinna si\u0119 znajdowa\u0107, i do\u0142\u0105czy\u0142 go. W przeciwnym razie interpreter pyta kolejnego autoloadera w kolejce, a dopiero je\u015bli wszystkie zawiod\u0105 \u2013 wyrzuca fatal error \u201cClass not found\u201d.\u003C\/p\u003E\n\u003Cp\u003ENapisa\u0142em sobie kiedy\u015b ma\u0142\u0105 klas\u0119 autoloadera, a raczej poprzerabia\u0142em jak\u0105\u015b znalezion\u0105 na necie. Wygl\u0105da\u0142a tak:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EAutoloader\u003C\/span\u003E \u003C\/span\u003E{\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $namespace;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $path;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $valid = \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003E__construct\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($namespace, $path = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\u0027\u003C\/span\u003E)\u003C\/span\u003E \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace = $namespace;\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path = $path;\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;valid = \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Eautoload\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ is this autoloader responsible for that particular class?\u003C\/span\u003E\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (substr($className,\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E,strlen(\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace)) === \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace) {\n            $path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path . str_replace(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E, ltrim( $className, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E)) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.php\u0027\u003C\/span\u003E;\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (file_exists($path)) {\n                \u003Cspan class=\u0022hljs-keyword\u0022\u003Erequire_once\u003C\/span\u003E($path);\n                \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n            } \u003Cspan class=\u0022hljs-keyword\u0022\u003Eelse\u003C\/span\u003E {\n                \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ if not straightforward, maybe try \u0022common\u0022 class files\u003C\/span\u003E\n                \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ eg. \u0022Exceptions\u0022 for \u0022NotFoundException\u0022;\u003C\/span\u003E\n                $slashPos = strrpos($className,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-number\u0022\u003E-1\u003C\/span\u003E) + \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E;\n                $base = substr($className,\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E,$slashPos);\n                $classPure = substr($className,$slashPos);\n                preg_match_all(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/(?:^|[A-Z])[a-z]+\/\u0027\u003C\/span\u003E,$classPure,$matches);\n                $path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path . str_replace(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E, ltrim( $base . end($matches[\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E]) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027s\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E)) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.php\u0027\u003C\/span\u003E;\n                \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (file_exists($path)) {\n                    \u003Cspan class=\u0022hljs-keyword\u0022\u003Erequire_once\u003C\/span\u003E($path);\n                    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n                } \u003Cspan class=\u0022hljs-keyword\u0022\u003Eelse\u003C\/span\u003E {\n                    \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E; \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ damn, maybe other autoloaders will find something\u003C\/span\u003E\n                }\n            }\n        } \u003Cspan class=\u0022hljs-keyword\u0022\u003Eelse\u003C\/span\u003E {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E; \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/ no, let the other autoloaders handle that\u003C\/span\u003E\n        }\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Eregister\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;valid) {\n            spl_autoload_register(\u003Cspan class=\u0022hljs-keyword\u0022\u003Earray\u003C\/span\u003E(\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027autoload\u0027\u003C\/span\u003E));\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;valid = \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E; \u003Cspan class=\u0022hljs-comment\u0022\u003E\/\/in order not to register it twice\u003C\/span\u003E\n        }\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EPrzyk\u0142adowe u\u017cycie mojego autoloadera wygl\u0105da nast\u0119puj\u0105co:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n$autoloader = \u003Cspan class=\u0022hljs-keyword\u0022\u003Enew\u003C\/span\u003E Autoloader(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027Micrus\\\\\u0027\u003C\/span\u003E, \u003Cspan class=\u0022hljs-keyword\u0022\u003E__DIR__\u003C\/span\u003E . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/vendor\/\u0027\u003C\/span\u003E);\n$autoloader-\u0026gt;register();\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETworzymy nowy autoloader maj\u0105cy obs\u0142ugiwa\u0107 wszystkie klasy w przestrzeni nazw \u201cMicrus\u201d i szukaj\u0105cy ich w katalogu \u201cvendor\u201d, gdzie klasy s\u0105 umieszczone w podfolderach zgodnie ze swoj\u0105 przestrzeni\u0105 nazw. Oznacza to, \u017ce je\u015bli gdzie\u015b w kodzie b\u0119dziemy chcieli stworzy\u0107 nowy obiekt klasy \u003Ccode\u003EMicrus\\Foo\\Bar\\MyClass\u003C\/code\u003E, to powinna si\u0119 ona znajdowa\u0107 w pliku \u003Ccode\u003E\/vendor\/Micrus\/Foo\/Bar\/MyClass.php\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EDo tego dochodzi jeszcze pewien ma\u0142y feature (niezgodny z \u003Ca href=\u0022http:\/\/www.php-fig.org\/psr\/psr-4\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PSR-4\u003C\/a\u003E). Ot\u00f3\u017c je\u015bli chcemy zgrupowa\u0107 kilka podobnych klas w jednym pliku, mo\u017cemy zrobi\u0107 to w bardzo prosty spos\u00f3b. Mamy na przyk\u0142ad klasy wyj\u0105tk\u00f3w, kt\u00f3re potrafi\u0105 by\u0107 naprawd\u0119 malutkie i czasem niewygodnie jest rozbija\u0107 je na osobne pliki. Nazywamy je wszystkie u\u017cywaj\u0105c \u003Ca href=\u0022http:\/\/pl.wikipedia.org\/wiki\/PascalCase\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Csvg class=\u0022icon\u0022\u003E\u003Cuse xlink:href=\u0022#light-link\u0022\u003E\u003C\/use\u003E\u003C\/svg\u003E PascalCase\u003C\/a\u003E z \u201cException\u201d jako ostatnim s\u0142owem i umieszczamy w pliku \u003Ccode\u003EExceptions.php\u003C\/code\u003E (z dodatkowym -s). M\u00f3j autoloader obs\u0142u\u017cy taki przypadek.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\u003Cspan class=\u0022hljs-keyword\u0022\u003Enamespace\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EMicrus\u003C\/span\u003E;\n\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EConfigFileException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ENotFoundException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprotected\u003C\/span\u003E $code = \u003Cspan class=\u0022hljs-number\u0022\u003E404\u003C\/span\u003E; }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ECacheException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003ERouteNotFoundException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprotected\u003C\/span\u003E $code = \u003Cspan class=\u0022hljs-number\u0022\u003E404\u003C\/span\u003E; }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EInvalidArgumentException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EUnauthorisedException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprotected\u003C\/span\u003E $code = \u003Cspan class=\u0022hljs-number\u0022\u003E403\u003C\/span\u003E; }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EArgvException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EDatabaseException\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Eextends\u003C\/span\u003E \\\u003Cspan class=\u0022hljs-title\u0022\u003EException\u003C\/span\u003E \u003C\/span\u003E{ }\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EKod autoloadera nie wygl\u0105da \u017ale (a przynajmniej widzia\u0142em gorsze). Ale pierwsze spojrzenie na metod\u0119 \u201cautoload\u201d potrafi przerazi\u0107. Jest okropnie nieczytelna, mimo \u017ce komentarze obja\u015bniaj\u0105 jej dzia\u0142anie. Potrzeba troch\u0119 wysi\u0142ku, \u017ceby dowiedzie\u0107 si\u0119, co konkretnie robi.\u003C\/p\u003E\n\u003Cp\u003EWszyscy ucz\u0105, zeby pisa\u0107 komentarze do kodu. Du\u017co komentarzy. Nawet je\u015bli wydaje ci si\u0119 to bezsensowne, bo przecie\u017c rozumiesz, co napisa\u0142e\u015b, to musisz bra\u0107 pod uwag\u0119, \u017ce je\u015bli kod trafi w r\u0119ce kogo innego, albo i ty sam zajrzysz do niego rok czy dwa p\u00f3\u017aniej, to rozszyfrowanie go mo\u017ce ju\u017c nie by\u0107 takie proste.\u003C\/p\u003E\n\u003Cp\u003EMartin natomiast uczy czego innego. Dobry kod wymaga tylko znikomej liczby komentarzy. Je\u015bli ich potrzebujesz, by zrozumie\u0107, co si\u0119 dzieje, znaczy \u017ce kod jest nieczytelny. No i komentarze s\u0105 w pewnym sensie \u003Cem\u003Eniebezpieczne\u003C\/em\u003E: zapominamy je pisa\u0107, zapominamy je aktualizowa\u0107, boimy si\u0119 je usuwa\u0107, szybko trac\u0105 na wa\u017cno\u015bci...\u003C\/p\u003E\n\u003Cp\u003ESp\u00f3jrzcie na kod autoloadera po serii poprawek:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022hljs php border\u0022\u003E\u003Cspan class=\u0022hljs-meta\u0022\u003E\u0026lt;?php\u003C\/span\u003E\n\n\u003Cspan class=\u0022hljs-class\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Eclass\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EAutoloader\u003C\/span\u003E\n\u003C\/span\u003E{\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $namespace;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $path;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E $registered = \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003E__construct\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($namespace, $path = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.\u0027\u003C\/span\u003E)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;addEndingSlash($namespace, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;addEndingSlash($path, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E);\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EaddEndingSlash\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($word, $slash = \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        $lastCharacter = substr($word, \u003Cspan class=\u0022hljs-number\u0022\u003E-1\u003C\/span\u003E);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $lastCharacter == $slash ? $word : $word . $slash;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Eautoload\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;isNotResponsibleForClass($className)) {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n        }\n\n        $path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;classNameToFilePath($className);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (file_exists($path)) {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Erequire_once\u003C\/span\u003E($path);\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n        }\n\n        $groupName = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;classNameToGroupName($className);\n        $path = \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;classNameToFilePath($groupName);\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (file_exists($path)) {\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Erequire_once\u003C\/span\u003E($path);\n            \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n        }\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EisNotResponsibleForClass\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E substr($className, \u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E, strlen(\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace)) !== \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;namespace;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EclassNameToFilePath\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;path . str_replace(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/\u0027\u003C\/span\u003E, ltrim( $className, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E)) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027.php\u0027\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Eprivate\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003EclassNameToGroupName\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E($className)\u003C\/span\u003E\n    \u003C\/span\u003E{\n        $slashPos = strrpos($className,\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\\\\\u0027\u003C\/span\u003E,\u003Cspan class=\u0022hljs-number\u0022\u003E-1\u003C\/span\u003E) + \u003Cspan class=\u0022hljs-number\u0022\u003E1\u003C\/span\u003E;\n        $base = substr($className,\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E,$slashPos);\n        $classPure = substr($className,$slashPos);\n        preg_match_all(\u003Cspan class=\u0022hljs-string\u0022\u003E\u0027\/(?:^|[A-Z])[a-z]+\/\u0027\u003C\/span\u003E,$classPure,$matches);\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E $base . end($matches[\u003Cspan class=\u0022hljs-number\u0022\u003E0\u003C\/span\u003E]) . \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027s\u0027\u003C\/span\u003E;\n    }\n\n    \u003Cspan class=\u0022hljs-keyword\u0022\u003Epublic\u003C\/span\u003E \u003Cspan class=\u0022hljs-function\u0022\u003E\u003Cspan class=\u0022hljs-keyword\u0022\u003Efunction\u003C\/span\u003E \u003Cspan class=\u0022hljs-title\u0022\u003Eregister\u003C\/span\u003E\u003Cspan class=\u0022hljs-params\u0022\u003E()\u003C\/span\u003E\n    \u003C\/span\u003E{\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Eif\u003C\/span\u003E (\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;registered) { \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Efalse\u003C\/span\u003E; }\n        spl_autoload_register(\u003Cspan class=\u0022hljs-keyword\u0022\u003Earray\u003C\/span\u003E(\u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E, \u003Cspan class=\u0022hljs-string\u0022\u003E\u0027autoload\u0027\u003C\/span\u003E));\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003E$this\u003C\/span\u003E-\u0026gt;registered = \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n\n        \u003Cspan class=\u0022hljs-keyword\u0022\u003Ereturn\u003C\/span\u003E \u003Cspan class=\u0022hljs-keyword\u0022\u003Etrue\u003C\/span\u003E;\n    }\n}\n\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWystarczy zerkn\u0105\u0107 na funkcj\u0119 autoload, \u017ceby wiedzie\u0107, co robi. Ba, nawet nie trzeba zna\u0107 \u017cadnego j\u0119zyka programowania! To\u017c to niemal czysty angielski: \u201cif this is not responsible for class \u2018class name\u2019, return false\u201d. Nie mamy poj\u0119cia \u003Cem\u003Ejak\u003C\/em\u003E funkcja to robi, ale wida\u0107 jak na d\u0142oni \u003Cem\u003Eco\u003C\/em\u003E takiego wykonuje.\u003C\/p\u003E\n\u003Cp\u003E\u003Cem\u003E\u201cJak\u201d\u003C\/em\u003E natomiast znajduje si\u0119 w osobnych, prywatnych metodach. Rozdzielili\u015bmy zatem od siebie r\u00f3\u017cne \u003Cem\u003Ewarstwy abstrakcji\u003C\/em\u003E, kt\u00f3re wcze\u015bniej by\u0142y zlane w jedn\u0105, brzydk\u0105 funkcj\u0119. Bo je\u015bli kto\u015b zajrzy do naszego kodu, to najprawdopodobniej nie b\u0119dzie potrzebowa\u0142 znajomo\u015bci wszystkiego, co tam naskrobali\u015bmy, lecz przyjdzie z jakim\u015b jednym konkretnym zadaniem: \u201cogarn\u0105\u0107 jak mniej wi\u0119cej dzia\u0142a ten autoloader\u201d, \u201czmieni\u0107 format nazwy \u2018zbiorowego pliku\u2019\u201d, \u201czmieni\u0107 kolejno\u015b\u0107 sprawdzania potencjalnych plik\u00f3w\u201d itp. I dlatego rozdzielenie warstw abstrakcji tak bardzo upro\u015bci mu prac\u0119.\u003C\/p\u003E\n\u003Cp\u003ENa pierwszy rzut oka wydawa\u0142oby si\u0119 sensowniejsze stworzenie metody isResponsibleForClass zamiast jej negacji \u2013 isNotResponsibleForClass. Kto normalny pyta\u0142by klas\u0119, czy \u003Cem\u003Enie jest\u003C\/em\u003E za co\u015b odpowiedzialna? Odpowied\u017a \u201ctak, nie jestem\u201d tylko niepotrzebnie by wszystko zagmatwa\u0142a, prawda? No w\u0142a\u015bnie niekoniecznie. U\u017cycie tej metody jest tylko jedno i sprowadza si\u0119 do \u201cje\u015bli nie jeste\u015b za to odpowiedzialna, to daj sobie spok\u00f3j\u201d. Zapisanie tego warunku jako \u003Ccode\u003Eif (!$this-\u0026gt;isResponsibleForClass($className))\u003C\/code\u003E zmniejsza czytelno\u015b\u0107, poniewa\u017c tego wykrzyknika prawie nie wida\u0107. Zawsze zapominamy o wykrzyknikach...\u003C\/p\u003E\n\u003Cp\u003EZanegowanie dopad\u0142o te\u017c zmienn\u0105 \u003Ccode\u003Evalid\u003C\/code\u003E. Zawsze gdy j\u0105 widzia\u0142em, musia\u0142em si\u0119 zastanowi\u0107, po co ona komu. Kiedy niby autoloader staje si\u0119 \u201cinvalid\u201d? A chodzi przecie\u017c o to, \u017ce autoloader mo\u017ce by\u0107 albo \u003Cem\u003Ejeszcze nie zarejestrowany\u003C\/em\u003E, albo \u003Cem\u003Eju\u017c zarejestrowany\u003C\/em\u003E. Czemu wi\u0119c nie zmieni\u0107 nazwy tej w\u0142a\u015bciwo\u015bci na \u003Ccode\u003Eregistered\u003C\/code\u003E? Teraz metoda \u003Ccode\u003Eregister()\u003C\/code\u003E staje si\u0119 bardzo czytelna: \u201cje\u015bli jeste\u015b zarejestrowany, to ju\u017c wi\u0119cej si\u0119 nie rejestruj\u201d.\u003C\/p\u003E\n\u003Cp\u003EBazowy namespace powinien ko\u0144czy\u0107 si\u0119 backslashem, aby unikn\u0105\u0107 takich sytuacji, gdy chcemy na przyk\u0142ad przechwyci\u0107 klasy \u201cJava\/...\u201d, a zgarniemy tak\u017ce i \u201cJavascript\/...\u201d. Dla zachowania jednorodno\u015bci, to samo powinno dotyczy\u0107 drugiego parametru konstruktora (\u015bcie\u017cki do folderu). Ale po co cz\u0142owiekowi, kt\u00f3ry chce u\u017cy\u0107 naszego autoloadera, kaza\u0107 si\u0119 zastanawia\u0107 nad tym, czy wymagamy slasha czy nie? Mo\u017ce lepiej po prostu sprawd\u017amy, czy slash jest na ko\u0144cu parametru, i doklejmy go, je\u015bli nie? Dodanie metody \u003Ccode\u003EaddEndingSlash\u003C\/code\u003E sprawi\u0142o, \u017ce nie tylko sama klasa jest prostsza, ale tak\u017ce i jej u\u017cycie na zewn\u0105trz.\u003C\/p\u003E\n\u003Cp\u003ETym oto sposobem w nowym kodzie jest zdecydowanie mniej zagnie\u017cd\u017ce\u0144, metody s\u0105 kr\u00f3tsze, a ka\u017cda zajmuje si\u0119 dok\u0142adnie jedn\u0105 rzecz\u0105 na jednym poziomie abstrakcji.\u003C\/p\u003E\n\u003Cp\u003EI jak? Kt\u00f3r\u0105 wersj\u0119 wolicie? Kt\u00f3ra nie marnuje czasu programisty pr\u00f3buj\u0105cego j\u0105 zrozumie\u0107?\u003C\/p\u003E\n\u003Cp\u003E\u201cCzysty kod\u201d warto przeczyta\u0107, warto do niego wraca\u0107 i \u2013 przede wszystkim \u2013 warto stosowa\u0107 si\u0119 do zawartych w nim rad.\u003C\/p\u003E\u003Csvg xmlns=\u0022http:\/\/www.w3.org\/2000\/svg\u0022 style=\u0022display: none;\u0022\u003E\u003C\/svg\u003E","tags":["czytelno\u015b\u0107","informatyka","kod","ksi\u0105\u017cka","php","programowanie"],"hasMore":true,"image":"https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_small.png","introLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022341.70731707317\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKsi\u0105\u017cka Roberta C. Martina \u003Ca href=\u0022http:\/\/helion.pl\/ksiazki\/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u201cCzysty kod\u201d\u003C\/a\u003E bije rekordy sprzeda\u017cy w\u015br\u00f3d pozycji dotycz\u0105cych szeroko poj\u0119tej informatyki. Wstyd wi\u0119c \u017cebym jej nie przeczyta\u0142, no nie? I zdecydowanie polecam j\u0105 ka\u017cdemu programi\u015bcie, kt\u00f3ry chcia\u0142by by\u0107 jak najlepszy w tym, co robi.\u003C\/p\u003E\n\u003Cp\u003EChcia\u0142bym tutaj pokaza\u0107 na konkretnym fragmencie kodu, jak wiele mo\u017ce zmieni\u0107 stosowanie si\u0119 do zasad przedstawionych przez Martina. Na przyk\u0142adzie autoloadera.\u003C\/p\u003E","contentLite":"\u003Cfigure\u003E\u003Ca href=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_big.png\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E\u003Cimg src=\u0022https:\/\/avris.it\/image\/czysty-kod-w-praktyce-autoloader-w-php_mini.png\u0022 alt=\u0022\u0022 width=\u0022240\u0022 height=\u0022341.70731707317\u0022 loading=\u0022lazy\u0022\u003E\u003C\/a\u003E\u003C\/figure\u003E\u003C\/p\u003E\n\u003Cp\u003EKsi\u0105\u017cka Roberta C. Martina \u003Ca href=\u0022http:\/\/helion.pl\/ksiazki\/czysty-kod-podrecznik-dobrego-programisty-robert-c-martin,czykov.htm\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E \u201cCzysty kod\u201d\u003C\/a\u003E bije rekordy sprzeda\u017cy w\u015br\u00f3d pozycji dotycz\u0105cych szeroko poj\u0119tej informatyki. Wstyd wi\u0119c \u017cebym jej nie przeczyta\u0142, no nie? I zdecydowanie polecam j\u0105 ka\u017cdemu programi\u015bcie, kt\u00f3ry chcia\u0142by by\u0107 jak najlepszy w tym, co robi.\u003C\/p\u003E\n\u003Cp\u003EChcia\u0142bym tutaj pokaza\u0107 na konkretnym fragmencie kodu, jak wiele mo\u017ce zmieni\u0107 stosowanie si\u0119 do zasad przedstawionych przez Martina. Na przyk\u0142adzie autoloadera.\u003C\/p\u003E\n\u003Cp\u003ETylko najpierw kr\u00f3tki wst\u0119p, co to w og\u00f3le jest \u201cautoloader\u201d. Ot\u00f3\u017c: przy ka\u017cdym \u017c\u0105daniu do serwera uruchamiana jest nowa instancja interpretera PHP. Aby nie musia\u0142 on \u0142adowa\u0107 wszystkich plik\u00f3w .php obecnych w projekcie (a potrafi\u0105 ich by\u0107 tysi\u0105ce), lecz tylko te, z kt\u00f3rych akurat w tym \u017c\u0105daniu skorzysta, u\u017cywany jest mechanizm auto\u0142adowania. Dzia\u0142a to tak, \u017ce kiedy interpreter PHP trafi na u\u017cycie klasy, kt\u00f3rej nie zna, odpyta o ni\u0105 po kolei autoloadery, kt\u00f3re ma zarejestrowane. Je\u015bli kt\u00f3ry\u015b z nich zwr\u00f3ci true, oznacza to, \u017ce znalaz\u0142 on plik, w kt\u00f3rym dana klasa powinna si\u0119 znajdowa\u0107, i do\u0142\u0105czy\u0142 go. W przeciwnym razie interpreter pyta kolejnego autoloadera w kolejce, a dopiero je\u015bli wszystkie zawiod\u0105 \u2013 wyrzuca fatal error \u201cClass not found\u201d.\u003C\/p\u003E\n\u003Cp\u003ENapisa\u0142em sobie kiedy\u015b ma\u0142\u0105 klas\u0119 autoloadera, a raczej poprzerabia\u0142em jak\u0105\u015b znalezion\u0105 na necie. Wygl\u0105da\u0142a tak:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?php\n\nclass Autoloader {\n\n    private $namespace;\n\n    private $path;\n\n    private $valid = false;\n\n    public function __construct($namespace, $path = \u0027\u0027) {\n        $this-\u0026gt;namespace = $namespace;\n        $this-\u0026gt;path = $path;\n        $this-\u0026gt;valid = true;\n    }\n\n    public function autoload($className) {\n        \/\/ is this autoloader responsible for that particular class?\n        if (substr($className,0,strlen($this-\u0026gt;namespace)) === $this-\u0026gt;namespace) {\n            $path = $this-\u0026gt;path . str_replace(\u0027\\\\\u0027,\u0027\/\u0027, ltrim( $className, \u0027\\\\\u0027)) . \u0027.php\u0027;\n            if (file_exists($path)) {\n                require_once($path);\n                return true;\n            } else {\n                \/\/ if not straightforward, maybe try \u0022common\u0022 class files\n                \/\/ eg. \u0022Exceptions\u0022 for \u0022NotFoundException\u0022;\n                $slashPos = strrpos($className,\u0027\\\\\u0027,-1) + 1;\n                $base = substr($className,0,$slashPos);\n                $classPure = substr($className,$slashPos);\n                preg_match_all(\u0027\/(?:^|[A-Z])[a-z]+\/\u0027,$classPure,$matches);\n                $path = $this-\u0026gt;path . str_replace(\u0027\\\\\u0027,\u0027\/\u0027, ltrim( $base . end($matches[0]) . \u0027s\u0027, \u0027\\\\\u0027)) . \u0027.php\u0027;\n                if (file_exists($path)) {\n                    require_once($path);\n                    return true;\n                } else {\n                    return false; \/\/ damn, maybe other autoloaders will find something\n                }\n            }\n        } else {\n            return false; \/\/ no, let the other autoloaders handle that\n        }\n    }\n\n    public function register() {\n        if ($this-\u0026gt;valid) {\n            spl_autoload_register(array($this, \u0027autoload\u0027));\n            $this-\u0026gt;valid = false; \/\/in order not to register it twice\n        }\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EPrzyk\u0142adowe u\u017cycie mojego autoloadera wygl\u0105da nast\u0119puj\u0105co:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?php\n$autoloader = new Autoloader(\u0027Micrus\\\\\u0027, __DIR__ . \u0027\/vendor\/\u0027);\n$autoloader-\u0026gt;register();\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003ETworzymy nowy autoloader maj\u0105cy obs\u0142ugiwa\u0107 wszystkie klasy w przestrzeni nazw \u201cMicrus\u201d i szukaj\u0105cy ich w katalogu \u201cvendor\u201d, gdzie klasy s\u0105 umieszczone w podfolderach zgodnie ze swoj\u0105 przestrzeni\u0105 nazw. Oznacza to, \u017ce je\u015bli gdzie\u015b w kodzie b\u0119dziemy chcieli stworzy\u0107 nowy obiekt klasy \u003Ccode\u003EMicrus\\Foo\\Bar\\MyClass\u003C\/code\u003E, to powinna si\u0119 ona znajdowa\u0107 w pliku \u003Ccode\u003E\/vendor\/Micrus\/Foo\/Bar\/MyClass.php\u003C\/code\u003E.\u003C\/p\u003E\n\u003Cp\u003EDo tego dochodzi jeszcze pewien ma\u0142y feature (niezgodny z \u003Ca href=\u0022http:\/\/www.php-fig.org\/psr\/psr-4\/\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PSR-4\u003C\/a\u003E). Ot\u00f3\u017c je\u015bli chcemy zgrupowa\u0107 kilka podobnych klas w jednym pliku, mo\u017cemy zrobi\u0107 to w bardzo prosty spos\u00f3b. Mamy na przyk\u0142ad klasy wyj\u0105tk\u00f3w, kt\u00f3re potrafi\u0105 by\u0107 naprawd\u0119 malutkie i czasem niewygodnie jest rozbija\u0107 je na osobne pliki. Nazywamy je wszystkie u\u017cywaj\u0105c \u003Ca href=\u0022http:\/\/pl.wikipedia.org\/wiki\/PascalCase\u0022 target=\u0022_blank\u0022 rel=\u0022noopener\u0022\u003E PascalCase\u003C\/a\u003E z \u201cException\u201d jako ostatnim s\u0142owem i umieszczamy w pliku \u003Ccode\u003EExceptions.php\u003C\/code\u003E (z dodatkowym -s). M\u00f3j autoloader obs\u0142u\u017cy taki przypadek.\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E\u0026lt;?php\nnamespace Micrus;\n\nclass ConfigFileException extends \\Exception { }\nclass NotFoundException extends \\Exception { protected $code = 404; }\nclass CacheException extends \\Exception { }\nclass RouteNotFoundException extends \\Exception { protected $code = 404; }\nclass InvalidArgumentException extends \\Exception { }\nclass UnauthorisedException extends \\Exception { protected $code = 403; }\nclass ArgvException extends \\Exception { }\nclass DatabaseException extends \\Exception { }\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EKod autoloadera nie wygl\u0105da \u017ale (a przynajmniej widzia\u0142em gorsze). Ale pierwsze spojrzenie na metod\u0119 \u201cautoload\u201d potrafi przerazi\u0107. Jest okropnie nieczytelna, mimo \u017ce komentarze obja\u015bniaj\u0105 jej dzia\u0142anie. Potrzeba troch\u0119 wysi\u0142ku, \u017ceby dowiedzie\u0107 si\u0119, co konkretnie robi.\u003C\/p\u003E\n\u003Cp\u003EWszyscy ucz\u0105, zeby pisa\u0107 komentarze do kodu. Du\u017co komentarzy. Nawet je\u015bli wydaje ci si\u0119 to bezsensowne, bo przecie\u017c rozumiesz, co napisa\u0142e\u015b, to musisz bra\u0107 pod uwag\u0119, \u017ce je\u015bli kod trafi w r\u0119ce kogo innego, albo i ty sam zajrzysz do niego rok czy dwa p\u00f3\u017aniej, to rozszyfrowanie go mo\u017ce ju\u017c nie by\u0107 takie proste.\u003C\/p\u003E\n\u003Cp\u003EMartin natomiast uczy czego innego. Dobry kod wymaga tylko znikomej liczby komentarzy. Je\u015bli ich potrzebujesz, by zrozumie\u0107, co si\u0119 dzieje, znaczy \u017ce kod jest nieczytelny. No i komentarze s\u0105 w pewnym sensie \u003Cem\u003Eniebezpieczne\u003C\/em\u003E: zapominamy je pisa\u0107, zapominamy je aktualizowa\u0107, boimy si\u0119 je usuwa\u0107, szybko trac\u0105 na wa\u017cno\u015bci...\u003C\/p\u003E\n\u003Cp\u003ESp\u00f3jrzcie na kod autoloadera po serii poprawek:\u003C\/p\u003E\n\u003Cpre\u003E\u003Ccode class=\u0022language-php\u0022\u003E\u0026lt;?php\n\nclass Autoloader\n{\n    private $namespace;\n\n    private $path;\n\n    private $registered = false;\n\n    public function __construct($namespace, $path = \u0027.\u0027)\n    {\n        $this-\u0026gt;namespace = $this-\u0026gt;addEndingSlash($namespace, \u0027\\\\\u0027);\n        $this-\u0026gt;path = $this-\u0026gt;addEndingSlash($path, \u0027\/\u0027);\n    }\n\n    private function addEndingSlash($word, $slash = \u0027\/\u0027)\n    {\n        $lastCharacter = substr($word, -1);\n        return $lastCharacter == $slash ? $word : $word . $slash;\n    }\n\n    public function autoload($className)\n    {\n        if ($this-\u0026gt;isNotResponsibleForClass($className)) {\n            return false;\n        }\n\n        $path = $this-\u0026gt;classNameToFilePath($className);\n        if (file_exists($path)) {\n            require_once($path);\n            return true;\n        }\n\n        $groupName = $this-\u0026gt;classNameToGroupName($className);\n        $path = $this-\u0026gt;classNameToFilePath($groupName);\n        if (file_exists($path)) {\n            require_once($path);\n            return true;\n        }\n\n        return false;\n    }\n\n    private function isNotResponsibleForClass($className)\n    {\n        return substr($className, 0, strlen($this-\u0026gt;namespace)) !== $this-\u0026gt;namespace;\n    }\n\n    private function classNameToFilePath($className)\n    {\n        return $this-\u0026gt;path . str_replace(\u0027\\\\\u0027,\u0027\/\u0027, ltrim( $className, \u0027\\\\\u0027)) . \u0027.php\u0027;\n    }\n\n    private function classNameToGroupName($className)\n    {\n        $slashPos = strrpos($className,\u0027\\\\\u0027,-1) + 1;\n        $base = substr($className,0,$slashPos);\n        $classPure = substr($className,$slashPos);\n        preg_match_all(\u0027\/(?:^|[A-Z])[a-z]+\/\u0027,$classPure,$matches);\n\n        return $base . end($matches[0]) . \u0027s\u0027;\n    }\n\n    public function register()\n    {\n        if ($this-\u0026gt;registered) { return false; }\n        spl_autoload_register(array($this, \u0027autoload\u0027));\n        $this-\u0026gt;registered = true;\n\n        return true;\n    }\n}\u003C\/code\u003E\u003C\/pre\u003E\n\u003Cp\u003EWystarczy zerkn\u0105\u0107 na funkcj\u0119 autoload, \u017ceby wiedzie\u0107, co robi. Ba, nawet nie trzeba zna\u0107 \u017cadnego j\u0119zyka programowania! To\u017c to niemal czysty angielski: \u201cif this is not responsible for class \u2018class name\u2019, return false\u201d. Nie mamy poj\u0119cia \u003Cem\u003Ejak\u003C\/em\u003E funkcja to robi, ale wida\u0107 jak na d\u0142oni \u003Cem\u003Eco\u003C\/em\u003E takiego wykonuje.\u003C\/p\u003E\n\u003Cp\u003E\u003Cem\u003E\u201cJak\u201d\u003C\/em\u003E natomiast znajduje si\u0119 w osobnych, prywatnych metodach. Rozdzielili\u015bmy zatem od siebie r\u00f3\u017cne \u003Cem\u003Ewarstwy abstrakcji\u003C\/em\u003E, kt\u00f3re wcze\u015bniej by\u0142y zlane w jedn\u0105, brzydk\u0105 funkcj\u0119. Bo je\u015bli kto\u015b zajrzy do naszego kodu, to najprawdopodobniej nie b\u0119dzie potrzebowa\u0142 znajomo\u015bci wszystkiego, co tam naskrobali\u015bmy, lecz przyjdzie z jakim\u015b jednym konkretnym zadaniem: \u201cogarn\u0105\u0107 jak mniej wi\u0119cej dzia\u0142a ten autoloader\u201d, \u201czmieni\u0107 format nazwy \u2018zbiorowego pliku\u2019\u201d, \u201czmieni\u0107 kolejno\u015b\u0107 sprawdzania potencjalnych plik\u00f3w\u201d itp. I dlatego rozdzielenie warstw abstrakcji tak bardzo upro\u015bci mu prac\u0119.\u003C\/p\u003E\n\u003Cp\u003ENa pierwszy rzut oka wydawa\u0142oby si\u0119 sensowniejsze stworzenie metody isResponsibleForClass zamiast jej negacji \u2013 isNotResponsibleForClass. Kto normalny pyta\u0142by klas\u0119, czy \u003Cem\u003Enie jest\u003C\/em\u003E za co\u015b odpowiedzialna? Odpowied\u017a \u201ctak, nie jestem\u201d tylko niepotrzebnie by wszystko zagmatwa\u0142a, prawda? No w\u0142a\u015bnie niekoniecznie. U\u017cycie tej metody jest tylko jedno i sprowadza si\u0119 do \u201cje\u015bli nie jeste\u015b za to odpowiedzialna, to daj sobie spok\u00f3j\u201d. Zapisanie tego warunku jako \u003Ccode\u003Eif (!$this-\u0026gt;isResponsibleForClass($className))\u003C\/code\u003E zmniejsza czytelno\u015b\u0107, poniewa\u017c tego wykrzyknika prawie nie wida\u0107. Zawsze zapominamy o wykrzyknikach...\u003C\/p\u003E\n\u003Cp\u003EZanegowanie dopad\u0142o te\u017c zmienn\u0105 \u003Ccode\u003Evalid\u003C\/code\u003E. Zawsze gdy j\u0105 widzia\u0142em, musia\u0142em si\u0119 zastanowi\u0107, po co ona komu. Kiedy niby autoloader staje si\u0119 \u201cinvalid\u201d? A chodzi przecie\u017c o to, \u017ce autoloader mo\u017ce by\u0107 albo \u003Cem\u003Ejeszcze nie zarejestrowany\u003C\/em\u003E, albo \u003Cem\u003Eju\u017c zarejestrowany\u003C\/em\u003E. Czemu wi\u0119c nie zmieni\u0107 nazwy tej w\u0142a\u015bciwo\u015bci na \u003Ccode\u003Eregistered\u003C\/code\u003E? Teraz metoda \u003Ccode\u003Eregister()\u003C\/code\u003E staje si\u0119 bardzo czytelna: \u201cje\u015bli jeste\u015b zarejestrowany, to ju\u017c wi\u0119cej si\u0119 nie rejestruj\u201d.\u003C\/p\u003E\n\u003Cp\u003EBazowy namespace powinien ko\u0144czy\u0107 si\u0119 backslashem, aby unikn\u0105\u0107 takich sytuacji, gdy chcemy na przyk\u0142ad przechwyci\u0107 klasy \u201cJava\/...\u201d, a zgarniemy tak\u017ce i \u201cJavascript\/...\u201d. Dla zachowania jednorodno\u015bci, to samo powinno dotyczy\u0107 drugiego parametru konstruktora (\u015bcie\u017cki do folderu). Ale po co cz\u0142owiekowi, kt\u00f3ry chce u\u017cy\u0107 naszego autoloadera, kaza\u0107 si\u0119 zastanawia\u0107 nad tym, czy wymagamy slasha czy nie? Mo\u017ce lepiej po prostu sprawd\u017amy, czy slash jest na ko\u0144cu parametru, i doklejmy go, je\u015bli nie? Dodanie metody \u003Ccode\u003EaddEndingSlash\u003C\/code\u003E sprawi\u0142o, \u017ce nie tylko sama klasa jest prostsza, ale tak\u017ce i jej u\u017cycie na zewn\u0105trz.\u003C\/p\u003E\n\u003Cp\u003ETym oto sposobem w nowym kodzie jest zdecydowanie mniej zagnie\u017cd\u017ce\u0144, metody s\u0105 kr\u00f3tsze, a ka\u017cda zajmuje si\u0119 dok\u0142adnie jedn\u0105 rzecz\u0105 na jednym poziomie abstrakcji.\u003C\/p\u003E\n\u003Cp\u003EI jak? Kt\u00f3r\u0105 wersj\u0119 wolicie? Kt\u00f3ra nie marnuje czasu programisty pr\u00f3buj\u0105cego j\u0105 zrozumie\u0107?\u003C\/p\u003E\n\u003Cp\u003E\u201cCzysty kod\u201d warto przeczyta\u0107, warto do niego wraca\u0107 i \u2013 przede wszystkim \u2013 warto stosowa\u0107 si\u0119 do zawartych w nim rad.\u003C\/p\u003E","words":1438,"readTime":6,"lang":"pl"}}}}}