5 Bibliotecas Essenciais para Desenvolver React Apps
O conjunto de ferramentas, boilerplates e bibliotecas disponĂveis formam um ecossistema incrĂvel em torno do React.
No meio de tudo, existem ferramentas que sĂŁo comuns â e essenciais â a diversas aplicaçÔes, independente de suas arquiteturas. Cito cinco delas.
Muitas vezes, no React, um estado representarĂĄ um comportamento visual do componente (âselecionadoâ, âpressionadoâ, âfocadoâ), normalmente associado a uma classe CSS.
Um botĂŁo e seus estados disabled e hovered, por exemplo, ficariam assim:
A development branch of VS Code colorization, which is delivered as an extension. Finally got JSX to work properly, but syntax highlighting was still missing something.
So, no success.
Improving your VS Code workflow
After much trial and error, I came up with a better JS workflow in VS Code.
Fortunately, VS Code is an open source project and can be improved by developers like us! Letâs not leave it like this. Give useful feedback and help!
Math.random() is a JavaScript function that outputs a random number in the range [0, 1) (from 0 up to 1, but doesnât include 1). Itâs the main source of randomness in JavaScript.
Although the output looks random, itâs actually not.
Behind the Scenes
Math.random() uses a pseudo-random number generator (PRNG). Those algorithms work completely determined by a initial value called âseedâ.
Given a seed, the sequence of random numbers is deterministic.
Every PRNG requires a seed, which generally is the current system time in milliseconds. Yeah, simple as that.
Speaking of JavaScript language, the PRNG algorithm to deal with the seed is left up to implementors1. The algorithm powering V8âs Math.random() was very poor quality until last year (2015), and implementations between engines were pretty inconsistent.
But the scenario has changed. Currently, JavaScript Engines such as SpiderMonkey, V8, Webkit and Chakra all implements Xorshift128+ algorithm2, faster than the previous one.
Secure Randomness
Although randomness was improved in most JavaScript engines, it isnât trustworthy as seen that standard PRNGs are highly predictable after a certain period. Thatâs where Web Crypto API shines!
Web Cryptography API introduces window.crypto.getRandomValues, a cryptographically secure pseudo-random number generator (CSPNG), whose output is impossible or highly improbable to distinguish from a truly random one.
Example
// Array containing two 32-bit integers
+const arr = new Int32Array(2);
+
+// Override array integers with random values
+const random = crypto.getRandomValues(arr);
+
+for (let i = 0; i < random.length; i++) {
+console.log(random[i]);
+}
+
Of course it comes at a performance cost, so make sure you really need secure random numbers in your program.
Conclusion
If you need apparent randomnessâless and speed, youâd probably better off using Math.random(). If you need high-quality randomness, such as in cryptography applications, hashing or statistics, go for a CSPNG such as window.crypto.getRandomValues instead.
Muito embora todos os seres humanos do Planeta Terra tenham odiado sua sintaxe, as variĂĄveis finalmente chegaram ao CSS â e elas sĂŁo mais poderosas do que vocĂȘ imagina!
Motivação
O desenvolvimento de grandes aplicaçÔes web implica inevitavelmente em grandes folhas de estilo, que devem ser organizadas de forma que facilite a manutenção. Muitos valores definidos para propriedades são repetidos, quando poderiam ser reutilizados e padronizados, de forma compartilhada, pela folha de estilo.
Cascata, especificidade, herança⊠Esses conceitos sĂŁo muito importantes para entender o poder das variĂĄveis do CSS â e do CSS no geral, eu diria.
Aqui, uma das informaçÔes mais importantes deste artigo: As Custom Properties seguem regras de cascata tal como qualquer outra propriedade do CSS.
Exceto elementos div e seus filhos, que seriam verdes.
Exceto o elemento com id wow e seus filhos, que seriam ciano.
As Ășltimas versĂ”es do Firefox e Chrome jĂĄ implementaram as variĂĄveis nativas do CSS. Se estiver utilizando algum desses navegadores, o exemplo abaixo ilustrarĂĄ o funcionamento do CSS acima.
As Custom Properties abriram novas possibilidades para o uso de variåveis em folhas de estilo. Depois de diversas especificaçÔes e sintaxes (nem sempre foi --, acredite!), elas estão finalmente em fase de implementação nos navegadores.
Estuda Motion Design a fim de desenvolver nĂŁo sĂł sites, mas experiĂȘncias fantĂĄsticas? Estuda UX Design e prĂĄticas de Acessibilidade a fim de desenvolver produtos que engajam o mĂĄximo de pessoas possĂvel? Estuda padrĂ”es de arquitetura de software a fim de desenvolver aplicaçÔes web complexas e escalĂĄveis no client-side?
No fim, suas preferĂȘncias moldarĂŁo vocĂȘ como profissional. Elas farĂŁo com que vocĂȘ seja incluĂdo(a) ou excluĂdo(a) de vĂĄrias oportunidades, o que, por consequĂȘncia, moldarĂĄ sua carreira.
Estude o que gosta, reconheça suas preferĂȘncias, confie nas suas habilidades, e, entĂŁo, procure vagas sem entrar em desespero.
Perfis de Desenvolvedores Front-end
No fĂłrum do Front-end Brasil, foi proposta a divisĂŁo de separar profissionais de front-end que desenvolvem a camada de apresentação dos que arquitetam aplicaçÔes que interagem com back-end. Concordo com a divisĂŁo. Tenho uma visĂŁo bem definida, com base nas exigĂȘncias atuais do mercado internacional.
Dificilmente um rĂłtulo resumirĂĄ todo o seu conhecimento.
Eu nĂŁo me apego a isso, por exemplo. Mesmo exercendo a função de Front-end Engineer atualmente, continuo me denominando âFront-end Developerâ.
A Vaga Ideal Para Suas Habilidades
à utópico esperar que todos desenvolvedores front-end sejam bons UX Designers, Motion Designers, JavaScript Developers⊠Isso não existe. As empresas procuram diferentes perfis de desenvolvedores front-end. E elas nem sempre sabem disso.
Independente de como vocĂȘ se posiciona e rotula, dos projetos que trabalha e do caminho que quer seguir, o front-end nĂŁo deixarĂĄ de orbitar ao redor da trinca HTML, CSS e JavaScript.
Enquanto vocĂȘ possuir interesse nessas trĂȘs linguagens, os seus outros interesses apenas moldarĂŁo o seu caminho profissional.
Favicon is a simplified visual element associated with a particular website, page or event, which you once found only in your browserâs address bar or bookmarks. Nowadays, the scenario is different: they are everywhere.
Introduction
Favicons provide a important visual indicator to people, and help them to easily associate your content (which can be a website, a particular page or even events like a new message) when browsing.
Formerly, they, also called shortcut icons or bookmark icons, were just tiny pieces of art designed to help users to browse through their tabs or bookmarks. Today, shortcut icons can also provide an app-like link on operational systems (Windows 8, Android, OS X and so on), and should therefore be considered for achieving a pleasant cross-platform experience.
This is a guide for using favicons today, the right way. At the end of this article, Iâm sure youâll be excited about SVG favicons.
Usage
Favicons in different dimensions are needed, so devices and browsers can pick the picture that fits best based on sizes attribute (little exception for Mozilla Firefox, which always gets the last favicon declared and scale it if necessary).
The images are not requested when not used. As said, browsers will get only what fits them best, therefore itâs important to provide the favicon in the required dimensions to avoid ugly scaled images.
General
<!-- I'm lazy -->
+<link rel="icon" href="favicon.png" />
+
+<!-- Browser tabs -->
+<link rel="icon" href="favicon-16x16.png" sizes="16x16" />
+
+<!-- Safari on OS X, IE10 Metro -->
+<link rel="icon" href="favicon-32x32.png" sizes="32x32" />
+
+<!-- Google TV -->
+<link rel="icon" href="favicon-96x96.png" sizes="96x96" />
+
+<!-- Chrome on Android -->
+<link rel="icon" href="favicon-192x192.png" sizes="192x192" />
+
No need for type="image/png" when using HTML5.
Youâll need to provide a manifest in order to Chrome on Androidâs icon to work properly. See manifest.json example.
<link rel="manifest" href="manifest.json" />
+
Lacking of PNG support on IE: a workaround
Internet Explorer until version 11 and Safari donât support PNG favicons. However, you can provide a fallback for IE up to 9:
Notice the shortcut, which is a non-standard. Also, providing this fallback within a conditional comment is necessary; otherwise Chrome will use the ICO favicon, even if it supports PNG ones.
I donât recommend it, though, because IE 10 doesnât support conditional comments (so it wonât get any favicon, as seen that it doesnât support PNG too), and also because it encourages the use of the non-standard and confusing shortcut.
Luckily, you can workaround everything just placing a favicon.ico in the root directory (the browser will look for it automagically). Then link only the PNG favicon and donât worry.
Web Clip bookmarks
iOS users can add websites to their home screen â shortcuts called âWeb Clip bookmarksâ. The default icon is a thumbnail screenshot of the page, but developers can specify one instead.
You will need to provide a lot of dimensions in order to support both new devices and older (iOS6 and prior), however.
Thereâs a no-HTML way and a HTML way to provide those icons. Itâs up to you.
No-HTML: Touch Icon file
Add a apple-touch-icon-*.png file, where * is the size to the root directory, instead. iOS Safari will look for the appropriate icon size, and if it doesnât find any that fits best, itâll use apple-touch-icon.png.
Link tags
You can reuse the image of another favicon specifying a href (not possible while using the solution above).
Using apple-touch-icon-precomposed instead of apple-touch-icon, which prevents iOS icons defaults like rounded corners and reflective shine, isnât necessary, as seen that there isnât shiny effects on iOS 7 and up anymore.
Windows Tiles
Tiles are icons that appear on the Start screen, linked as apps. By default, the image on the tile is the websiteâs favicon or a default IE11 logo.
To cover a wide range of devices, use an image 1.8 times the standard tile size so the image can be scaled up or down as needed.
Thereâs a no-HTML way and a HTML way to provide those icons. Itâs up to you, again.
No-HTML: Browser config file
Provide a browserconfig.xml file and save it at the root of your server. Internet Explorer 11 will automatically read the file when the user pins the website. See browserconfig.xml example.
Metadata tags
msapplication-TileColor is the background color of the tile, and msapplication-TileImage is the icon, which can be tiny (70 Ă 70px), square (150 Ă 150px), wide (310 Ă 150px) or large (310 Ă 310px).
Iâm sure you are now excited about SVG support for favicons. Providing a lot of different images is quite boring.
I encourage you to support favicons everywhere (or at least retina-ready ones), but unfortunately thereâs no human-friendly way to do it nowadays. Use favicons package on npm or, if you are not comfortable with the command line, refer to RealFaviconGenerator.
Ask me for a screenshot of my desktop and all you get is a wallpaper â if Iâm using any. Everything else is hidden, unless actually requested by me.
Thatâs the way I work on macOS. The minimal way.My macOS desktop. This + Spotlight = life. đ
In my workspace, there are no desktop items, app icons, time clock, battery percentage, transition delays, distracting animations, dashboards or context menus.
Too much information makes it easy for me to get stimulated and then distracted. So I like it minimal.
Recipe for the minimal đ
Get rid of everything you can. Hide. Disable. Assume everything is useless, not useful. (I actually use this approach for life.)
Youâll get frustrated sometimes, because there are simple things you want so bad to get rid of but then found out itâs impossible unless you hack things. SRLSY GOTTA LOVE APPLE đđđ
Well, letâs begin! Follow the steps below and type the commands in a terminal. If youâre not familiar with a terminal, Iâm pretty sure itâs possible to find those settings in âSystem Preferencesâ as well.
(âŠBut I highly recommend you to open a terminal and start typing around because SRSLY USING A TERMINAL IS LIKE KNOWLEDGE AND POWER 4 UR ENTIRE LIFE!!!!!!!!)
Hide your desktop
Itâs easier to live without than to live with it. Disable it and it wonât be something you have to clean up anymore!
Other cool things you can do too to keep your dock clean are:
# Minimize windows into their application's icon
+defaults write com.apple.dock minimize-to-application -bool true
+
+# Wipe all (default) app icons from the Dock
+defaults write com.apple.dock persistent-apps -array
+
Because I initialise apps from Spotlight, I really donât mind not having any app in my dock. Sometimes I ask myself why do I have a dock at all. đ€
Usually, such thing would mean regular summer days. However, it wasnât summer or even a regular day â this was something else.
February 25th was winter. In that cold afternoon, I ended up into a place Iâll never forget: photographs from my phoneâs gallery.
My steps were slow.
Red bricks erected the walls of houses built on top of an equally red-bricked avenue.
The windows of the houses were made of a wood strategically white-colored to match the brickâs white grouts. With such detail, it was pretty easy to forgive the toughness those bricks carried.
Houses ended themselves in grey roofing shingles. The roofs were all hipped. Houses with hip roofs, gotta love them!, I thought to myself. (Imagine the âVâ letter upside down on top of a square â thatâs a house with a hip roof.)
Showing a winter that was already leaving, dark trees with dry twigs were in contrast against a white sky â the whitest Iâd ever seen in my life. Damn! The whole picture looked like a painting, while the white sky worked as the canvas board on which all that was drawn.
I remember walking and trying to get everything I could, until a freezing wind blew abruptly into my face. It was February, though. From where I come, February meant summer, not freezing winds. Why was February that cold?
In an attempt to clear things up, I told myself what I believed that was true: Youâre just looking at photographs from your phoneâs gallery. Thereâs no need to get this excited! Ok. So I was home and looking at the âWallpapersâ album I had on my phone.
A moment later, I found myself facing a large and wonderful canal, in which someone was solitary paddling a boat to somewhere. What a view.
Then, self-awareness hit me again: Wait. Isnât my smartphone in my pocket? How could I be possibly looking at photographs on it?
I immediately started touching my entire body in a desperate hunt for my phone. And there it was. In my fucking coat. It wasnât really possible for me to see photographs on my phone â that shit was in my pocket all the time.
Besides, why would I be wearing a coat on summer? And, if I was already wearing a coat, how could I be still cold? How inappropriate were my clothes for that weather? Only a person who sensed that winter solely with the eyes would underestimate its coldness like that!
The boat was really leaving through the canal. The view wasnât photographs. What was all that, then?
I got my phone from my pocket, turned off airplane mode, and opened the Maps app. Come on, where am I?
âNoorder Amstelkanaalâ, I read. Wow.
All of a sudden, February 25th was a cold winter in Amsterdam. My very first one.Someone solitary paddling a boat to somewhere in Noorder Amstelkanaal, an Amsterdam's canal.
As a High School student, I remember always finding Chemistry something between the boring and intriguing. Still, it isnât hard to find myself wondering about the science concepts Iâve learned at that time.
Lately, Iâve been particularly thinking about catalysis.
In Chemistry, catalysis is the acceleration of a reaction due to the participation of a substance â the âcatalystâ.
The way a catalyst induces a reaction to happen faster is intriguing. Curiously, it neither gives the reaction more energy nor change its environmental conditions. Catalysts have an even better strategy: they lower the amount of energy required for the reaction to take place.Uncatalyzed reaction (solid) vs. catalyzed reaction (dashed). The highest point is the energy required for the reaction to happen.
In a catalysed reaction, then, the same product is obtained for less energy. Bringing this concept to our lives is quite thought-provoking.
Sometimes it isnât possible for us to achieve something because it demands more time or energy than what we currently have. To deal with this, we then try looking for them in our lives â which mostly means depriving yourself of things.
However, matter of fact is that optimising isnât always about getting rid of things in your life. If we think of catalysis, we can manage it differently.
What if the problem werenât the lack of energy or time, but that weâre in need of too much of them in order to get things done? Having a catalyst would totally figure it out. Without something that pushes us forward, weâll always require more energy for the product we want to get.
At this point, you may think your catalyst is your motivation. Motivation is out of our control though â which makes it a goal, not a source. Itâs also too ephemeral, and a catalyst mustnât ever be consumed by an unique reaction, just like in Chemistry. We canât count on being motivated!
So it goes more like what habitual and practical things in life would give you productivity for less. Is it everyday meditation? A partner by your side? Self-confidence? Inspiring weekends without thinking of work at all? Eating healthy? Going out for a walk every day?
You have to mind what pushes your forward. Catalysts themselves cannot make a reaction happen that wouldnât happen on its own, but they sure make it occur under less extreme conditions. Itâs an improvement when youâre already motivated.
Choose life. Choose a job. Choose a career. Choose relocation. Choose giving life a fresh1 beginning. Choose an one-way flight ticket. Choose fitting your entire life in a 23 kg suitcase. Choose getting rid of all your crap. Choose a higher Human Development Index. Choose being thousands of kilometers far away. Choose devastating your loved ones. Choose different bureaucracies you still donât understand. Choose calling another place home. Choose not fitting in (you never did anyway!). Choose saying goodbye to places, food and friends, then choose new places, food, and friends. Choose memories. Choose developing new tastes. Choose being forced to develop social skills. Choose ignorance. Choose mundane and boring activities as exciting adventures. Choose not speaking your mother language. Choose limited self-expression. Choose missing the food from your country, and especially your mumâs. Choose letting part of your heart be elsewhere. Choose adapting 24/7. Choose wondering what the fuck you are doing. And choose getting the answer as soon as you go outside. Choose not understanding jokes from natives. Choose recognising you can do anything, anywhere. Choose not knowing if you should. Choose the bittersweet feeling of moving abroad. Choose to be afraid. Choose your future. Choose life.
But why wouldnât I want to do a thing like that?
I chose to choose life. And the reasons? There are no reasons. Who needs reasons when youâve got Berlin?2
1
See HelloFresh, which helped me relocating to Berlin.
2
The entire essay is inspired by Mark Rentonâs âChoose Lifeâ speech from Trainspotting, a movie that makes me think a lot about life choices.
O Centro de ConvençÔes, ao menos, foi fĂĄcil de achar, e o check-in ocorreu como esperado: pontual. As meninas que forneceram minha credencial estavam de Ăłtimo humor â e olha que era um dos primeiros horĂĄrios da manhĂŁ de sexta! Ano passado, o meu check-in foi feito pelo Jaydson, o que fez eu me perguntar onde estaria ele, se nĂŁo credenciando os participantes do evento.
âŠE, na verdade, ele tinha se tornado um Power Ranger junto com o Felipe. E Power Rangers nĂŁo fazem check-in. Descobri isso da pior maneira.
Uma abertura idiota
Dois desenvolvedores, os organizadores desse evento que trouxe mais de mil pessoas para o mesmo lugar, brincando de âlutinhaâ na frente de todo mundo, vestidos de Power Rangers sĂł porque o JavaScript fez 20 anos. Essa foi a abertura da BrazilJS, e eu nĂŁo mudaria nada.
Com uma camiseta do Brasil, Christian chegou com um dos assuntos mais importantes na atualidade, e que estå dando muito o que falar: pushing the web forward. Palavras de protagonismo, reiteração do nosso papel, motivação para acreditar na web e no nosso trabalho, e, o mais importante: como isso deve ser feito. Falou, claro, sobre o ECMAScript 6, sobre o Babel, e fez uma anålise de como resolvemos os problemas atualmente.
We all know the DOM is slow, terrible and to blame for all our problems. Did we allot it to say that way and still be a problem as we abstracted its issues away?
Os argumentos foram reĂșnidos, as situaçÔes em que podemos nos tornar web makers foram apresentadas, e tudo em prol de provar o nosso protagonismo.
You are a creator of the next web!
Sem dĂșvidas, uma das melhores palestras que jĂĄ assisti na minha vida. Ă difĂcil relatar uma interpretação detalhada sobre a mensagem do Christian, mas, aos que jĂĄ se sentiram no dever de fazer a web um lugar melhor alguma vez e nunca deixaram de acreditar nessa mĂdia, acho que essas minhas palavras foram mais que o suficiente para compreender o pensamento dele. Simples e sensacional.
Douglas falou sobre compiladores, e engajou os desenvolvedores a entender how things work under the hood, explorando conceitos como AST (Abstract Syntax Tree), um assunto que estå finalmente chamando a atenção em JavaScript, tanto que não foi a primeira vez que foi abordado na BrazilJS.
Acredito que o questionamento que o palestrante buscou provocar no pĂșblico nĂŁo teve ĂȘxito. Os 30 minutos, infelizmente, nĂŁo foram bem aproveitados e nĂŁo atenderam Ă s perguntas que o Douglas tentou provocar e responder. Ficou a sensação de uma mensagem subentendida, no entanto:
Itâs really important for us to take a look at the things we donât necessarily like.
JavaScript at Spotify
Felipe Ribeiro juntou os desafios encontrados durante a transição do Spotify (nativo com C++ para hĂbrido), e o resultado foi uma palestra bastante completa sobre arquitetura e engenharia de software. Diversificou bastante a programação da conferĂȘncia, e mostrou que devemos analisar a necessidade de re-escrita de cĂłdigo em uma aplicação complexa sob uma Ăłtica criteriosa que equilibra utilidade, valor e esforço necessĂĄrio.
Uma palestra que dividiu bastante o pĂșblico. Na verdade, acredito que o Raphael Amorim deu o melhor dele para fazer o discurso significar exatamente o que ele queria que significasse. O Raphael sabe se comunicar muito bem, e paciĂȘncia foi o Ășnico requisito para captar a mensagem.
A Ju Gonçalves explicou o uso do reduce() na pråtica. (Na pråtica mesmo, para sair da BrazilJS usando, caso nunca tenha usado.)
O tema escolhido complementou muito bem a palestra de programação funcional do Jacob Page, anterior a dela. O formato ficou perfeito para 30 minutos (a propĂłsito, a ideia de abordar apenas o reduce() foi muito legal!), e deu para aprofundar bastante em algo que deve fazer parte do dia a dia. SĂł fiquei com a sensação de que 5 minutos a mais ajudariam ela a guiar os exemplos com mais calma. O tempo estava bastante inflexĂvel nesse quesito.
Enfim, a Ju sabe o que faz. NĂŁo a conhecia pessoalmente ainda, mas conheço o trabalho e o entusiasmo dela e apostaria nela de longe, tal como a organização da conferĂȘncia, sem dĂșvidas, fez.
ECMAScript 6: O que HĂĄ de Novo, O que Mudou, O que tem de Bacana ou de Estranho!
Como o Laurie disse, o trabalho feito foi sensacional. Mereceu todos os aplausos recebidos, tanto pela apresentação quanto pelos projetos paralelos que organizou.
Terminou com a frase que foi a grande mensagem da BrazilJS 2015: always bet on JS.
O fim
O evento acabou com um show de rock e cerveja artesanal. NĂŁo sou uma pessoa agitada, nem gosto de beber cerveja, nem queria me arriscar a chegar tarde em casa (voltaria de ĂŽnibus), entĂŁo me limitei a finalizar meu dia indo falar com o Daniel Filho, que estava com outras duas pessoas, o Leonardo Balter e o Igor-que-foi-aprender-InglĂȘs.
Muitas pessoas levam notebooks e o Espaço BrazilJS foi uma Ăłtima ideia para lidar com isso. Conciliou o Ăștil (reconferir palestras, programar durante coffee break) ao agradĂĄvel (nĂŁo ficar no computador durante palestras). Ă muito legal ter um lugar para ficar com o notebook, embora eu nĂŁo recomende levar caso vĂĄ embora de ĂŽnibus, como vivenciei.
Notas finais
Foi difĂcil comer e beber no primeiro dia. Percebi que, em vez de as pessoas organizarem-se em filas, muitas ficavam no entorno da mesa do coffee break, e isso dificultou muito o fluxo. No segundo dia, no entanto, foi bem mais organizado.
Os organizadores nĂŁo param. EstĂŁo sempre envolvidos com o evento, resolvendo pendĂȘncias e atendendo a feedbacks. Houve dedicação integral por parte do Daniel, Felipe e Jaydson em fazer uma conferĂȘncia confortĂĄvel para todos. O segundo dia nĂŁo foi mais tranquilo porque simplesmente foi e a a conferĂȘncia deste ano nĂŁo foi mais diversa porque simplesmente foi. Agradeço a eles por isso.
Basic knowledge of computer languages (mainly JavaScript) is assumed.
Some time ago, a friend of mine asked how skilled Iâd say I was with JavaScript. I told him I was fluent.
â Fluent? What does it mean to be fluent?
â Well, think Portuguese. â We both speak Portuguese â I donât know every word, but I do know the language enough to express anything I need somehow.
It turned out that âfluentâ was just the perfect word.
Fluency is a powerful and straightforward concept to express your ability with a language. When it comes to human languages, itâs the ability to fully communicate your intentions to a human; for computer languages, the ability to fully communicate your intentions to a computer.
That line of thought is shared in one of the most important and revolutionary introductory books to Computer Science. In Structure and Interpretation of Computer Programs, right before introducing Lisp (the programming language used throughout the book) a similar analogy is made:
Just as our everyday thoughts are usually expressed in our natural language (such as English, French, or Japanese), and descriptions of quantitative phenomena are expressed with mathematical notations, our procedural thoughts will be expressed in Lisp. 1
For both kinds of languages, the levels are the same: one cannot communicate; can poorly do it (beginner); can do it (native/fluent), or can brilliantly do it (think book authors, public speakers, and Software Engineers in a senior level).
Why do they match so well?
They match because the linguistics of computer and natural languages wonderfully intersect. Both consist of syntax, semantics and pragmatics functions, found in the core of theoretical linguistics.
In their ecosystem, we can also find syntax trees and different style guides.
Syntax
Syntax is the set of rules that govern how language elements are combined to form a valid expression.
In English, the basic rule is that elements like nouns, verbs and punctuation marks must follow the subject-verb-object order to produce a valid sentence. In JavaScript, a programming language, to produce a valid conditional statement, elements such as if, parenthesis, braces, comparison operators (===, <= ) must be combined in a certain order too.
In the same way that âDo they car a put?â (??) is not valid English, the following code is not valid JavaScript:
if {1 === 2} (
+return true
+)
+// => SyntaxError: missing ( before condition
+
+add x y = x + y // u can't use elm's lambda syntax on js, no
+
And just like a pedant friend would do when you write shitty English, the computer will throw a syntax error when running your program. Forgot closing a brace? Wrote an if statement condition using curly braces instead of parenthesis? Well, SyntaxError!
This, however, is valid JavaScript:
if (1 === 2) {
+return true
+} // "if (1 === 2) return true" is also fine!
+
+const add = (x, y) => x + y
+
In HTML there are syntax rules too. Adding a div inside ul, for instance, is invalid. An unordered list in HTML (ul) only allows list items as children, such as li â and div is not one.
Languages have different degrees of syntax strictness, which is what usually makes some harder to grasp than others. Think the German language â German imposes very strict rules for articles: they may vary in number, gender, and function. English, on the other hand, has a definite (the) and an indefinite article (a/an)Â â and thatâs it.
The same applies to computer languages: some happen to be extremely strict when it comes to syntax, while others are designed for greater syntactic flexibility, letting you achieve the same result in different ways. Think semicolons: they are optional when ending statements in JavaScript, but mandatory in C.
Semantics
Semantics is what the language expression evaluates to. In human languages, expressions evaluate to thoughts, questions, answers; while computers evaluate expressions to CPU instructions that comprise a programâs flow.
Consider the following English statement:
The ant ran over the car.
I donât know what ants you are familiar with, but even though the sentence contains the necessary elements in correct order and grammar, that doesnât make sense. The statement is syntactically correct but semantically wrong â we canât conceive a meaning from it.
(âThe car ran over the antâ, however, would be definitely more acceptable to our ears.)
We can relate semantics to computer languages in several ways (like âsolving the wrong problemâ, basically), but the âsemanticâ word bubbles up more often when we think about HTML. Consider the following markup:
<span>What is a fruit?</span>
+<div>
+ A fruit is something that humans eat. Some examples of fruits are:
+ watermelon, pineapple and apples.
+</div>
+
The elements span and div do exist in the language and are validly marked in this case (I didnât do >div<, right?), so the browser will understand and show it accordingly to the user. The syntax is correct; yet, span and divs are non-semantic elements, so computers wonât get any meaning from it. Again, syntactically correct but semantically wrong.
That text, though, is clearly a title and a paragraph. With a bit of HTML knowledge, we can communicate this in a meaningful way to computers! The language provides elements to achieve that.
The following code improves the previous markup for better semantics.
<h1>What is a fruit?</h1>
+<p>
+ A fruit is something that humans eat. Some examples of fruits are:
+ watermelon, pineapple and apples.
+</p>
+
The element h1 is being used to communicate the main title, and p communicates the paragraph. Both syntax and semantics make sense now!
Pragmatics
Pragmatics is what the language expression evaluates to within its interactional context â which might totally affect semantics and syntax.
In a natural language, the context is essentially built around the cultural aspects of the speaker, place, time, manner, and several others unpredictable aspects that humans introduce when communicating.
For computer languages, we can see pragmatics as the methodology or implementation used when approaching a problem: composition vs. inheritance, functional vs. imperative, picking a Design Pattern etc.
Consider the following examples:
A child saying that the food is horrible to a beginner that started cooking just recently.
A new joiner in the company filters items in an JavaScript array using forEach, but the team expected filter to be used â a more functional approach.
A programmer implements Fibonacci with recursion instead of iteration.
Your friend uses a very erudite language to add a cake recipe on the internet.
What do they all have in common? By themselves, they are neither right or wrong â unless you consider the context in which they were approached in.
Having either syntax or semantic skills wonât help you understand whatâs wrong, since pragmatics is more about whatâs appropriate within a context. Some approaches are more elegant, antiquated, or dialect-based than others, and we can only tell how valid they are considering what we are trying to achieve.
Syntax trees
Both kinds of languages can be represented using syntax trees, a concept that reuses the mathematical concept of partially ordered sets.
Human languages are analysed through the Concrete Syntax Tree (âCSTâ), a context-free analysis that tells us about the function of each language token (word, punctuation etc) used.
This is the Concrete Syntax Tree for the previous sentence, âThe water drank a glass of Mary.â:Concrete Syntax Tree for a sentence in a human language, where "S" stands for "sentence", "N" for "noun", "V" for "verb", and P for "phrase". See Wikipedia on Parse Trees for more information.
Computer languages are also represented using syntax trees! When the code (high-level) gets translated into instructions for the computer (low-level), a program called compiler make uses of them. The Concrete Syntax Trees for a program contains a lot of detailed information, from whitespaces to language expressions, so you can imagine a CST for a real-world JavaScript program as something really lengthy.
What compilers do might be tough to understand at first, but think of this program inside us that converts languages to meaning â our internal compiler. Kids improve their compilers while communicating with their families, so every day they get to understand their mother language even more. If you understand English yet struggle with German, we can say your German compiler is pretty bad and has to be improved.
The compiler simplifies the CST down to the expressions that truly represent the program after syntax analysis. Thatâs where the Abstract Syntax Tree (AST) comes in: the syntax tree that actually lies at the heart of semantic definitions!
Letâs consider the following JavaScript program:
let x = 0
+
+if (x) {
+x++
+}
+
This is the Abstract Syntax Tree for it:Abstract Syntax Tree for a JavaScript program.
Itâs really about the essentials when considering language grammar. If a whitespace means nothing in a language, that wonât show up in the AST.
When the same expression can be written in several ways because the language is not strict enough about it, style guides aim to answer the question of which style to go for. Curiously, style guides of writing are just as useful for programmers as they are for journalists!
Letâs say Iâm telling someone my favourite fruits. I could do it in different ways:
My favourite fruits are watermelon, bananas and strawberries.
+
+// or using the Oxford comma
+My favourite fruits are watermelon, bananas, and strawberries.
+
The programmer, like the poet, works only slightly removed from pure thought-stuff. He builds his castles in the air, from air, creating by exertion of the imagination. [âŠ] Yet the program construct, unlike the poetâs words, is real in the sense that it moves and works, producing visible outputs separately from the construct itself. It prints results, draws pictures, produces sounds, moves arms. 2
Even with all the similarities, programming languages are still artificial, while human languages are natural. Computers are rigorous, wonât allow you to be ambiguous, and only get what you mean if you put it the right way.
You wonât have filler words in a computer language, because computers donât benefit from your thought process. Humans do benefit, though, and Iâd even say that those communication imperfections is what connects us to others.
Apart from that, a programming language is an interface between you and a computer, while a natural language is an interface between you and another human being. You are communicating to a computer, but as a human â and you probably wonât be the only one doing it.
Writing in a way thatâs meaningful for both is therefore part of the writing process â and probably the most demanding one.
Final thoughts
Just like experienced programmers look at documentation and easily apply language features to create pieces of software, fluent English speakers would look at the dictionary and easily come up with phrases.
Because both computer and natural languages share linguistic structures, speaking about programming skills in terms of fluency works just as well.
After all, fluency is all about how easily our intentions are expressed with a language.
In a life where, by default, thereâs no meaning at all, I value creating above all. If Iâm creating, thatâs a meaningful day.
Lately, Iâve been pondering on the phenomenon of creativity and why creative people are so inspiring to be around. They just broaden my perception of the universe profoundly. What really happens?
The Phenomenon
In an interview in the late 1990s1, Steve Jobs said something that years later would be seen as one of the most simple but accurate definitions of creativity:
Creativity is just connecting things.
And he followed with something I couldnât help but relate: âWhen you ask creative people how they did something, they feel a little guilty because they didnât really do it, they just saw something. It seemed obvious to them after a while. [âŠ]â.
In the wake of being called creative, I was used to responding with the most unfair answer ever: âBut everything I did was mixing stuff from here and there!?!â. It turns out, however, that âmixing stuffâ actually describes precisely the process creative people go through.
And when Steve Jobs said that, he was mixing stuff as well! He most likely got inspired by James Webb Youngâs conception of idea, presented in his book A Technique for Producing Ideas, from the 1940s.
An idea is nothing more nor less than a new combination of old elements [and] the capacity to bring old elements into new combinations depends largely on the ability to see relationships.
For James to suggest that, well, guess what? He was inspired by Pareto's idea of the "speculator", a personality type characterized by a constant preoccupation with the possibilities of new combinations of old elements. (Which sort of proves his own point on "ideas as a combination of old elements".)
Creatives are just so overloaded with elements to mix that those overflow and flow out of their heads, and they canât help but inspire everyone around.
They reframe experiences and mix their elements to be synthesised into something valuable and unique. From songs, painting, programming to scientific theories â all of them comes from mixtures. When the mixture feels good, either as a homogeneous or heterogeneous result, itâs then a creation.
When the creation distances itself too much from its origin elements (which are things people are already aware of, most likely), itâs perceived as weird, rather than authentic. But thatâs when we truly innovate! To come up with the weird, though, we have to limit ourselves to certain existing elements â an outstanding habit people like Alan Turing had.
Alan Turing was an inspiring computer scientist. Among other cool stuff, he proposed humans to consider the question "Can computers think?", and also designed cryptanalytical machines, crucial to cracking German encoded communication during the World War II. Cool stuff!
As described by James Wilkinson, who worked closely with him, Turing avoided looking at previous work on a topic just so he could invent something truly original, truly weird.
âTuring had a strong predilection for working things out from first principles, usually in the first instance without consulting any previous work on the subject, and no doubt it was this habit which gave his work that characteristically original flavor.â2
Finally, the ones who release their creations end up turning into painters, mathematicians, writers, architects, sculptors, programmers, musicians. Itâs a process that happens in absolutely every realm of thinking and work.
And you know what?
âŠItâs Been Shown by Nature
When Young and Steve Jobs pointed out that the creative process wasnât magic, they, again, didnât do anything ânewâ either. That definition has been shown by Nature for a long time, and, as early as 450 B.C, the philosopher Anaxagoras described it:
Wrongly do the Greeks suppose that something3 begins or ceases to be; for nothing comes into being or is destroyed; but all is an aggregation or secretion of pre-existing things; so that all becoming might more correctly be called becoming mixed, and all corruption, becoming separate.
That might remember you of the Law of Conservation of Mass, later defined by the chemist Antoine Lavoisier.
Just like in the creative process, Nature has always found a way out of its problems by coming up with solutions from pre-existing elements. Even the Planet Earth has transformed from a violent, molten rock to a supporter of life by using what the Universe had already provided!
Its process of creation was the same as the humanâs creative process for the discovery of fire, the invention of the wheel, shitty and useful startup ideas, the Pink Floydâs Echoes song, and all quotes in this post: mixing, connecting, combining âstuffâ. From the Planet Earth to what youâre reading right now, the laws that ruled their creations were, in essence, the same.
Brushing teeth is a good habit. An easy-to-build one, Iâd say, thanks to the immediate reward given by the refreshing sensation. After brushing, you feel clean right away.
On the other hand, flossing teeth isnât a habit as easy to build. After flossing, what comes to mind is how dirty your teeth still were even though you just brushed, not how cleaner they became. Thereâs no such thing as a fresh sensation in your mouth.
When you finish brushing your teeth, theyâre still dirty â no doubt. However, itâs still gratifying, since youâre fooled by the menthol ability to trigger the cooling sensation. (Hence the human inclination to brushing rather than flossing!?)
In terms of dental health, though, flossing teeth is more effective on cleaning than brushing1, even if it doesnât feel like it. Thereâs no immediate reward in flossing, but definitely a long-term one.
What am I trying to say? Apart from dental health advice, that sort of reminds me that we shouldnât rely on feeling instantaneously compensated as a fuel to build habits. After all, some things just need the long-term to pay off; for we to benefit from them.
1
Iâve read that at some point in my life but donât remember where. You can find some resources out there, such as âWhatâs More Important: Flossing or Brushing?â. Anyway, I think weâre safe assuming that flossing is, at least, as important as brushing.
Se existem recursos no CSS que a total compreensĂŁo se restringe a uma parcela de desenvolvedores, esses sĂŁo os combinadores filhos (>), irmĂŁos adjacentes (+) e adjacentes gerais (~).
Sem dĂșvidas, esses 3 combinadores sĂŁo tĂŁo poderosĂssimos quanto mal-explicados. Ă importante compreendĂȘ-los integralmente e hĂĄ dois bons motivos para isso: o seletor descendente nĂŁo dĂĄ conta de tudo e, o Ăłbvio: o CSS estĂĄ evoluindo.
Supondo um artigo constituĂdo por um tĂtulo e 3 parĂĄgrafos. O primeiro parĂĄgrafo apĂłs o tĂtulo servirĂĄ como uma introdução ao artigo e, portanto, deve ser destacado com um aumento no tamanho da fonte.
HTML
<article>
+<!-- Z -->
+ <h1>TĂtulo do artigo</h1>
+<!-- X -->
+ <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
+<!-- Y -->
+ <p>Debitis sint aperiam numquam nisi animi porro in reprehenderit!</p>
+ <p>Magnam atque placeat fuga sed eligendi maxime neque labore. Doloribus?</p>
+</article>
+
CSS
h1 + p {
+font-size: 20px;
+}
+
Na prĂĄtica 2
O checkbox hack funciona com o uso do combinador irmĂŁo adjacente.
HTML
<input type="checkbox" id="hider" />
+<div>Hide me if you can!</div>
+<label for="hider">Esconder div</label>
+
CSS
input[type="checkbox"] {
+display: none; /* Esconde o checkbox */
+}
+input:checked + div {
+display: none; /* Quando o checkbox for checado, a div serĂĄ escondida */
+}
+
Esse combinador contorna algumas inflexibilidades do combinador irmĂŁo adjacente. Ainda com o exemplo do checkbox hack, podemos personalizar o elemento de forma nĂŁo tĂŁo especĂfica quanto Ă sua posição:
HTML
<input type="checkbox" id="shower" />
+<label for="shower">Mostrar div</label>
+<div>Hide me if you can!</div>
+<div>Hide me too if you can!</div>
+
CSS
input[type="checkbox"],
+div {
+display: none; /* Esconde o checkbox e a div, por padrĂŁo */
+}
+input:checked ~ div {
+display: block; /* Quando o checkbox for checado, a div aparecerĂĄ */
+}
+
ConclusĂŁo
As linguagens CSS e HTML foram documentadas para serem intuitivas: os elementos formam famĂlias com outros elementos pais, filhos, descendentes, irmĂŁosâŠ. Isso fica claro no nome dos seletores, que tĂȘm papel importante na compreensĂŁo do combinador; afinal, caso o desenvolvedor entenda que irmĂŁos tem o mesmo pai e que filhos sĂŁo descendentes diretos do pai, ele poderĂĄ tirar um bom proveito do nome dos combinadores para compreender seus funcionamentos.
[âŠ] In both cases, non-element nodes (e.g. text between elements) are ignored when considering adjacency of elements.
What most people donât know when they first get into Redux is that, just like React, Redux itself is meant to be simple. And as seen that simplicity is a goal, both React and Redux wonât and donât want to tell you how to solve everything.
They wonât tell you how to deal with side effects, or what HTTP request library you should use. Thatâs completely delegated to the JavaScript ecosystem.
React and Redux alone donât do much for really complex web applications.
React indirectly delegates state management problems to solutions like Flux. On the other hand, Redux, for instance, delegates dealing with async stuff or even the too-much-boilerplate problem that people complain.
But what motivates React and Redux to be that way? Some reasons I can think of are:
Both libraries are highly focused on their principles, not the built-in stuff. The efficiency of them is on the why and how, not the what.
They aim to be a great fit for both simple and large applications, so the âplug-in-playâ approach is followed. (A framework wouldnât ever do everything a programmer needs anywayâŠ)
Diversity of solutions. Because React and Redux are more like âplug-in-playâ, the âpluginsâ (tools, libraries, middlewares) will evolve by themselves. For instance: axios, a HTTP request library, will evolve in parallel to Redux itself â which certainly make things move forward faster!
If your applicationâs state is messy, donât blame it on React. If you find yourself writing too much boilerplate, donât blame it on Redux. React and Redux donât really do much, but this is by design.
React is awesome not just because it makes it possible to turn a large and complex application into simple components.
Redux is awesome not just because it makes it effortless to deal with and share state throughout an application.
Theyâre also awesome because of their great and diverse ecosystem. So, when you buy into React or Redux, itâs better for you to buy into their ecosystem too.
Conditionals! As programmers, we write at least one every day. Easy to write, horrible to read, and sometimes it seems as though thereâs no way to work around that.
Today, Iâm happy to share some patterns Iâve learned over time and have spread heavily in code reviews. Letâs rethink conditionals to make the most out of a languageâs power of expression â in the case of this article, JavaScript.
Patterns for Conditionals
First, to put you in the mood, a quote from Literate Programming1, by Donald Knuth.
The practitioner of literate programming can be regarded as an essayist, whose main concern is with exposition and excellence of style. Such an author, with thesaurus in hand, chooses the names of variables carefully and explains what each variable means. He or she strives for a program that is comprehensible because its concepts have been introduced in an order that is best for human understanding, using a mixture of formal and informal methods that reinforce each other.
That sums up the approach for this post: purely aimed at how to write code for people to read. Performance doesnât matter now, since 1) thatâs not the goal and 2) I donât believe in premature optimisation.
Iâll briefly talk about each pattern, but whatâs more important here is to read the code carefully and get something out of it (as if it were poetry or something!).
1. Variables that hold conditions
When your condition is made up of an expression (or many of them), you can store it within meaningful-named variables.
Letâs say, to illustrate, that our program holds some data about a fruit and we have to check whether that fruit is a banana. We could do this:
const fruit = {
+ colors: ["yellow", "green"],
+ sweet: true,
+}
+
+const isSweet = fruit.sweet === true // or just `fruit.sweet`
+const isYellow = fruit.colors.some((color) => color === "yellow")
+const isBanana = isYellow && isSweet
+
+if (isBanana) {
+alert("do your stuff đ")
+return "is banana"
+}
+
Not all conditions need to be in a variable. fruit.sweet, for instance, is quite expressive by its own.
This way, if we or our workmates need to know what makes a fruit a banana in our program, itâs just a matter of checking out the variable itself. The logic for how conditions evaluate will be there, behind a meaningful name.
Itâs even more useful for composing and reusing conditions.
Filtering arrays
In the previous example, all variables were conditions based on the fruit object, for didactic purposes. Commonly, though, those variables actually store (pure) functions that take any fruit and test against it. I'm changing that to fit this example.
Letâs say weâve got an array of fruits and we need to filter all the bananas out of it.
So expressive! I love the way that I can read that last line and even a kid (a non-programmer one!) can understand. (Yes, Iâve tried that.)
The currying technique would help introduce expressiveness without the verbosity for isBanana. An optional appendix at the end of the article elaborates more on that, if youâre curious.
Thatâs it. Hold on to that one though â itâs the foundation for whatâs next.
2. Define value conditionally
Still considering the variables from the example above, this could also be done:
The value for the myFruit variable will only be assigned to âbananaâ if those conditions are true. Pretty useful for when values are defined conditionally!
That saves you from if (isYellow && isSweet) [...], and itâs quite expressive, Iâd say. An expressive expression. đ
Some additional but important advice Iâd give regarding ternary expressions:
Make them as compound as possible.
Do NOT nest them. Donât pretend the nesting is readable â itâs not even human to do that.
Donât avoid writing if statements because you want to look smart.
4. Check for all conditions
Weâve (finally) found out that checking for isYellow and isSweet isnât enough to make sure the fruit is a banana. After all, yellow pepper is both sweet and yellow and itâs still not a banana, right?
Right. We then add more checks to the isBanana variable, and this time theyâre ugly ones: they check whether the fruit is either from Brazil or Ecuador, both top banana producing countries.
Did you see how big isBanana is getting? Weâd have to start breaking lines in those && to improve readability, which, personally, I donât like doing.
If refactoring the booleans into new variables isnât an option anymore, what about storing the conditions in an array and testing every item for truthiness?
We want something special for when the banana is Brazilian! else conditions would do the trick, wouldnât they?
const fruit = {
+ colors: ["yellow", "green"],
+ sweet: true,
+ countries: [
+ {
+ name: "Brazil",
+ topProducer: true, // i'm brazilian and therefore biased
+ },
+ {
+ name: "Ecuador",
+ topProducer: false,
+ },
+ ],
+}
+
+const isSweet = fruit.sweet === true // or just `fruit.sweet`
+const isYellow = fruit.colors.some((color) => color === "yellow")
+const isBrazilian = fruit.countries.find((i) => i.name === "Brazil")
+const isEcuadorian = fruit.countries.find((i) => i.name === "Ecuador")
+const isBanana = isYellow && isSweet
+
+if (isBanana && isBrazilian) {
+// first true case!
+alert("i am a brazilian banana i love football đ")
+} else if (isBanana && isEcuadorian) {
+alert("i am an ecuadorian banana do not mess with me đ")
+} else {
+alert("a normal banana from somewhere else")
+}
+
Alternatively, THOOOUGH, we can early return (nothing at all, i.e. undefined), which will make our code stops its flow at that point.
if (isBanana && isBrazilian) {
+alert("i am a brazilian banana i love football đ")
+return // sTAAAAHP!!!1
+}
+
+if (isBanana && isEcuadorian) {
+alert("i am an ecuadorian banana do not mess with me đ")
+return // DON'T GO ANY FURTHER, JAVASCRIPT!11
+}
+
+// or do, whatever
+alert("a normal banana from somewhere else")
+
Those checks could also be refactored into a variable named isBrazilianBanana. I found it too much for this example though, so this is just a friendly reminder that your conditions can always be composable.
Keep in mind that early returns might make the flow of your program confusing. Different from when youâre using else conditions, itâs not explicit that the conditionals are from the same logical group anymore.
7. Check for the same variable
Letâs get the colour of the fruits! Each fruit has one.
Hmmm⊠Different cases that require different handling, but all handled cases depend on the same thing. What do we do? We conditionally check for its value and handle the case depending on that.
This is a very common technique I first saw on a blog post from Angus Croll in 2010. I love the simplicity of it.
Nowadays thereâs even more freedom with this technique, considering features such as computed property names for objects. But donât get too creative with that! Go for whatâs more readable and expressive for you AND the people you work with.
Appendix: Currying, because verbosity isnât expressiveness
This is an additional reading and requires familiarity with curried functions. For further reading on the currying technique, I recommend the "Currying" chapter of the book Mostly Adequate Guide to Functional Programming, or A Beginnerâs Guide to Currying, as a more beginner-friendly introduction.
Letâs reconsider:
the problem from the 1st, where we had an array of fruits and had to create a function that checks whether the fruit passed to it was a banana, and
the all util from the 4th pattern.
Check for all conditions, revisited
Imagine if we had a lot of conditions for isBanana. We could use && or even all.
Itâs meaningful, easy to read, but introduces too much verbosity. The currying technique could help us introduce more meaning without being verbose. With some changes in the all util, that could be boiled down to:
const isBanana = all([isSweet, isYellow, isEcuadorian, isBrazilian])
+// no explicit fruit here, and still works!
+const bananas = fruits.filter(isBanana)
+
Notice weâre not explicitly passing fruit anymore. How do we do that? By making all a curried function. There are some ways to achieve that, hereâs one:
It takes the array of conditions and returns a function that takes the current item and calls each condition with that (as argument!). At the end, we check whether they all evaluated to true. Itâs not magic, itâs CURRYING!!!112
Thatâs, of course, a simplistic implementation, which has costed me an array (from map). Whatâs important to get is how we play with function arguments under the hood to achieve currying.
You can curry your functions using Ramdaâs curry (or Lodashâs, whatever); or, if youâre interested on that as an util, Ramdaâs all and its source are really worth-checking!
Final considerations
By striving for conditionals as expressions other than statements, you write code in a functional approach. Code with a clearer sense of what itâs being checked without having to unearth to its foundations. Code thatâs easier and faster for people to reason about.
But if your code is fine with an if rather than an object lookup or a ternary operator, just stick to it.
Itâd break the whole purpose of this post if those patterns were used for looking smart. However, if refactoring your conditionals with them would lead to a more expressive codebase, go for it! Play with the patterns, compound them. Use your creativity to communicate well.
Itâs a language, after all.
1
A programming paradigm first introduced by Donald Knuth, with the goal of providing an alternative, human, perspective on the programmerâs motivation. Read the article.
2
It may seem more magic than currying sometimes. JavaScript isnât a purely functional language, so such techniques arenât as popular as they are in Haskell community, for instance. Simplicity conflicts with easiness here.
The other day, a npm package was released broken to a private GitHub registry and it wouldnât install:
> npm install @company/my-package
+This error happened while installing the dependencies of @company/my-package@0.0.34
+
+another-package is not in the npm registry, or you have no permission to fetch it.
+
The error message is clear: the released package @company/my-package Iâm trying to install depends on a package another-package expected to exist in the npm registry somewhere. But another-package is not there. I already knew those packages came from a monorepo, so likely another-package was only an internal dependency in the monorepo, left unreleased. I wanted to inspect the package contents before releasing any fix to be sure, but couldnât rely on npm install for that. There used to be an option to download npm packages via GitHub UI, but thatâs no longer the case.
Finding the package tarball
One can read the packageâs metadata to find a download URL for the packageâs latest version. Hereâs how:
(For private GitHub registries) Grab a classic GitHub token with packages:read permissions (hereafter {GITHUB_TOKEN}).
The URL of a npm package published to GitHub is https://npm.pkg.github.com/{PACKAGE_NAME}. Use that to fetch the package metadata, which contains the package tarball URL.
Setup for Audio Interface with Guitar Rig 5 on macOS Mojave
Setting up Guitar Rig 5 on macOS Mojave seems not to be straightforward.
Although I had gotten the signals to be sent from my guitar to the audio interface and from the interface to Guitar Rig, somehow itâd still not work. Instead of using my audio interface as the input and output device on Guitar Rig, I had to set up an âaggregate deviceâ.
This how you can do it too.
(My specs, just so you know:)
macOS Mojave Version 10.10.14
+Guitar Rig Pro 5.2.2
+Audio Interface Steinberg UR22mkII
+
Audio MIDI setup
Open âAudio MIDI setupâ in your Mac. (Itâs a tiny secret sound manager shipped along with the system, youâll find it.)
At the very bottom of the app, there is a small + (âplusâ) button wherein you should select âCreate an aggregate deviceâ.
Set up your âaggregate deviceâ with your 1) audio inteface and 2) speakers/headphones/whatever â which should be all shown up there, given the setup is correct. Remember to give your device a remarkable name â I suggest FUCK COMPUTERS AND AUDIO.
My custom device in Audio MIDI Setup on macOS.
Go back to Guitar Rig. In the context menu âFileâ, go to âAudio and MIDI Settingsâ. In the âAudioâ tab, select your aggregate device as the device, instead of only the audio interface as you were doing before; then configure input/output as expected in the âRoutingâ tab.
Using translate() is one of the easiest ways^[Flexbox also provides a great solution. See Solved by Flexbox: Vertical Centering] to instantly horizontal and vertical align any element with CSS without knowing its dimensions.
Nevertheless, after witnessing some people getting their bikes stolen, I feel privileged to say that itâs been more than 1 year Iâve got my bike. If that is because of my good lock or my good luck, Iâll never know.
But I can tell you about the lock.
My lock setup
I generally agree that you should invest as much as you can afford in your lock setup. Iâve put a considerable amount of money on mine because I deeply care â in other words, I have no psychological resilience when it comes to bicycles so losing mine would definitely get me in tears.
If you care about numbers without any trustable source, I've seen recommended somewhere that you should be investing between 10%-20% of the bike price in a lock. đ€·
Therefore, considering the price of having to go home by feet and with tears in my eyes, I did the best I could and went for the Kryptonite Evolution Mini-7 with Double Loop Cable (highly recommend you to check their website for more information).
I make sure my bikeâs frame and both wheels are locked to a fixed rack â cemented into the ground, ideally.My tiny yellow bike parked and properly locked at the office's parking space! Locking up the U-lock to the front wheel instead is a good alternative. Also, I often wrap the steel cable through the rack.
I had considered the Kryptnonite's New York Fahgettaboutdit, but I found it way too heavy and the safety factor difference didn't pay off for me at that time. I'd recommend it if an extra weight is no problem for you though.
For I still have my bike after 1 year, I am honestly happy with my choice. The lock came with:
Three keys with an unique number. For your information, Kryptonite has a system where every key gets a number, so you can order replacements online in case you mess up.
A handy mount made by Kryptonite: Transit FlexFrame U-Bracket (not visible in the photo because itâs in the top tube), so I donât have to carry the U-lock in my backpack or whatever.
Iâve read a couple complaints about the lock not fitting both the wheel and frame to most city racks, however Iâve managed to do it in most racks around Berlin. Itâs definitely not the most flexible and spacious lock, but thieves would love some extra space to do their work too, so I think itâs just the size it should be after all.
When looking for a lock, instead of (only) asking yourself whatâs the best lock ever, ask âHow much trouble am I putting a thief into with my lock strategy?â.
It hasnât been enough stressed that locks do NOT prevent determined thieves with their lock pics, cable cutters, bolt cutters and angle grinders to steal you bike. Period.
Locks do, though, make it harder for thieves to pick your bike, by increasing the âriskâ factor in the risk/reward calculation done before they attempt to steal.
Itâs all about making it harder. And how do you do that? By having a diverse lock setup, and, just as important: by being extremely careful on where and how to park.
Donât think just U-lock: saddle locks, wheel locks might be worth-checking too! One awesome lock is just one at the end of the day, and the more tools the thief needs to carry out, the better.
Looking further
Some articles Iâve read last year and that might be interesting if you own a bike and want to learn more on how to keep it safe.
Best Bike Lock: Review of several bike locks and learnings on how to pick a good one.
How to Lock your Bike: Great tips on where to park your bike and what to lock it to.
How to Exclude CSS, Images, Anything from Unit Tests
Your app needs all those require, but your unit tests may not.
When developing web applications, we deal with assets that our JavaScript tests donât have to be aware of.
If using Webpack, which enables different imports in your JavaScript files, youâve configured loaders that your test runner probably know nothing about. Therefore, that SVG image in your React component and the imported CSS will both be parsed like JavaScript in your tests. A lot of confusing errors will be thrown, of course.
So letâs learn to exclude anything your unit tests, from styles (CSS, Sass), images (PNG, SVG), to other specific imports (like SVG images as React components).
Hook your require() calls
By intercepting require() calls, you can make your testing framework ignore what you want to be ignored the way you want it to be ignored.
Itâs also useful in isomorphic setups.
Return an empty module
It all comes to returning an empty module for unwanted imports. It looks like this:
module.exports = "";
+
Jest
For Jest, configure moduleNameMapper to return the empty module for specific extensions. Example:
require-hacker is an option for hooking require() calls.
You can also use built-in compilers (like moduleNameMapper in Jest or Mocha compilers), or even only import ignore-styles into your testing framework (which is preconfigured).
Iâll stick to require-hacker and custom configuration because thereâs more flexibility.
Get it from npm:
npm install require-hacker --save-dev
+
Configure
Create a JavaScript file and set custom handlers for specific extensions using require-hackerâs hook() method.
Assuming you want to ignore CSS and PNG files, always return an empty module for them:
Because youâre smart, youâll store all extensions in a variable and forEach them, so thereâs no need to repeat yourself. Example.
Import into your test runner
Let your favourite testing framework know about the require hacking! Some examples, assuming a ignore-utils.js file:
Mocha
Add to your mocha.opts, or use the --require flag:
mocha --require ./ignore-utils
+
ava
Add to your package.json:
"ava": {
+"require": [
+"./ignore-utils"
+ ]
+}
+
Now some files will be treated like shit in your JavaScript tests â which is AWESOME!
Bonus: React null component
You donât need to load that boring SVG icon of a house to test that critical feature in a React component, right?
Right. In case youâre using svg-inline-loader, which transform your SVG files into React components, you cannot just return an empty module because your test case would be actually expecting a React component. Things will break. Annoying errors will be shown.
So, instead of returning an empty module for SVG files, return an empty React component. Letâs set a custom handler for that!
Configure
This example uses require-hacker. For Jest, export a React null component and set it in moduleNameMapper.
When we want to test whether a prop has been called, mocking the prop in the component is usually the preferred way. This is how it goes with Jest and Enzyme:
I am using Enzyme however you should be able to spy on similarly using other testing libraries â just make sure you are spying on a function in the props coming from the component prototype (as in wrapper.instance()).
Thatâs all. Just posting it here cuz I couldnât find it easily anywhere else.
What if the user interface is more beautiful-looking than usable, understandable, and intuitive?
The visual aspects of an user interface play an essential role in organising information. Once youâve got the resources, however, that turns out to be the easiest part of an Interface Design process.
Sure we like things that look nice, but looking nice doesnât compensate a bad product design. Visual communication should not compensate flaws.
If you spend most of the time looking for visual inspiration rather than conducting research, doing usability tests, and studying metrics such as business goals and conversion rates, you will probably come up with a interface that only looks beautiful.
I struggle every day trying not to be one step ahead. Living everywhere else but the present and leaping through time have become part of how my brain is wired, so I often find myself not experiencing much anymore.
A while ago, a friend told me about his sensory-deprivation experience in some kind of pool, the so-called Isolation Tank. No sight, no hearing, no touch, no taste, no smell â the idea of getting absolutely no input from anywhere struck me as a way to get my perception back on track. I decided to try it out.
On a sunny Saturday of November, I, along with my endless stream of thoughts, floated for 1 hour straight in a soundproof egg-shaped tub shallowly filled up with salt water. This is my report.
Getting In
With my bathing suit on and no expectations of anything, I showered, got into the tub and sealed down its cover. My body floated easily on that water that thermically felt like my own skin, and a relaxing sound was playing in the background up to the moment my surroundings got all pitch-black.
The first 15 minutes were all about withstanding how restlessly my mind wanted to get out of there. Iâve had done meditation before, but 1 hour was something else. I recalled I worked 8 hours a day, 5 days a week, and therefore I should be making the most out of my Saturday instead. Leisure time! In modern life, that usually means stimulation by means of binge-drinking with friends, uplifting music, delicious food, watching heart-breaking moviesâŠ. Quite the opposite of soul-crushingly doing nothing.
The mind just plays a lot of games on you all the time. It tricked me into being physically irritated by the water, its salt, that bogus zero-gravity environment, and that Iâd be better off giving up for my own survival  â at least, that was how my body anxiously (over-)reacted to it. But there was actually no physiological danger or whatsoever; truth be told, I was way safer than I had ever been throughout that week. I quit panicking.
I came upon different phases of denial, approval and mind-numbness from that onwards. Saw myself bringing up problems and drifting them away. Tried to work out situations I had no control over. Missed music, so made my own by tapping on the water. Went hyper-focused on how I had performed socially last week to what was going to happen in the next few weeks when I eventually hand over my old apartmentâs keys to that spiteful Hausmeister who hates my German.
My thoughts just went on super randomly. After a while, I could draw the exact line where each one ended, and got mindful about my weary physical overreactions to them.
Towards the end, I sank into something else: weightlessness, timelessness, solitude were emerging from that isolation. Things started losing shape. Didnât perceive water. I was either a floating head or a floating body. I had to touch my thighs, boobs, neck just to relieve myself from the uncertainty that being so relaxed made me feel about where I was.
I wanted to come back down to Earth from wherever I was, and, surprisingly, to be myself â the way I was. Then time was up.
Getting Out
I showered again to wash the salt off. The spa provided a relaxation lounge that was essential to ease the transition, since I had neither desire nor need (important!) to rush anywhere. Hung out there for 1 hour.
The readjusting was an interesting and unexpected phase to me. Had an apple and felt how crispy in sound and taste it was. Drank a glass of water and sensed it going right down through. Read a book and couldnât make sense of why we humans have ever brought up speed reading techniques in the first place.
Stepping out of the spa, I got savagely welcomed by a gloomy afternoon1 undergoing that life I was used to every day. A lot was happening out there: lights of apartments being turned on and out, cars groaning, people running around, traffic noise, the cozy energy of having my friend by my side, sharper textures of the sidewalksâ cobblestones, and the joy of a having a sky whose amount of stars doesnât depend on the many times we screw up as human beings, thankfully.
Berlin-Schöneberg is quite chill so thatâs helped to readjust. I was sensible and my thoughts were vivid and receptive â pretty much the actual poetic mood I strive for, where I settle and listen to whatâs being said in order to write it down. A mood that is âhighly disturbed by Philosophyâ, as Goethe brilliantly summed up to Schiller once:
âI am still hoping for poetic hours, and philosophy, in my case, disturbs the poetic mood, probably because it drives me into the object, for I am never able to keep myself in a purely speculative mood, but have immediately to try and form a distinct conception, and on this account at once fly out into nature. [âŠ]2
I had finally my mind drifted towards just as much of the world as it was going on.
Lessons Learned
My poetic mood didnât last much â it wore off the day after.
Iâve realized how much we are externally stimulated and easily adapt to it as if it were natural. On top of that, we are internally stimulated by our worries and whatnot: have I paid my taxes? Am I persuading a career? Does my family still love even though I am thousands of kilometers from them? Have I been eating healthy enough?
It turns out itâs clear why we donât feel much anymore. Our brain gets wired to parallelising stimuli, and we have less and less coming from our body to the head than the other way around. Apart from that, our experience of the world is barely passive: we actively generate it with our biases, mental models, what and how much we consume. Mind shortcuts are crucial, but might restrain us from genuinely experiencing life, getting us to either ignore ou hyper-focus unconsciously.
I, now, have a better grasp of what Erling Kagge meant in Silence: In the Age of Noise, written after he had spent fifty days walking solo in Antarctica: âEverything seemed completely flat and white. [âŠ] Eventually, in complete isolation, I began to notice that nothing was completely flat after all. The ice and snow formed small and large abstract shapes. The uniform whiteness was transformed into countless shades of white. [âŠ]â
Meditation is the absolute protagonist here, but floating got me into a different flow, and faster. The topic of sensory deprivation is definitely worth-exploring. Think like: If you ditch sugar for a while, it tastes sweeter afterwards. ;-)
This is pretty much what floating offers: sensory starvation and you on your own. You may waste your time and never get to anything, or make even most out of that 1 hour than me.
In 2018, circumstances inevitably changed and I began taking up much more in life. I was under stress, regardless of being on the safe side, and the patterns that kept me grounded were no longer holding up.
Back then, seeing the big picture was unattainable with the stress snowballing and skewing my perspective. Dwelling in my head, paving the way to learned helplessness, I decided to try out journaling.
More than a year later, I can finally say alles gut. Although circumstances havenât changed much, I certainly handle them better. I keep journaling as of today, and am excited to share my setup and (hopefully) motivating takeaways!
How I Journal
I did not go for the traditional diary format. I decided to Bullet Journal, a flexible journal method founded in quick lifelogging by means of a pen, paper, and bullet points.
Pen and paper pull me out of my head and let me continuously evolve my notebook as my needs change, since there is no predefined template. As for bullet points, we all know their efficacy: hasty logging and later reviewing at a glimpse.
The Bullet Journal framework is made out of four fundamental âcollectionsâ: Index, Daily Log, Monthly Log, and Future Log, plus custom collections you find valuable. After a while of tinkering around, I came to some insights and tweaks.
Index turned out useful when I added custom collections, as those usually end up scattered across the journal and thus hard to find.
Daily Logs is where I keep track of notes, events, tasks, thoughts, and ideas. (All mixed together, which portrays a day accurately if you ask me.) I recommend using signifiers and nesting (for a tree-like view) in bullet points to convey meaning with ease, as Bullet Journal suggests.
Monthly Log didnât work for me. I steer towards weekly or quarterly ranges. Also, my online calendar is more practical so I couldnât bother drawing calendars every month.
Future Logs are useful to migrate tasks or events to upcoming months, for when you donât get something done but canât ânevermindâ it either.
As for custom collections, the Bullet Journal ecosystem is huge! Iâve seen stuff of all kinds out there: finance/sleep/food/water trackers, recipes, trip planning, doodles, and whatnot. Yet, these are the ones I always come back to:
Diaries: longer diary entries or brain dumps without the limitation of bullet points, for when I feel like it.
Habit Trackers: a simple daily tracker to monitor or develop habits across weeks, e.g. meditation, alcohol intake, call family.
Weekly Logs: my weekly variation of âMonthly Logâ, with upcoming events and small goals for the week. Usually done on Sunday or Monday.
Quarterly Logs: my quarterly variation of âMonthly Logâ, with upcoming events and big goals for the quarter.
Year Retrospective: a straightforward year review regarding what did and did not go well, what to keep or let go from last year etc. I journal spontaneously throughout the day, but mostly in mornings or evenings. I do it every day, even when I donât feel like it. In the long run, thatâs gotten me to fathom my anxieties by having them logged as well as what was up days before. It goes a long way to flip through logs of piled up chores, social isolation, binge drinking, and sleep deprivation, to later find yourself taking down âI am anxious. Canât do shitâ.
Be that as it may, I donât keep it all gloomy. With my throughput in mind, I may also soften up my daily logs with receipts from exquisite restaurants I come across, cute post-its from friends, or even silly useless quotes from fortune cookies.
At last, I have to say Iâm not really a big planner so you can see thatâs not what I optimise my journal for. All I strive for is a little awareness of whatever Iâm doing for the time being. I enjoy a spontaneous and organic life, and thatâs gotten me far enough to make me happy.
Pen & Paper
My 2019 journal (left) and 2020 journal (right).
In 2019, I used an A5+ (slightly wider than regular A5) dot-grid notebook. Itâs bulky to carry around but I donât regret it: the pages are wide enough to encourage writing. The quality of its pleasing yellow paper is outstanding, thick enough to prevent ink from leaking through. I ended 2019 with a few pages empty.
This year, I went for something more portable: an A6 dot-grid notebook. It took me a while to get used to the size constraints, and Iâve been certainly more straightforward with my logs. I am pretty sure I will have no pages left this time. (Wondering what was the advantage of it all as Iâm not going anywhere anyway thanks to COVID-19.)
As for pens, I use different colours of a 0.4 mm fineliner.
What Iâve Learned
I'd not assume these stem necessarily from the way I set myself up. Audio or video recordings, traditional diary, and other journal formats are worth exploring and might help just as well.
Less overwhelm, more time. To truly chill out when life gets overwhelming, you gotta plan ahead. Especially in already busy weeks, I use my journal to put down chores I commit to get done, prioritising what I signify as deadline-sensitive. Before, with my tendency to overfocus, Iâd take up activities without planning and end up neglecting my responsibilities and needs. Imagine how far this can go!
Emotional awareness. Iâve gained a grasp of the phenomenology of my emotions and the lens through which I see life, markedly my cognitive distortions on stressful days. Attitudes like pessimism inevitably surface as you jot down negative thoughts all the time. Being mindful allowed me to reframe negative views, and turn obstacles into opportunities.
Better retainment. Itâs easy to fall into the trap of âI have a bad memoryâ when one has been busy and mooning for so long. Leading a busy life mindlessly is not what I strive for, and journaling only feeds into that: I hold dear people, moments, promises, and no longer miss so many appointments (planning helped here too!).
Constant assessment. Journaling is a tool to assess the present as well as the past and the future. By peeping into where Iâve been, what did/didnât go well, or who I have been with, for instance, I can ponder more sensibly on my growth and relationships. Early feedback on my own life, sort of, to leverage self-improvement in relationships, health, work, and so on.
Pitfalls
Perfectionism. Obsession over constant logging or perfection is right at the door for you to slip into. On social media (Pinterest, YouTube), everyoneâs journal seems visually-appealing every day without fail. Even Bullet Journal, a method dead straightforward, can be a rabbit hole. Remind yourself to solve your problem in a way that enhances your daily life, not burdens it. You gain absolutely nothing from buying into slices of life people sell online.
Habit-building. When not a habit, journaling is just another chore. Make it effortless and engaging: establish a routine (if thatâs your thing), designate it a place where itâs always within reach, or tailor the framework to your needs. If you enjoy drawing once in a while, why not? If you have no patience for 29872 different pen colours, why do it? If you want to write about your day with your partner in bullet points instead of coming up with a best-seller love story, who cares?
Procrastination. Journaling constantly nudges you to look back at your life and how youâve been spending your time and energy. That can be challenging and wonât change. For starters, you might come to the unpleasant realisation that you self-sabotage, or that a certain relationship is fading away. If you are avoidant, you will most likely put off journaling often; not because of the method or routine, but fear of what you may find â fertile soil for procrastination.
For pen & paper⊠No backup. Some companies have tried, but whatâs hand-written wonât sync with a cloud server. You do carry the weight if traveling or taking it to work, and itâs probably gone if you spill coffee on it. I, though, think the trade-off is worth it and havenât looked back.
Final Takeaway đ„Ą
I am all for simplicity, yet that didnât keep my mind from boggling when I realised such a simple tool turned out to be a game-changer. Starting off was not easy, but the benefits showed up and kept me motivated â a rewarding feeling I wouldnât expect so hastily while building a new habit. Today, itâs just effortless and natural.
Ultimately, I hope this stimulates you to try journaling in whatever way and to deem simple tools as helpful to uncomplicate and improve our lives.
In the past three years, a wild mix of stuff dragged me away from writing. More time đł offline â°ïž, which was great. Then a demanding role in a small team, the chaotic grip of a global pandemic, increasing perfectionism, and a blossoming and ultimately collapsing relationship â which all conspired to shake up my pursuits and thrust me into an introspective whirlwind. And as if that wasnât difficult enough, I lost two yearsâ worth of drafts in a backup blunder.
Whenever I attempted to restart, I found myself entangled in a web of what still resonated with me and what no longer did. But hey, listing more excuses would only scratch the surface. I recognize now, after seeing how little it takes for me to be back, that parts of me were simply in disarray. Yet, as I come together again, so does my motivation to reclaim what I enjoy, and make time for it despite the busyness and excuses.
So, last night, I did what I do best: I embarked on an in-one-sitting endeavor! I migrated this blog to Zola (a speedy static generator written in Rust), so this WeBpAg3 remains therefore static and snappy af, joining the <512 kB club. Letting my creativity flow with Tailwind, I gave my WeBpAg3 an extravagant-outrageous look, and made sure itâs accessible. I rewrote my introduction like a million times. I sifted through my writings, organising and archiving some, and lo and behold!: I stumbled upon those lost drafts hidden away in the depths of my physical backups. Pretty thrilling. As a friend once told me, good things happen when good things happen.
Long time no see! It all feels quite nice, if you ask me. đ
Slack comes with limited file storage, so you eventually run out of space. Deleting files isnât easy though: there is no way to bulk delete them using the web interface.
Slack forces you to delete one by one.
And although Slack can force humans, it canât force JavaScript. So JavaScript to the rescue!
Since the beginning of this year, Iâve created a lot of different boilerplates for projects. Working as a freelancer makes you challenge yourself everyday to find out what fits better while working. Currently, itâs sometimes Stylus, sometimes Sass.
Stylus is flexible, and I love it. Sass isnât, but itâs cool anyway. Sometimes I find it hard to bear its inflexibility, though.
On GitHub, thereâs a closed issue about multiline comments on Sass (a Stylus feature!), where I shared a solution for multiline Sass comments. A lot of people still donât agree.
I just want people on community to know it, because it needs to be discussed.
Solution
Start writing the comment as if it were single-line (//), then just follow its indentation. Example.
// Multine comment
+ Indent the text
+ And this will be a comment too
+
Exploring the country where my surname came from and hacking collaboratively at Science Hack Day Vilnius!
I love to hack stuff, and, this year, Iâve been pushing myself to do more of that along with people.
Thatâs how I found a hackathon called Science Hack Day, a weekend event with the goal of âmaking weird, silly or serious things with scienceâ1 in collaboration with others. Although I missed the Berlin edition for just a few days after it happened in November, another event was about to come â this time, in Lithuania, where my surname âGurskasâ came from.
There it was the perfect replacement: the Science Hack Day Vilnius 2018 would be my great excuse to explore the country where my grandfather was born.
Right on the last minute, I got a bedroom in a cheap hotel booked, and my flight and event tickets ready. All set for the hacking adventure!
Welcome to Vilnius
Approximately 2 hours from Berlin by plane, there I was: Vilnius, the capital of Lithuania. A modest city, so small you can pretty much explore everything by feet.
Temperatures were more negative than in Berlin. Winter, and the city wasnât the most colourful either, so the atmosphere was somewhat dark â even though the snow was painting all buildings, houses, and streets in a shining white.
The cold was totally dismissible as soon as I met the Lithuanians, warm and welcoming people who seemed to lead a simple life.
Science Hack Day Vilnius 2018
Trophies for different prize categories. (Photo: Raitis Gocentas)
A Science Hack Day is a 2-day event run by volunteers. Since itâs a hackathon, itâs pretty hectic and leaves you exhausted at the end. However, also since itâs a hackathon, itâs remarkably rewarding at the end.
These were my days!
First Day
Early on Saturday, I walked to Technarium, where the event would happen. Itâs a laid-back and community-operated hackerspace in Vilnius, where technology enthusiasts work or co-work on their projects and share knowledge. My perfect habitat, sort of.Technarium. (Photo: Raitis Gocentas)
I found a seat in the middle of a diverse crowd of enthusiasts: kids, teenagers, and adults (in which you could also find scientists and professors). I had forgotten to adjust my clock to the local timezone when I arrived in Lithuania â 1 hour ahead of Berlin â, so I was kinda late and the talks on open science had already started.
With honestly no idea on how all thatâd end up (a feeling Iâm used to, since I always do unexpected stuff to myself anyway), I was watching the talks and telling myself that the worst that could happen was that Iâd have no idea and no team, and would end up just exploring what others were building. It didnât sound any bad at all! Being around creative people is always appreciated anyway.Electronic hackable badge and some stickers I got for joining the event! The badge features a WiFi-enabled micro-controller and MicroPython, for some hardware hacking fun. Check the badge's GitHub repository.
After the talks, it was time for people to pitch about their potential projects. Most ideas involved Biology, Programming, Physics, Chemistry â anything related to (science) hacking! One of the ideas, from a team of 3 guys, was to build an audio visualiser.
âWe need a Python engineer who understands some audio engineeringâ, they said, in Lithuanian (thanks person who was real-time translating everything!). Luckily, in a beautiful coincidence, I love music, Python, and also have been playing with spectrum analysis for audio visualisation in the last year â so I decided to take a shot and ask them to join the team.
They said they had no idea how to get the input from a microphone, and that they knew more about the hardware part, Arduino, and manipulating those machines in the hackerspace to come up with a cool design for our project. Iâm just bad at things that require manual work that isnât with the keyboard, so my manual help would be typing Python for 2 days on my laptop. They accepted it. So far, we had:
the idea;
an Arduino Nano;
a power supply;
long LED strip lights;
an acrylic sheet.
Since Arduino Nano isnât powerful enough for that computation, itâd be only used for data acquisition, and the spectrometer would live in our Python program in my laptop, computing the Fourier transform of the audio signals.
By the end of the day, we managed to get input from the microphone, analyse its signals in the frequency domain with Python, and start mapping that data to be sent to our Arduino over a serial interface. Some libraries we played with were: pyaudio, numpy, pyserial, matplotlib.
Second Day
Now with the clock correctly set (thanks to my friend that asked what timezone I was in, otherwise I wouldnât ever know), I was on my way to Technarium again, walking over and under snow in that early Sunday morning.
A day in the Science Hack Day Vilnius was a day with Lithuanian hearty lunch, black coffee, and hard work around kind people. (By the way, if you ever end up there, try the kibinai â I ate one filled with spinach and will never forget how it smelled and tasted.)
Most people there were Lithuanians and I didnât know anything about their language besides âlabas vakarasâ2 (âgood eveningâ), so I felt like an outsider sometimes. My teammates and other Lithuanians in the event â including kids â, though, were friendly and spoke English flawlessly, and fortunately even translated some stuff into English for me.
Curious fact: A teenager at the event told me that my surname was "wrong" â in Lithuania, single women get a different surname suffix, so my name should be Gurskaite ("skaite" suffix, instead of âkas). In Brazil, of course, they didnât know that and only cloned my grandfatherâs surname â with the "kas" suffix, since he was a man: Gurskas.
More talks in the morning on open hardware and software. They introduced everyone to GitHub, and many people, even students, were already familiar with it. The importance given to open source was impressive! That made me really happy.
Time flew on the second day! We had got the data we needed, and the next step was to decide on what would be more fun: to map amplitudes from the maximum frequency to RGB values for all LEDs, or map each LED to a frequency and change its colour depending on the amplitude? We picked up the latter, and got our LEDs to blink.
One of my teammates was learning Programming. He told me he didnât know what programming languages to really sit down and learn, as seen that there were a lot of them out there. True, and a nice question! I gave him a biased answer, of course: âgo for Python or JavaScriptâ. My reasons? Way more fun. Besides beginner-friendly, those languages have the most interesting, welcoming and lively ecosystems I know these days.
We were running out of time. While 2 of my teammates were building the LED tower, the other and I were testing the code and trying to improve our algorithm, everything at the same time. Eventually, we got our LEDs to blink the way we wanted them to, and the clock pointed 18:00 sharp. Time for presenting!Project showing how lasers work. It emitted sounds too! (Photo: Raitis Gocentas)
Teams came up with a lot of cool things! Projects related to lasers, contactless payment systems security tests, shopping-cart-rocket launch (#SpaceXLithuania!), plant-watering automation, posters with LEDs crafted by kids celebrating the 100th year of the Lithuanian as an independent country⊠And ours, of course.Two of my teammates (one's missing!) and me. I was weirdly concentrated uttering different notes to show how LEDs reacted to frequencies. (Photo: Raitis Gocentas)
There were different category prizes, and we won as the Best Data Hack!
I got the honor to take home not just this LED-powered trophy below, but also a memorable experience I had the pleasure to share with people I didnât know in a country I didnât know.A trophy for the Best Data Hack 2018 and a Raspberry Pi. Our prizes for having fun!
The Hack Day ended with a science show by N2! Lots of fun with liquid nitrogen and eating cookies at temperatures close to the absolute zero. My teammates, Physics students, knew a lot of the science behind that stuff so I got some extra explanations! (I have to say, though, that one of my greatest learnings of that day was to not to chew those cookies slowly â they stick to your tongue in a TORTURING way.)Playing with fire. Literally. (Photo: Raitis Gocentas)
Itâs always truly amazing to experience closely how creative and curious humans are! The event was awesome, well-organised, and, last but not least, fun. Organisers provided us all the materials (food included!), borrowing me even the single USB-C adapter they had!
Clearly, the only intent behind Science Hack Days is for people to share and learn openly. And that has been achieved just right.
Final words
Open knowledge is one of the most valuable things in this world. I have no doubt.
Iâm happy to have picked such an eccentric travel destination for my weekend, and really grateful for everything I saw and everyone Iâve met on the way.I don't feel my fingertips anymore since I did that. Writing in the snow: definitely NOT encouraged!
Lithuania was freezing, yes, but people were warm.
JĂĄ existem especificaçÔes garantindo funcionalidades incrĂveis para o CSS: variĂĄveis; uma nova sintaxe para media queries; nesting; novos seletores, valores e propriedades. E vocĂȘ pode usĂĄ-las, hoje.
Sobre o que hĂĄ de errado, serei sucinta, pois, para esse artigo, espero um pĂșblico-alvo preguiçoso e acomodado.
O que hĂĄ de errado
âŠem usar jQuery em 2015? O que hĂĄ de errado em importar jQuery ao iniciar o meu projeto?
Analisando superficialmente, nada.
Mas isso tem dado brecha a uma zona de conforto profunda e, na minha experiĂȘncia, com raĂzes difĂceis de arrancar. Essa cultura se expande e transcende aquilo que lhe deu origem. Portanto, perceba:
Deve-se saber quando abranger uma visĂŁo holĂstica do projeto, e quando separar responsabilidades.
A separação de responsabilidades se daria pela anĂĄlise dos requisitos da aplicação e dos desafios gerados, que trazem consigo o que chamo de âsubproblemasâ (necessidades que surgem durante a anĂĄlise do desafio), que devem ser solucionados separadamente. A visĂŁo holĂstica ajudaria a estruturar os componentes de forma consistente em um sistema, definindo uma arquitetura.
Falando de desenvolvimento front-end moderno (e, portanto, falando de front-end modular e de unidades encapsuladas e independentes, os componentes), essa separação de responsabilidades torna-se ainda mais fåcil! Vejamos, abaixo, alguns subproblemas que surgem durante a anålise de requisitos, apenas para exemplificar o que quero dizer quando trato a decisão de ferramentas como uma solução para um subproblema.
Os exemplos a seguir nĂŁo explicam o front-end modular na prĂĄtica. Adianto, no entanto, ferramentas como Browserify ou Webpack, que fazem parte do tooling necessĂĄrio.
Solução possĂvel: encapsular, no componente um mĂłdulo como Reqwest e httpinvoke. VocĂȘ pode, inclusive, utilizar apenas o Ajax do jQuery (e nĂŁo o jQuery inteiro!).
Solução possĂvel: Virtual DOM, que estĂĄ embutido em bibliotecas como React e Mithril. Ou, se precisar mesmo do DOM, considere pacotes como qwery ou Dominus, junto com domready.
E se precisĂĄssemos de Ajax no React, por exemplo? Este mau exemplo na documentação do React importa o jQuery inteiro. Como vocĂȘ faria? ;-)
Basicamente? Tenha um conhecimento decente de arquiteturas front-end (sugiro abrir a mente com Flux, que jĂĄ possui bastante materiais e implementaçÔes da arquitetura disponĂveĂs), e nĂŁo um conhecimento aprofundado de MVC.
Lembre-se de que existem habilidades que a documentação de uma ferramenta nunca_ te ajudarå a desenvolver.
Com o tempo, vocĂȘ vai saber quando adotar um framework especĂfico em escala, quando optar por bibliotecas monolĂticas, e terĂĄ, inclusive, seus preferidos a ponto de nĂŁo ter sempre que definir soluçÔes possĂveis para subproblemas que aplicaçÔes tĂȘm em comum.
(Em alguns projetos, vocĂȘ enxergarĂĄ padrĂ”es, por exemplo: qwery, domready e lodash sĂŁo usados juntos frequentemente.)
Um dia, no entanto, suas ferramentas falharĂŁo, outras ferramentas se adaptĂŁo melhor Ă realidade de seus projetos, e, entĂŁo, o ciclo de anĂĄlise recomeça. E vocĂȘ jĂĄ sabe como proceder.
De acordo com o que venho experimentando, desenvolver essa mentalidade tem retornado experiĂȘncias maravilhosas e, inclusive, gerado menos cĂłdigo legado. Basta apenas aplicĂĄ-la Ă Engenharia de Software com bom senso.
ConteĂșdo sugerido
Os complementos abaixo sĂŁo apenas para despertar a curiosidade em relação aos conceitos apresentados neste artigo, e nĂŁo devem substituir o estudo necessĂĄrio para deixar de lado, na prĂĄtica, a âcultura jQueryâ.
E, humildemente, o meu próprio blog, pois pretendo falar mais sobre arquiteturas de aplicação e front-end modular (que adoro!) na teoria e pråtica.
Se vocĂȘ entendeu a razĂŁo pela qual a âcultura jQueryâ distancia vocĂȘ do seu papel, a mensagem foi entregue com sucesso.
O NOT significa que todos os bits do operando serĂŁo invertidos (0 vira 1, 1 vira 0). Parece inĂștil quando nĂŁo estamos trabalhando com nĂșmeros binĂĄrios, mas as aplicaçÔes criativas tornam o operador mais interessante.
let data = "2";
+const dataAsNumber = ~~data;
+
+console.log(dataAsNumber); // => 2
+
Verificar a existĂȘncia de um item no array
let women = ["Ada Lovelace", "Joan of Arc", "Marie Curie"];
+
+if (~women.indexOf("Ada Lovelace")) {
+console.log("Ada Lovelace was such an important woman!");
+}
+
O equivalente humano, utilizando Lodash (_), seria:
let women = ["Ada Lovelace", "Joan of Arc", "Marie Curie"];
+
+if (_(women).contains("Ada Lovelace")) {
+console.log("Ada Lovelace was such an important woman!");
+}
+
No geral, operadores bitwise, principalmente ~, | e &, possuem aplicaçÔes interessantes e bastante criativas.
Quanto ao ~~, nĂŁo acredito que chegarĂĄ a se popularizar como aconteceu com o !!, que converte para um valor booleano. Em anos, a prĂĄtica com til nunca se tornou realmente popular, talvez pelo fato de ser um operador bitwise â e, portanto, pouco compreendido â e ter casos de uso bastante excĂȘntricos.
Ficam Ă tĂtulo de curiosidade suas aplicaçÔes bastante criativas. ;-)
A Saturday afternoon of May and a few square meters in Berlin were what a couple of people needed to openâ and voluntarily discuss how we impact the Planet to change and how those changes impact us. Topics ranged from radical solarpunk utopia to more down-to-earth and short-term ideas within our generationâs reach today: musings about climate change awareness, sustainability policies for companies, traveling sustainably, tech tools for political change, and how to get out of our bubbles and active listen to other realities.
In this post, Iâll be sharing my personal notes on that engaging and constructive afternoon. There will be, also, references at the end of this post so you can keep yourself posted.
Pitching and picking topics for discussion
OMG Climate is an unconference, meaning that attendees proactively come up with the agenda and topics to be discussed. To kick it off, we got instructed to pitch topics for discussion thatâd be prioritised also by ourselves into tracks, attended based off our preferences. Everyone was expected to have at least a certain knowledge, even if rather tacit, about the challenges weâre facing right now with the climate emergency.
These were the tracks of the first OMG Climate:
Track 1: âLow-carbon travelâ / âGreen Mafiaâ / âHow do you sleep at night? Coping with climate anxietyâ
Track 2: âTech tools for political actionâ / âCircular economies: Re-use and techâ / âCompany sustainability policy templateâ
Track 3: âSolarpunk, imagination and excitementâ / âCO2 Offsets as an API and tracking carbonâ / âClimate change awareness in developing countriesâ
We had enough attendees for tracks to make for productive discussions. Listening and talking to one another, while facilitated by a volunteer, did the job on keeping up an constructive flow between finding root causes and ways to take action.During the "Green Mafia" discussion.
Iâve joined âLow-carbon travelâ, âGreen mafiaâ, and âClimate change awareness in developing countriesâ, so these are the ones I have more insights about. Towards the end, we all got together to wrap it up, and I have to say: all tracks were interesting, so donât restrain yourself to this post!
The following notes don't reflect directly what's happened or everything that's been said in the event, it's rather my personal perspective. They are also somewhat vague, but I hope you can benefit from them somehow.
Low-carbon travel
Air travel, even when occasional, has an environmental impact difficult to make up for no matter how many bamboo toothbrushes we gift our friends, how often we commute by bike or how vegan is our diet.
With low airplane ticket prices getting more popular than ever and enabling people to travel more, how can we make traveling sustainable when not traveling to begin with is not an option? That was the question we kicked off the âlow-carbon travelâ discussion with.
Meeting notes
Collective sketch notes about the low-carbon travel track
In our circle, everyone seemed to have access to the privilege that is air flying.
We began exploring traveling by breaking it down into traveling for work vs. pleasure.
Ground travel might be an option; however, itâs rather time-consuming and hence less appealing in a capitalist society where time translates to money. How can we shift the paradigm?
Instead of seeing longer trips as wasted time, we should begin seeing the journey as part of the trip.
Traveling less: We often optimise our trips to visit as many places as possible; instead, we can optimise for depth and start going to fewer places for a longer time. Think: going to a European country and making the most of it, instead of going to 999 different countries just because they are 1-hour-flight away from each other.
Share practical solutions for people to make trade-offs, EcoCost rather than overwhelming scientific evidence.
What if companies supported employees whose carbon footprint is the least?
Green travel agencies and flying policies.
Search engines for flights obviously donât suggest alternative ways to get to a place when a plane is definitely not the best option.
BVG app, on the other hand, recommends walking instead of taking public transport sometimes.
Transport apps could also order route options by the least environmental impact.
The car industry should be ashamed of its climate record.
The train industry is not modernised and integrated, rather rigid.
Investment on 10 km of autobahn could pay off the renovation for bike lanes all over Berlin.
Globalisation vs. environmental footprint: IT workers immigrating usually go back to their countries often since they have the need and resources. I asked whether there was data available on how that situation in particular couldâve increased our carbon emissions coming from aviation.
Business trips by train are possible only among those who have the privilege of a flexible work schedule, such as freelancers.
Making the most out of idle time: we tend to be more creative in idle times, while in a train; not hunching over a keyboard or in an office environment.
âFast-moving home/officeâ as an alternative to turn the journey time into productive time.
Frequent flyer levy: A fairer tax system according to how often people fly. Those that fly more should pay more. (More information: A Free Ride)
Airline campaigns often promote the image that everyone should become part of a group of young, urban frequent flyers, visiting another city every few weeks for very low costs.
Action points
everyone to shift mindsets in regard to traveling.
everyone to vote instead of buying a bamboo toothbrush.
everyone to use and promote tools with different options of transport within a route, instead of blindly going to specific train or flight websites.
everyone to keep consuming local goods.
airline companies to stop promoting flying as a status symbol.
travel agencies to work out more sustainable ways to travel and consider it in their branding.
We should fight back! We mused about beating off lobby groups representing the coal, car, oil, electricity, and aluminium industries using their same sneaky techniques, as a Green Mafia. An intriguing and fun topic!
The brainstorming served as a tool to get a grasp on the way those mafias function, and discuss whether the ethical approach is always the way to go when facing a crisis.
Meeting notes
Collective sketch notes about the Green Mafia track
Leverage civil disobedience and tools of intimidation to influence green policies for the climate, fight extreme wealth and weaken existing mafias such as the oil industry.
How far should one go with non-ethical practices, such as blackmailing or public shaming of those who harm the planet?
Whatâs ethics after all?
Could we use illegal money to fund our causes?
Could we use legal money to fund our cases? There are ways to get money from the state in licit ways such as from green parties.
What if we made the green cause as profitable for the mafia as oil?
Sell a belief system, or use an existing one such as âharmony with natureâ.
Cyber hacking/hijacking internet algorithms to spread awareness instead of climate change denial and fake news as it happens today.
Coming from a developing country, I was looking forward to this topic! Apart from Brazil, we had people from India too. There was a range of issues that could be tackled within this track, such as the risk of massive displacements of people in developing countries, the need of support to adapt, environment destruction for the sake of economic prosperity, how to approach climate change education etc.
Meeting notes
We are building awareness, not âteachingâ others about climate change.
Climate change is an existential threat to life, but it seems rather remote if you think about poverty, disease and economic stagnation. How do we educate children for the long-term if, for some of them, not showing up at school tomorrow means not eating at all?
How do we let them know about the risk of massive displacements of people who have no resources whatsoever to move?
Just by existing in a developed country in Europe, our carbon footprint is more impactful than any developing country.
Indigenous people are already defenders and protectors of the environment more than we will ever be in our generation.
Developing countries idealisation of economic development, influenced by âdeveloped world standardsâ: tall buildings and industries all over the place, where often we donât see the green implications of âsuccessâ.
What about a model of development thats puts together the simple living of developing countries with the green development of developed ones?
We could shift the discussion to think about environmental impact in terms of social classes instead of countries. After all, rich lifestyles and âstatusâ in general damage the environment in untold ways.
The Swadeshi movement brought back self-manufactured clothing in India to boycott foreign goods, a part of a movement to liberate India from British control and industrialisation.
When teaching, consider whatâs in peopleâs context, reach and language instead of whatâs âout thereâ.
We should actively listen more to those communities and whatâs happening in those countries. Sometimes, instead of thinking that there is something to be taught, we should rather learn from their realities so we can bring about a meaningful conversation.
This is a problem not to be approached by technology, remotely. Itâs rather about Politics and Education.
Action points
everyone to assure inclusivity, cooperation and engagement across boundaries, first and foremost.
countries to keep cooperating efforts internationally through policies, institutional frameworks for development and investments in infrastructure.
Conclusion
Well-led communities that strive for welcoming environments enable the best out of people. OMG Climate has shown that â its unconference format got everyone to take responsibility and engage towards constructive and meaningful discussions about climate change.Final presentations wrapping up the tracks.
Although most of us had a tech background, everyone seemed aware: tech alone will not solve all problems, but we are eager to address them either way.
React and Form Management: Is Redux Form Worth It?
This is an improvement over my answer to a question in a Brazilian forum: "is using Redux for forms worth it?", in Portuguese. It assumes previous knowledge with React and Redux, and also mentions Redux Form, a library for managing forms in React.
It depends.
I know âit dependsâ is far from an interesting answer, yet thatâs the perfect-generic answer to any âis using X worth it?â question. It really depends, yes, but more often you donât need that.
Last year I picked Redux Form to build a multi-step form wizard, each step containing different forms, with its own fields and validations (some of them asynchronous!). In the end, all forms would be merged into one JavaScript object to be sent at some point.
So, Iâd like to share my experiences and hopefully help you to figure it out what your problem is, and help you to decide by telling you how Iâve solved mine.
Where Redux Form thrives
Redux Form is useful for larger and more complex forms where ease of development, high control (especially), consistency, and persistence (especially) are required. There are advantages from:
the state form being in the Redux store, and
Redux Formâs abstraction itself.
Which are two different things. You might need both, just one, or none at all.
Yes, you could also get to build forms in a productive way with only React, but I think it's still worth-mentioning that Redux Form makes it really painless.
High control
You can manipulate forms from anywhere in the application: you trigger Redux actions provided by Redux Form and thatâs all. No need to create your own Redux reducers and actions.
Redux Form is also flexible on what can be an input. Anything works as a field: custom 3rd-party inputs, a regular HTML input, a fancy select component without any standard form element at all⊠Just pass the right props to it.
You can set up validation at the form and field level, supporting either synchronous or asynchronous validation. The errors triggered are also in the store â which makes it sweet to give useful feedbacks for users from anywhere, and also to debug! đ
Consistency
All forms have the same data structure so youâd have the exact same information for every form and its fields, such as field values, field/form validity and further information (is the field touched? Pristine? Dirty?) in the Redux store.
Of course you can build forms consistently just by using React itself, but using Redux Form definitely enforces it.
Persistence
Since the state is already in the Redux store, Redux Form is easily pluggable with tools from the ecosystem.
Letâs say you want to save drafts from userâs inputs so people can finish and submit the form later. Redux Form + redux-persist make it pretty easy: the rehydrate process in the Redux store autofills the UI like magic!
Where Redux Form might die
In the thread, someone mentioned the article Redux Form is dead.TL;DR: It's not fucking dead, as any library, framework and whatsoever that has an "X is dead" post for it.
Letâs not forget that the JavaScript community is flooded with âX is deadâ articles for everything in the ecosystem. That post, in particular, mentions valid points to consider such as ephemerality of the state (quoting Dan Abramov), performance issues within Redux Form, and the project maintenance/activity. I will go through them a bit.
Form data in the Redux store
Dan Abramov, creator of Redux, said: âUse React for ephemeral state that doesnât matter to the app globally and doesnât mutate in complex ways. For example, a toggle in some UI element, a form input state. [âŠ]â.
Which is completely accurate. Where your state should live in your app depends entirely on its ephemerality â how trivial it is for the application as a whole when it comes to reading, updating it and so on.
In the post, that quote is used to support the claim that Redux Form fucks up when stores all form data in the Redux store by default â a pretty bold design decision for sure.
However, Dan did not write that in stone â he never does and heâs clear about it. That should serve as an encouragement for developers to think better about where your applicationâs states should go into. So, yes, you should think twice â and that doesnât kill Redux Form.
The state of a form wizard, whose input data persists until the end of the steps (in a session or local level, for instance), whose inputs may trigger UI changes, whose inputs gets touched and changed by external components, itâs definitely not as ephemeral as the state of a newsletter sign up or a contact form. In the former, the form state is important for the whole application. Just notice thatâs a very specific case.
When it comes to performance, though, you should never rest easy anyway. If you measure and find that your forms are slow, you should find bottlenecks and optimise from that.
Project activity
Regarding the project activity, it is something to consider when deciding, and should always be. Is it active? Are there people maintaining it? Can YOU help to maintain it?
Yes, Erik (the author) has recently started working on another solution called Final Form, which moves the form state out of the Redux store. However, Redux Form is mature, still well maintained (check GitHub, and he even said it himself on Reddit), and its documentation is great.
Final words
Only if the state of your form is non-trivial enough to live in the Redux store, Iâd give it a chance for Redux Form, especially if you are considering making your own solution. Redux Form has suffered and evolved a lot and nowadays it has a very stable and mature API you can count on, Iâd say.
Other React form management solutions you should definitely be looking at are Formik and react-final-form, by Redux Formâs author. They donât rely on Redux for state management and are most likely what you need now â or not.
The price is the abstraction, of course, it always is. đ However, their everyday API is indeed minimal though, just be prepared to go through the documentation when you need to achieve specific stuff. In return, donât forget youâll get a consistent and solid structure to build forms upon.
Because it assures consistency throughout the project and avoids magic numbers, sharing variables between JavaScript and CSS code may help you to keep your project codebase tidy and easier to reason about.
No magic is needed to use those variables in your JS files â just import them when you need it. But in order to communicate those variables to your CSS files and use them with var(), some magic is needed.
For this, I will be using cssnext, a PostCSS plugin, and injecting that object into our stylesheets as custom properties.
import MediaQuery from "react-responsive";
+import { customMedia } from "./variables";
+
+function DesktopOnlyComponent() {
+/* (min-width: 1024px), according to variables.js */
+
+return (
+ <MediaQuery query={customMedia.desktop}>
+ <p>My desktop-only component!</p>
+ </MediaQuery>
+ );
+}
+
Final Words
A non-consistent front-end codebase is just messy.
I really use this technique on everyday work, and itâs a cheap way to significantly improve the quality of the front-end codebase.
So, donât underestimate it! Besides breakpoints, there are infinite possibilities for this, such as project colors, layout dimensions and other shared stuff that can easily get out of hand while working on a large project.
Sometimes, we donât want all of our SVG files to be loaded as React components. If you use a SVG in a img element, for example, it may lead to conflicts. Fortunately, you can avoid them by being more specific in test regular expression:
A memória parece distante agora, mas não faz muito tempo que eu tive essa conversa. 30 de Março de 2016. Jå faz um pouco mais de um ano. Falåvamos de indecisÔes, insatisfaçÔes e mudanças, quando sonhos vieram à tona.
Sonhos. Pessoalmente, penso neles como desejos fixos que habitam a nossa consciĂȘncia junto a outros desejos, mais efĂȘmeros, e que, assim que vocĂȘ os deixa de lado (nem que seja um pouco), inconvenientemente voltam a te atormentar; lembrar que eles ainda estĂŁo lĂĄ e nĂŁo sĂŁo como os outros desejos.
Iâm personally very happy to say that after everything weâve heard and seen, we think youâre a great match for us and would love for you to join our team here in Berlin.
([âŠ] Pessoalmente, estou muito feliz de dizer que, depois de tudo que nĂłs ouvimos e vimos, achamos que vocĂȘ tem tudo a ver com a gente e gostarĂamos que se juntasse ao nosso time aqui em Berlim!)
O que seria para sempre o meu foco, o desejo que eu descorri por 30 linhas no meu LG R510 em uma carta de maio de 2012, aquilo que eu nunca havia tirado da mente, naquele momento surgia como uma oportunidade. Eu topei.
Foram vårios passos antes disso, e eu lembro de estar ansiosa antes de cada um deles. Encontrei pessoas maravilhosas durante o caminho, com um coração tão grande como o meu. Tanto na vida quanto nessa entrevista em particular.
Just got the call! [âŠ] Thatâs an important moment of my life for sure. Iâm just, you know, happy. Thank you for this.
The call. A ligação se referia a do Consulado Geral da Alemanha de Porto Alegre que recebi no dia 8 de maio, dizendo o que esperei 2 semanas (ou toda a minha vida?) para ouvir. O meu visto estava aprovado. Ali estava, sem dĂșvidas, um momento importante da minha vida.
Hoje estou voando para Berlim, a capital da Alemanha, para fazer o que amo na HelloFresh, que me ajudou em todo o processo. Sou grata por isso, por tudo.
A few years back, I jumped into the world of ebooks to broaden my reading without stacking so many physical books. I went with the ever-popular Kindle; yet the full weight of âowningâ ebooks, particularly from Amazon, was not something I understood.
âŠUntil I decided to break up with Amazon, despite its convenience. You know the drill: Amazon exploits workers, aggressively avoids taxes, dominates markets, and I was just itching to explore alternative bookstores. The hiccup? My Kindle was firmly rooted and entangled in Amazonâs ecosystem. Without Amazon, I could no longer conveniently or legally read books on my Kindle, and without Kindle, I could not legally read books I once purchased on Amazon.
Hereâs what Iâve learned while attempting to part ways.
It all begins with âDRMâ
Digital Rights Management (âDRMâ) might not be a household term, yet its fingerprints are everywhere. Ever wondered how we consume content via proprietary software, rather than owning the content?
Think Spotify (you never own the music), Netflix (you never own the film), Adobe Creative Cloud (you never own the software), Steam (you never own the game), and Amazon Kindle (you never own the ebook). You download those proprietary software on your device, not the content itself. While you may have a license to the content, but itâs not truly yours.
The use and distribution of the copyrighted content provided by those services (and many others) are restricted by DRM (âDigital Rights Managementâ) technologies, implemented in various ways, increasingly restrictive and controversial. While DRM aims to address the legitimate need of copyright protection, it fundamentally reshapes the landscape of intellectual consumption, often at the expense of user privacy and freedom. For example:
Content Sharing: DRM often limits, or restricts altogether, the ability to share, lend and gift content outside of the same ecosystem.
Content Portability: DRM can authorise content to only a specific set of devices or apps, and restrict the supported file formats (even to a proprietary format). That limits content migration across platforms, technologies and devices that better suit you.
The points above reveal an alarming side-effect: dependency on the ecosystem, or "vendor lock-in", which is detrimental to individual freedom and market competition. When content is tightly bound to the platform, disengaging becomes challenging. And when you're limited to sharing only within an ecosystem, your social circle gets roped in too. Kinda seem like cute digital mutualism until it's a toxic relationship you can't leave.
Content Perpetuity: DRM cannot guarantee perpetual access to content. If a service or platform discontinues the content or themselves entirely, you may simply lose what you purchased. In fact, that has already happened, more than once or twice.
Content Geographical Restrictions: DRM can prevent access to certain content based on location. With the internet alone, we could technically provide equal access to cultural and educational resources â DRM kills that.
Content Offline Access: DRM often requires online authentication or periodic online checks. Not very nice in low connectivity areas or during travel.
All those âside-effectsâ (given they are actually unintended đ) of copyright protection through DRM conveniences corporations. Corporations may not only protect their profit but also actively profit through DRM, charging high customer cost while delivering zero customer value.
Finally, because DRM implementations vary so much, itâs nearly impossible to determine your rights without diving into lengthy terms of use agreements. The restrictions are rather obscured by clever marketing â youâll soon see.
Leaving Amazon, and failing
Do you still remember I was trying to break up with Kindle? I get too hung up sometimes but letâs not forget why weâre both here, right!!?!
First things first, let me make it clear â I did not want to give up ebooks. Itâd been a pleasure to be able to dive into new literature and keep only the gems in my bedroom bookshelf. And I could also carry a multitude of stories effortlessly during my travels.
Secondly, I had no intention of trashing my Kindle. It was a fully functional piece of hardware, and it worked well.
So here was my grand plan: Iâd log out of my Amazon account on the Kindle, and source my ebooks somewhere else. Seems pretty straightforward, right? But the hurdles kicked in right from the very first step.
As it turns out, signing out of my Amazon account meant every single piece of content Iâd ever acquired through Kindle would vanish into thin air. On Kindle, your books are tied to your Amazon account.
That was an unforeseen repercussion. I naĂŻvely expected to hold rights over books Iâd purchased regardless of whether they were digitally or physically distributed. So I was disappointed and surprised â with myself, the state of things; both. And yes, I clearly had not read Kindle terms of use back when I got into the ecosystem (otherwise you wouldnât be reading this! đ).
FINALLY reading Kindle Terms of Use
The latest Kindle Store Terms of Use (Last updated: November 30, 2022), determines a set of restrictions you buy into when you decide to buy Kindle and Kindle content, DRM-protected or not. The âUse of Kindle Contentâ section states a couple of DRM-ish things:
ebooks are meant to be consumed only on Kindle, or Kindle apps.
Upon your download or access of Kindle Content and payment of any applicable fees (including applicable taxes), the Content Provider grants you a non-exclusive right to view, use, and display such Kindle Content an unlimited number of times (for Subscription Content, only as long as you remain an active member of the underlying membership or subscription program), solely through a Kindle Application or as otherwise permitted as part of the Service, solely on the number of Supported Devices specified in the Kindle Store, and solely for your personal, non-commercial use. [...]
when you click âBuy Nowâ1, you are actually buying a license i.e. renting.
Kindle Content is licensed, not sold, to you by the Content Provider. [...]
Coming from DRM-based services like Spotify or Netflix, where you subscribe for access to a collection of music or film, the Kindle model might be a surprise.
Within the Kindle ecosystem, you are able to buy individual content, which does evoke a stronger sense of direct ownership. Yet, when you do so, youâre essentially obtaining a license: every ebook is an one-off payment to a mini-subscription. And that was absolutely not straightforward or intuitive to me.
you may not lend or sell your ebooks.
Unless specifically indicated otherwise, you may not sell, rent, lease, distribute, broadcast, sublicense, or otherwise assign any rights to the Kindle Content or any portion of it to any third party [...]
your books might disappear anytime.
We may change, suspend, or discontinue the Service, in whole or in part, including adding or removing Subscription Content from a Service, at any time without notice.
(Funny enough, I checked Wayback Machine and noticed that one was amended around March 2015, after reports of disappearing ebooks years before. đ€·)
âŠAnd embracing the sacrifice
Delving into the Kindleâs terms brought the truth crashing down on me: I never really had a choice to transition away from Amazon while retaining my content. Severing ties with Kindle came at a cost I hadnât anticipated, and I felt very exploited for it.
Some might argue I actually had the âchoiceâ to enter Kindleâs ecosystem. And sure, itâs true â I did it willingly, no one coerced me into becoming a Kindle user. But, hey, thereâs a nuanced reality here you canât brush aside: we make our individual choices within systems. Thereâs an entire environment lying behind the notion of individual choice.
Systems can be designed to subtly exert control or exploit personal choice in ways that arenât always apparent. You canât look at individual choice alone overseeing the environment in which those decisions are made. In no defensiveness, blaming on individual choice is, I dare to say, exactly how exploitative systems maintain their facade of legitimacy. And I donât think being exploited or not should be a choice to be made.
Yeah, a bitter pill to swallow, but a new plan has to emerge out of my anger: to log out of my Amazon account, and therefore leave books Iâve purchased behind, and use Kindle only as an e-reader, not a shop.
Leaving Amazon, and failing less
After logging out of my Amazon account, Iâm left with an anonymised Kindle (I hope). At this point I wonder if I even have the right to keep the hardware Iâve purchased, but so far nobody hasnât taken it away from me. đ So, how can I rebuild my e-book library?
Using Kindle with other bookstores
Before buying ebooks elsewhere, one needs to understand what file formats are supported by Kindle. The file formats supported by Kindle are MOBI, PRC, PDF, and primarily the proprietary AZW, and the files may or may not be DRM-protected depending on the publisher. Only Amazon sells AZW books2. So my options are:
MOBI. But no bookstores sell them these days.
PDF. But formatting sucks for reading books.
PRC. I donât know what that is.
So I have no options. \đ/ Bookstores sell EPUB books, an open standard well supported by all e-readers in the market but Kindle. Fortunately, you can manually convert EPUB books into one of the Kindle-compatible formats above. Unfortunately, if the book is DRM-protected (very likely!), you would need to strip out DRM before conversion which is downright illegal LMAOOOOOO!!!!! This drives me CRAZY, but letâs move on.
For ebook format conversions, Amazon fortunately offers Kindle Previewer, a publishing software, but itâs just a little too bloated for my goal. So I went with Calibre, a free and open source e-book manager that does it all. It works wonders!
If you keep your Amazon account, importing EPUB into is easier with Send to Kindle. It's a more convenient option but it often messes up with the book formatting.
Ultimately, using non-Amazon ebooks on a Kindle device can involve various technical and legal considerations, especially when dealing with DRM-protected content. DRM-free book shopping is also limited â DRM is an industry standard! So using a Kindle without Amazon is not just very inconvenient, itâs barely legal. đ
The most promising plan seems to be tossing Kindle altogether, and choose an open standard e-reader with less hostile DRM platforms, but thatâs for another time.
Amazon caters for publishers, not consumers
It all makes sense when you put it all together. When traditional publishing giants contemplated the world of e-readers and online stores, they had to be a bit careful about it. With physical distribution, they already had a model that offered a clear sense of ownership and control. Then, remember the music industryâs digital transformation, marked by piracy and revenue decline3? Obviously publishers would be wary of a similar fate.
But in comes a compelling offer from Amazon: a tight grip on digital ownership of books, and a shortcut into an already profitable book marketplace. All or nothing. A captivating promise of control and access which publishers, late to digital transformation, did not pass up. And so seamlessly, Amazon paved the way towards market dominance. đ
Today, Amazon also positions itself as a platform for emerging writers and attracts independent publishers. So does Spotify for musicians, and Steam for game developers. For both publishers and consumers, content discovery is whatâs great about such platforms, despite their license model.
Alternatives like Bandcamp (music) and GOG.com (games) also promote publishersâ content. In contrast, their DRM-free4 model ethically caters to both consumers and publishers: the consumer has direct ownership to content, and publishers get their content secured, even earning more5. How does that work? Fingerprinting content files (i.e. watermarks), but above all, cultivating consumer trust and transparency, and a sense of community and support for artists.
Final words
While writing this, an analogy came to mind.
Picture when you buy a physical book from a store. You know that book will patiently await you right where you left it and not vanish into thin air, whether you frequent the store or it eventually shuts down. That store is unaware of your identity. It doesnât know when you open or close the book, nor does it know which passages youâve highlighted. You can even lend the book to a friend, regardless of whether they shop at the same store or if the store recognizes them. And that both of you can go buy books elsewhere later with no strings attached.
But I know thatâs kinda corny. Itâs an oversimplification. Digital content IS different, and copying files is far easier technically than producing physical copies. We do have new challenges.
Yet, while the analogy might not outright invalidate DRM as a solution, it can serve as a reminder of the current asymmetry of our digital rights today. A nudge to the way our essential rights are exploited within the current framework of digital copyright protection. And, ultimately, it extends an invitation to reimagine it from the ground up. Perhaps looking at how other platforms like Bandcamp have already done so brilliantly, perhaps radically starting at copyright itself.
Keep reading
âŠon how despite massive technical effort and corporate interest, DRM is a flawed security model.
A cloudy day 1 of Autumn in Berlin, probably something else in the place you live, and youâve read the same date twice and this introduction actually doesnât matter. But let me tell you about something that matters.
Everything is made up of <div>s and <span>s again, utterly hidden behind abstractions proudly called components. No one seems to remember (or do they?) the difference between p and span, let alone the point of using section rather than div.
Bad decisions â to not just to say bad and even invalid HTML markup â are buried in components developers find awesome to compose user interfaces with. The web, and people, pay the price.
Creating components
From now on, to explain my point, I'll be assuming some familiarity with React (a JavaScript library), although this applies to any kind of component abstraction.
Letâs say you just started a brand new React web app. You need to create a button at some point, and, because itâs reused in other parts of the app, has custom styles and also a fancy icon, you decide to introduce a component with all that abstracted out. Nice! You could do it like this:
The user interface is then composed as the following:
<h1>Brazilian Bananas (1 kg)</h1>
+<p>Sweet and healthy bananas!</p>
+<p>Absolutely the best.</p>
+<Button onClick={() => alert('đ')}>Buy $0.99</button>
+
It looks good! You were born for this, werenât you?
Quite easy to miss whatâs wrong when components are just used like that. A button, isnât it? The engineering team can easily grasp what that means and what that does, after all.
It could also be a <FormLabel /> or <Paragraph /> as span elements, or divs all over that place. Although they all work, mistakes are abstracted in components.
I specifically talk about markup as the mistake throughout this article, however it could be anything really. Components look inoffensive when you're using them.
The web isnât your abstraction
Now that HTML is all abstracted through JavaScript libraries and frameworks (which is not wrong), I wonder whether developers only went for semantic elements for the sake of making markup more readable for themselves. With React, your <Header> now may be a div. Out of the abstraction, though, youâd think twice before going for a div to make a header â youâd rather use HTML5âs header.
Because of the abstraction, output markup isnât something we talk that much about anymore.
Did we really get the benefits of HTML5 and why new elements were introduced? Why button? 2 Whatâs header useful for? Why should one use section at all?
By the way, do you know how many occurrences of header, article, section I've found on Netflix's landing page? Zero. It's all div soup.
Matter of fact is that browser engines and people â nothing less than the ones who you really write code for â wonât ever know about your abstractions. A screen reader wonât know your âbuttonâ is actually a button3. (They will definitely get to know the span though, and that wonât help.)xkcd: Tags
Also, itâs never been easier to write invalid markup without even realizing it! After React, it seems acceptable to place a button inside an anchor link, and even giant elephants inside span. Has anyone ever thought why they are considered invalid markup in the first place?
Donât make it hard
Browsers and assistive technologies are smarter than ever4, indeed, yet they still count on developers to write code they can understand and people can benefit from. By doing so, you make it easy for:
people, who will be able to navigate around the website, skipping over navigation sections or quickly jumping from one article to another5.
yourself, so you donât have to reimplement default browser behaviours.
Therefore, please: donât waste features that technologies try to give users, and developers, out of the box.
Remember who you write code for.
1
If I had managed to publish this yesterday, the day would be sunny. Iâve missed the opportunity to make the article seems a little happier.
2
The button element was first introduced in HTML4. (Source)
3
Whatâs wrong with using a non-semantic element as a button? Well, if the button is accessible, nothing really. But doing so demands extra work that nobody is up for, besides that fact that you canât actually create a button.
4
Technologies may even process <span class="tel">123-456-7890</span> as a telephone, and allow for automatic dialling of it. See microformat for more information.
5
Why not, right? After all, articles are for independent pieces of content, e.g., an user-submitted comment or a forum post. (Source)
Still do it? Iâm flattered to tell you that you donât need that extra variable anymore.
Arrow functions
Go with arrow functions instead. Besides having a shorter syntax, arrow functions bind to the parent scope by default.
The scope that was firstly intuitive to you will work as expected now.
function Requester(data, req) {
+this.data = data;
+
+req.done(() => {
+console.log(this.data); // intuitive as hell!
+ });
+}
+
You can count on them most of the time, but they also have unexpected behaviour in more advanced cases. After all, you're dealing with the `this` keyword. So don't just go around refactoring all anonymous functions into arrow ones and expecting everything to work.
You may also .bind()!
If for some reason (such as no support for IE) you canât use them, check JavaScriptâs bind. Itâs not as awesome as arrow functions, but does the job.
We misunderstand learning. We think learning happens as we consume information, so we insist on consumption, hoping it will make sense. Reading sparks new ideasâyet often we merely seek out validation for the ones we already have. We misunderstand learning. We cling to theory like a lifeline, as though it can stand on its own, while overlooking the experimental space where it transforms: practice. Perhaps we gamify it. (Unlearning our addictions is another matter entirely.) We escape the confusion that must lingerâit slips us that lingering isnât forever. We misunderstand learning. Through edutainment, we satisfy the illusion of smooth progress, estimated reading times, chapter after chapter. True learning is too disjointed, unpredictable, and fraught with setbacks. We obsess over minimising gaps between repetitions, but are these gaps learning breaks, or learning itself? I recall the first time I picked up a guitar: my fingers aching to stretch, shredding like crazy against the strings. The morning after, I played the chordânot through conscious effort or passion, but because my fingers developed dexterity and calluses overnight. We misunderstand learning. Technique matters, yes, but some processes of embedding patterns are handled in their own time. Others have it easier, and we feel ashamed. I wonât lieâsome do have it easier. But most often we donât know, we werenât there to see behind the ease, and nobodyâs quite vulnerable these days.
We misunderstand learning, but once, we were in intimate touch with it. Back when we hadnât yet been subjected to environments of comparison, deadlines, narrow molds, and had our complexities and neuro-diversities amassed into pure functions. Iâm not immune to this. At times, learning as an adult feels like a endless chase of the instinctive dance of curiosity it once was. Throw at it: Pomodoro timers, habit trackers and productivity hacks. Yet, itâs only when I sit down to an unmysterious learning practice and truly welcome confusion, chaos, and seeming non-productivity that I feel like I can dance with curiosity again, and learn.
Your teammate worked on a few improvements in all forms of the companyâs website. At some point you, also a programmer, are asked for a code review.
This is the feature branchâs commit history you get in the Pull Request:
[290xx26] Resolve merge conflicts
+[9efxxf2] Refactor event listener for form fields
+[5d9xx5a] Update snapshots
+[948xxfa] Update dispatch event
+[f5xxea1] WIP
+[f8xxaae] Revert change
+[49xxf55e] Revert changes
+[02xxdf1] Update snapshots
+[21xx329] Pass down prop
+[28xxa865] Fix onChange event and add minimal design in form
+[cfxx37c] U[date snapshots
+[cfxx36c] Update form to handle onChange event for autofill
+[242xx25] Fix another bug with onChange
+[f7xx738] Update form component
+[09xx868] Update snapshots
+
It seems like a lot, when actually those improvements are simply 1) fixing a bug with event handling and 2) introducing a minimal style to them. It just that it takes time to visualise that.
Indeed, committing often to a branch is a good practice1 and commits are supposed to be low-level rather than huge. However, a commit is applicable when you have a meaningful, self-contained batch of work to log to the history â and updating Jest snapshots is not it.
How about the following history?
[9efxxf2] Refactor event listener for form fields
+[cfxx37c] Add minimal design in form
+[cfxx36c] Update form to handle onChange event for autofill
+
That history communicates in a clear way what in the codebase has been changed in order to get the improvements done. If you want to know how itâs changed, itâs just a matter of checking out a particular commit.
Why a clear history matters
Apart from facilitating code reviews, since reviewers could grasp the context of the changes right at the first glimpse, a clear Git history is healthy for the project.
When commits started to reflect oneâs workflow rather than the work done itself, the history turns into a mess of both meaningful and meaningless logs, hard to navigate through and undo changes (since commits are âcheckpointsâ of work). Itâs highly likely that, as time goes by, developers will stop caring about the source code history as the powerful resource it is.
*The final Git history should reflect your work not the way you worked.
You begin to lose the benefit of source code management with a messy history, which was supposed to reflect how the codebase evolved over time.
A better relationship with Git
There are very common comprehensible reasons â yet not excuses at all! â for developers to unnecessarily commit. I can think of:
âI had to update snapshots/fix unit test/code formatting/a typo in something I introduced.â
âI had to merge master.â
âI wanted to save my work.â
âI donât necessarily follow a clear flow â I am productive when I work in iterative way and usually do a lot of things at once.â
They can all be worked out by developing a better relationship with Git itself. That might take a while at first, but when itâs part of your daily workflow, you barely think about it at all. (I promise!)
First, letâs talk Git rebasing
Git rebase is a very powerful tool to reorganise your commits. It does a lot, so I wonât get deep into it.
The command git rebase has an important tool you should get comfortable with: interactive rebase. Letâs say we want to reorganise the latest 3 commits:
git rebase --interactive HEAD~3
+
HEAD points to the current branch in your Git repository. You can use @ as an alias as well: @~3, or the commit hash.
Interactive rebase will provide you a text interface with the list of the commits (in this case, within the range HEAD~3..HEAD) that are about to be rebased and actions you can apply to them:
pick [242xx25] Fix another bug with onChange
+pick [f7xx738] Update form component
+pick [09xx868] Update snapshots
+
+# Rebase 242xx25..09xx868 onto 242xx25
+#
+# Commands:
+# p, pick = use commit
+# r, reword = use commit, but edit the commit message
+# e, edit = use commit, but stop for amending
+# s, squash = use commit, but meld into previous commit
+# f, fixup = like "squash", but discard this commit's log message
+# x, exec = run command (the rest of the line) using shell
+#
+# These lines can be re-ordered; they are executed from top to bottom.
+#
+# If you remove a line here THAT COMMIT WILL BE LOST.
+#
+# However, if you remove everything, the rebase will be aborted.
+#
+# Note that empty commits are commented out
+
pick just means that commit is included. It's the default.
Editing that file (either by applying actions to commits or reordering them) and closing it will reapply those commits to the branch. Weâll explore some scenarios where that is useful.
Rebase instead of merge
The branch that you branched from has been updated (letâs call it master), so you need to fetch latest changes and merge that into yours with git pull. Instead of merging and introducing an ugly new commit for that, you can rebase and pretend that nothing ever happened in the first place.
git pull origin master --rebase
+
"Why isn't that the default then?", you might ask. I'd guess they didn't want to make a feature that rewrites history part of the default behaviour.
Squash commits when you can
You need to fix a typo, update a test, or include anything else that should have actually been part of a commit previously introduced. You can create a new commit and later squash it to the initial one with rebase.
git commit -m "Update contact form tests"
+git rebase -i HEAD~2 # act on top of latest 2 commits
+
Interactive rebase will show up, and you can mark that âUpdate contact form testsâ as the commit to be squashed into a previous one by changing pick to s (squash).
The squashed commit has to come exactly before the commit you want to squash into, so you might have to some reordering.
Fix up and save time
Using the --fixup flag along with the commit hash of the previous commit will mark a commit as a fix of an existing one. Then, when you rebase with --autosquash, they will⊠well, automatically get squashed.
Letâs say we have fixed a typo in the commit i2r923:
git commit --fixup i2r923
+git rebase --autosquash 9ef00f2 # one commit before above
+
You can configure Git to use the --autosquash flag by default when rebasing. I do that so you can check my dotfiles if you're curious.
Quite often, youâll know how far youâre traveling from the current commit (HEAD). Instead of specifying hashes, you can just use HEAD as a reference to previous commits:
git commit --fixup HEAD # fix 1 commit before HEAD
+git rebase --autosquash -i HEAD~1 # squash latest 2 commits
+
Stash to save your work in progress
You want to check or change other branchâs files, but donât want to commit unfinished work either. You can stash your work in progress (âWIPâ):
git stash
+
That stores everything from your working directory into stash. Itâs so useful in my day-to-day work that I honestly often cry using it.
On how to get your work back, name your WIPs, or stash specific files, refer to the docs on Git staging. No way I am better at explaining than the documentation itself!
Commit selected chunks of your work
Remember the âI work in a very messy way, iterating between featuresâ excuse? This helps. (It helped me yesterday when I refactored and introduced something new to it â should not be done altogether! â at the same time without noticing.)
Besides only adding a specific file to your commit with git add, you may want to add only a chunk of the fileâs code to a commit. That can be achieved with the --patch flag:
git add --patch
+
Thatâs another interface youâll have to get comfortable with. You can also try out its --interactive option.
Using VS Code?
VS Code has a powerful built-in Git editor that allows you to add chunks of code to a commit. To stage specific lines to commit later, open VS Codeâs Git editor, select the lines of code you feel should go into a commit, and âStage selected changesâ by right-clicking on it.Changed the whole thing but want to commit only a chunk of it? VS Code has got you covered.
The Command Palette also has a âGit: Stage selected changesâ option.
Rename commit messages for meaning
You had a look at the final history and found out your commit messages need some love. To change your latest commit (HEAD), you can just do git commit --amend; for other commits, youâll have to rebase.
Letâs say you want to fix the latest 5 commits:
git rebase -i @~5
+
That will open up the interactive rebase youâre already familiar with. Find the commit you want, change pick to e (edit), and save and close the file; after Git rewinds to that commit, edit its message with git commit --amend, and run git rebase --continue when youâre done.
Make sure that your branch has got a clear, readable and meaningful historyâŠ
git log --oneline
+
Then push it into the remote repository!
git push origin head
+
If you have already pushed (Y THO???!), you can (carefully) use the force option (-f) to rewrite the remote history.
Extra: Fixing the first history
Remember the first history? We can fix it. Itâs definitely harder to change it after itâs done, but totally doable with rebase -i. A possible solution would be:
squash [290xx26] Resolve merge conflicts
+pick [9efxxf2] Refactor event listener for form fields
+squash [5d9xx5a] Update snapshots
+squash [948xxfa] Update dispatch event
+delete [f5xxea1] WIP
+delete [f8xxaae] Revert change
+delete [49xxf55e] Revert changes
+squash [02xxdf1] Update snapshots
+squash [21xx329] Pass down prop
+pick [28xxa865] Fix onChange event and add minimal design in form
+squash [cfxx37c] U[date snapshots
+pick [cfxx36c] Update form to handle onChange event for autofill
+fixup [242xx25] Fix another bug with onChange
+squash [f7xx738] Update form component
+squash [09xx868] Update snapshots
+
Be mindful about your decisions and make sure you are not losing work along the way. I deleted commits unused commits (WIP then reverted), squashed âfixâ and âupdate testsâ commits, and then picked only those that are meaningful batches of work.
I could have also split Fix onChange event and add minimal design in form into two separate commits⊠But thatâs for a future post.
Final considerations
Nowadays, I can say for sure that Git helps me to work better. Those techniques youâve learned are all part of my daily workflow.
There is always something I donât know about Git though, so I keep exploring. I recommend you do to do the same, and you can start right from your command line:
git help -w reset
+
Finally, if somehow you donât feel comfortable with moving around your work from the command line, Iâd recommend Git GUI clients2 â they are powerful and simplify visualising branches and its commits, especially when it gets tough3.
I hope you have better, more sane, work days after that!
It will get tough, because source code management is not easy. Anyhow, itâs always tougher when you care about things anyway. Easiest thing is not to care about anything at all.
Iâm a big fan of writing. Iâm also a big fan of using my code editor and Markdown for that!My "writing mode" in VS Code, with the dark theme enabled.
Code editors are usually packed with a bunch of useful features, such as multi-selection, syntax highlighting, a file tree easy to operate, and sometimes even Markdown support â which I need for writing my articles, notes, to-do lists, and absolutely everything I can write using Markdown. I love having a consistent workflow and thatâs crucial to me, so why not?
After configuring my editor of choice, VS Code, to get rid of the coding mode clutter (and also after an important update on its zen mode â€ïž), Iâve finally achieved a totally distraction-free writing experience!
Setting up the âWriting Modeâ
1. User Settings
There are some important details to achieve total focus on writing. No line numbers, word wrap enabled, comfortable line height, no rulers, are some of them.
Since I only write in Markdown, I only set up those settings (and other tweaks) specifically for that language.
// github.com/diessica/dotfiles/blob/master/vscode/settings.json
+{
+....
+
+"[markdown]": {
+// force centering in zen mode
+"zenMode.centerLayout": true,
+// use the beautiful duospace font when available
+"editor.fontFamily": "iA Writer Duospace, monospace",
+// enable word wrap, since horizontal scroll while writing isn't human
+"editor.wordWrap": true,
+// i don't need line numbers, i'm not coding
+"editor.lineNumbers": "off",
+// light by default, but can be easily toggled to dark
+"workbench.colorTheme": "Default Light+",
+// i don't need rules, i'm not coding
+"editor.rulers": [],
+// larger text, to improve focus on writing
+"editor.fontSize": 14,
+// more comfortable line height
+"editor.lineHeight": 25,
+// disable editor suggestions based on previous words
+"editor.quickSuggestions": false,
+ },
+
+...
+}
+
Now, toggle zen mode in VS Code (see Keybindings, or View > Toggle Zen Mode) and check if that fits you!
2. Theme
Honestly, I think the default themes provided by VS Code do a great job. I use Dark+ as the dark theme; for light themes, either Quiet Light or Solarized Light.
If you don't like them, feel free to pick anything else, since most themes provide sufficient Markdown support anyway. Just don't procrastinate â a good theme won't make you a better writer.
3. Font
My font of choice for writing is the Duospace, designed by the people behind the text editor iaWriter. Itâs a free and beautiful font shaped for the perfect writing experience.
Configure the spell checker for your language, there are dictionary extensions for that available in the marketplace. I also have the Brazilian Portuguese package installed, for instance.
Like extensions? Keep exploring! The extension alex, for instance, catches insensitive, inconsiderate writing in texts.
Learn the Markdown keybindings provided by the All in One extension for a better workflow.
I'm based in ever-changing Berlin, but grew up in never-changing ViamĂŁo, a humble town in Brazil which taught me to be resourceful. Whether it was making kites out of bags and twigs, playing DIY football and cricket on muddy dirt roads, or ringing neighbors' doorbells and dashing away, I hacked whatever came my way.
That ultimately led me to unearth a fascination for computers. Back when I hacked my first game and setup a pirate server just so everything was free, I felt empowered by how computers could help solve our problems. Coming of age, I also realised how they may create new ones. đ
Having honed my skills, and developed a passion for audio along the way, I am nowadays a Lead Software Engineer at Native Instruments. I manage web architecture and operations for leading audio brands, including iZotope.
Raised by the internet, I wholeheartedly support and draw on open knowledge to teach myself, experiment, and have fun. I wish nothing but for everyone to empower themselves towards never-ending exploration as I do.
____
\ No newline at end of file
diff --git a/keybase.txt b/keybase.txt
new file mode 100644
index 0000000..6f95a96
--- /dev/null
+++ b/keybase.txt
@@ -0,0 +1,75 @@
+==================================================================
+https://keybase.io/diessica
+--------------------------------------------------------------------
+
+I hereby claim:
+
+ * I am an admin of https://diessi.ca
+ * I am diessica (https://keybase.io/diessica) on keybase.
+ * I have a public key with fingerprint 4302 C586 30C5 2251 35E4 07A4 449A A724 D631 01B2
+
+To do so, I am signing this object:
+
+{
+ "body": {
+ "key": {
+ "eldest_kid": "0120c2ee894d3a532403315abd1286e80ee3245566c9405b35f3078835f66d6bd0600a",
+ "fingerprint": "4302c58630c5225135e407a4449aa724d63101b2",
+ "host": "keybase.io",
+ "key_id": "449aa724d63101b2",
+ "kid": "01018fbb8563b64f4402fda4c9a56f78869299b72a4407dd248da57eb55d6925a35a0a",
+ "uid": "80c2b902f6438ee3657715451871c819",
+ "username": "diessica"
+ },
+ "service": {
+ "hostname": "diessi.ca",
+ "protocol": "https:"
+ },
+ "type": "web_service_binding",
+ "version": 1
+ },
+ "ctime": 1537532089,
+ "expire_in": 157680000,
+ "prev": "95359140301f30e8c90770914e96635bbd95cb78bbdddb134083e30667dfa6c1",
+ "seqno": 12,
+ "tag": "signature"
+}
+
+which yields the signature:
+
+-----BEGIN PGP MESSAGE-----
+Version: Keybase OpenPGP v2.0.77
+Comment: https://keybase.io/crypto
+
+yMNqAnicbVJtUFRVGF6EdFgiMTAl+oAbLtUweO7HOffeNRgto7XBicKSEKH7cRZu
+wO66u4CAFMFMSfFhBKMhGiAOTskIC0RkRiwoQ9pAOSLWEA3gyqhTjhSZY2PnMvmj
+mc6fc85znvd5n/d9z3Cwv8Hot7mxPXqC9vP4nR1syDfsaPulv4SS7WoRZS6hcvDS
+hnNV7HJn5mgqZaYAzQCFwVgQOZWVIMtwgGVpKMkqzQgICwBjgkGIkCJyAMostLKA
+FwSyI6QiWQUIAImKpayaLQs7HU7N5iayHAsYBQqIBQpkGEizEHOAlziOEyWJZzgV
+sTSgZYYEZttdegQxJ0suHKfZCUYumUv2/od/zzegBassCxCxMuKsHAcYqypxiihB
+ZCUGkciIoswzJCfgVZXhBFWCPJYhVMkTlFgoLfnOX5ITSBNkkUggjhVIyQjyPA05
+SAs8rQi0qBNd2GmT8jBhqxp2uTRFokpjKYIWaArWG6tX8h9GnKJncDjtbrtizyVw
+ttvtcJn1MHeRQ+cVYjnzX4VMWbOppIkkogA7XZrdRplpwlTcmi5JQ5Yn4wGCGEvh
+3Q7NiTM1nQF5JACy9Dy4gEiKkIUiTcYIaDIqLCgi4HlAECwixEJZVkWoyLxADqoq
+0ywHBBazACFetUpIoSm9pl02O9FmiE8pi2i6tCyb5M53YqrUO5geYPAzGpbft0z/
+XQZjYMi9P7cpbeXd10xPUlOJ7M6X0ZzDKuR8MljYmTbRXhNQVPpYbfTC1FMR/ft9
+ZysivftOj8SMmR+vsFjuH2I+77llCtucimP6Vvkvjn31gKdt/Ofuvrc/rHm1abYh
+4JszdsvMTOSj246FKRGtXZVtizfWRf4d5b5WL09F7blZZWru2edsWJNqA8sPxIfP
+H84oX1EX/oG5bNOLp0IXa3qvzo9Om/fYZs99Gz139NKl7dcTfeGPPON/OHDhN+6L
+zEVDrGHibkXr8bKxopzU4e0nSs7d7H33jfJXOioDa7s6Lkgpd0YO5K3N9VXnGoYH
+G93rx4wZzbDr1MD+qihTYuSAJez1o9lx3ts7j0e4R9NMGbOr+6ON7X1bt/zUUtq4
+IyXgZPVFPHrEkpLv+DQr4dC6pqDP4v5YnVD3+3Mjbe8EN4QdrFzono6cMjXKxlFP
+yY/jH3188mIzZ/1OzO59KTg5uS7/0KJ7Rdn56yL0DXWWdbzXWvy8OFn7q8t6Z/72
+KvEhYauB9Wz4emHt1Rso1DZXdWXgzxy4N967e3JXQnfY+72pz04e63ki1JN8q1O7
+4mssMBkdnrfe/EE0FCSJ4wdDQpo2/uXtbCu8Nj/ul/Rluq9mZkNxYOlkkpeq4IPM
+l20PWloy1mysX7klt379GZweH1LtudySmtcaM70Q9HTMhaETxS+cfrjl+2Urj5wv
+74lHe7O5bf8A+5q5NQ==
+=mYMo
+-----END PGP MESSAGE-----
+
+And finally, I am proving ownership of this host by posting or
+appending to this document.
+
+View my publicly-auditable identity here: https://keybase.io/diessica
+
+==================================================================
diff --git a/media/2015/knowledge-diagram.png b/media/2015/knowledge-diagram.png
new file mode 100644
index 0000000..7ba8fb7
Binary files /dev/null and b/media/2015/knowledge-diagram.png differ
diff --git a/media/2015/knowledge-diagram_2x.png b/media/2015/knowledge-diagram_2x.png
new file mode 100644
index 0000000..a76b185
Binary files /dev/null and b/media/2015/knowledge-diagram_2x.png differ
diff --git a/media/2015/moinhos-de-vento.jpg b/media/2015/moinhos-de-vento.jpg
new file mode 100644
index 0000000..15746e4
Binary files /dev/null and b/media/2015/moinhos-de-vento.jpg differ
diff --git a/media/2015/moinhos-de-vento_medium.jpg b/media/2015/moinhos-de-vento_medium.jpg
new file mode 100644
index 0000000..0b43db5
Binary files /dev/null and b/media/2015/moinhos-de-vento_medium.jpg differ
diff --git a/media/2015/moinhos-de-vento_small.jpg b/media/2015/moinhos-de-vento_small.jpg
new file mode 100644
index 0000000..2f70dbd
Binary files /dev/null and b/media/2015/moinhos-de-vento_small.jpg differ
diff --git a/media/2016/twelfth-floor.jpg b/media/2016/twelfth-floor.jpg
new file mode 100644
index 0000000..9da1a68
Binary files /dev/null and b/media/2016/twelfth-floor.jpg differ
diff --git a/media/2016/twelfth-floor_medium.jpg b/media/2016/twelfth-floor_medium.jpg
new file mode 100644
index 0000000..06fd4f9
Binary files /dev/null and b/media/2016/twelfth-floor_medium.jpg differ
diff --git a/media/2016/twelfth-floor_small.jpg b/media/2016/twelfth-floor_small.jpg
new file mode 100644
index 0000000..f891fb2
Binary files /dev/null and b/media/2016/twelfth-floor_small.jpg differ
diff --git a/media/2017/catalysis-diagram.png b/media/2017/catalysis-diagram.png
new file mode 100644
index 0000000..537bebc
Binary files /dev/null and b/media/2017/catalysis-diagram.png differ
diff --git a/media/2017/catalysis-diagram_2x.png b/media/2017/catalysis-diagram_2x.png
new file mode 100644
index 0000000..cd2750f
Binary files /dev/null and b/media/2017/catalysis-diagram_2x.png differ
diff --git a/media/2017/dad-2005.jpg b/media/2017/dad-2005.jpg
new file mode 100644
index 0000000..fe31265
Binary files /dev/null and b/media/2017/dad-2005.jpg differ
diff --git a/media/2017/macos_desktop.mp4 b/media/2017/macos_desktop.mp4
new file mode 100644
index 0000000..df4d2fc
Binary files /dev/null and b/media/2017/macos_desktop.mp4 differ
diff --git a/media/2017/noorder-amstelkanaal.jpg b/media/2017/noorder-amstelkanaal.jpg
new file mode 100644
index 0000000..ea12634
Binary files /dev/null and b/media/2017/noorder-amstelkanaal.jpg differ
diff --git a/media/2017/noorder-amstelkanaal_medium.jpg b/media/2017/noorder-amstelkanaal_medium.jpg
new file mode 100644
index 0000000..c0e14f0
Binary files /dev/null and b/media/2017/noorder-amstelkanaal_medium.jpg differ
diff --git a/media/2017/noorder-amstelkanaal_small.jpg b/media/2017/noorder-amstelkanaal_small.jpg
new file mode 100644
index 0000000..8a0114b
Binary files /dev/null and b/media/2017/noorder-amstelkanaal_small.jpg differ
diff --git a/media/2018/abstract-syntax-tree.png b/media/2018/abstract-syntax-tree.png
new file mode 100644
index 0000000..381bd3b
Binary files /dev/null and b/media/2018/abstract-syntax-tree.png differ
diff --git a/media/2018/benjamin-franklin-routine.jpg b/media/2018/benjamin-franklin-routine.jpg
new file mode 100644
index 0000000..3610fdf
Binary files /dev/null and b/media/2018/benjamin-franklin-routine.jpg differ
diff --git a/media/2018/clicker-flow.jpg b/media/2018/clicker-flow.jpg
new file mode 100644
index 0000000..8341170
Binary files /dev/null and b/media/2018/clicker-flow.jpg differ
diff --git a/media/2018/creativity.png b/media/2018/creativity.png
new file mode 100644
index 0000000..ba0815d
Binary files /dev/null and b/media/2018/creativity.png differ
diff --git a/media/2018/gurskas-snow.jpg b/media/2018/gurskas-snow.jpg
new file mode 100644
index 0000000..19a89c9
Binary files /dev/null and b/media/2018/gurskas-snow.jpg differ
diff --git a/media/2018/mary-glass-syntax-tree.png b/media/2018/mary-glass-syntax-tree.png
new file mode 100644
index 0000000..940f170
Binary files /dev/null and b/media/2018/mary-glass-syntax-tree.png differ
diff --git a/media/2018/sdhv18-badge.jpg b/media/2018/sdhv18-badge.jpg
new file mode 100644
index 0000000..d416306
Binary files /dev/null and b/media/2018/sdhv18-badge.jpg differ
diff --git a/media/2018/sdhv18-lasers.jpg b/media/2018/sdhv18-lasers.jpg
new file mode 100644
index 0000000..da50621
Binary files /dev/null and b/media/2018/sdhv18-lasers.jpg differ
diff --git a/media/2018/sdhv18-n2-fire.jpg b/media/2018/sdhv18-n2-fire.jpg
new file mode 100644
index 0000000..31a5eb0
Binary files /dev/null and b/media/2018/sdhv18-n2-fire.jpg differ
diff --git a/media/2018/sdhv18-prize.jpg b/media/2018/sdhv18-prize.jpg
new file mode 100644
index 0000000..6f61e56
Binary files /dev/null and b/media/2018/sdhv18-prize.jpg differ
diff --git a/media/2018/sdhv18-spectrogram.jpg b/media/2018/sdhv18-spectrogram.jpg
new file mode 100644
index 0000000..afd4eb8
Binary files /dev/null and b/media/2018/sdhv18-spectrogram.jpg differ
diff --git a/media/2018/sdhv18-technarium.jpg b/media/2018/sdhv18-technarium.jpg
new file mode 100644
index 0000000..c6c4241
Binary files /dev/null and b/media/2018/sdhv18-technarium.jpg differ
diff --git a/media/2018/sdhv18-trophies.jpg b/media/2018/sdhv18-trophies.jpg
new file mode 100644
index 0000000..1f382c2
Binary files /dev/null and b/media/2018/sdhv18-trophies.jpg differ
diff --git a/media/2018/vs-code-stage-selected-changes.png b/media/2018/vs-code-stage-selected-changes.png
new file mode 100644
index 0000000..e54d1bc
Binary files /dev/null and b/media/2018/vs-code-stage-selected-changes.png differ
diff --git a/media/2018/vs-code-writing-mode.png b/media/2018/vs-code-writing-mode.png
new file mode 100644
index 0000000..7270aac
Binary files /dev/null and b/media/2018/vs-code-writing-mode.png differ
diff --git a/media/2018/yellow-bike-lock.jpg b/media/2018/yellow-bike-lock.jpg
new file mode 100644
index 0000000..5569811
Binary files /dev/null and b/media/2018/yellow-bike-lock.jpg differ
diff --git a/media/2019/guitar-rig-macos-mojave-setup/audio-midi-setup.png b/media/2019/guitar-rig-macos-mojave-setup/audio-midi-setup.png
new file mode 100644
index 0000000..a0eed55
Binary files /dev/null and b/media/2019/guitar-rig-macos-mojave-setup/audio-midi-setup.png differ
diff --git a/media/2019/guitar-rig-macos-mojave-setup/guitar-rig.png b/media/2019/guitar-rig-macos-mojave-setup/guitar-rig.png
new file mode 100644
index 0000000..b69d4e3
Binary files /dev/null and b/media/2019/guitar-rig-macos-mojave-setup/guitar-rig.png differ
diff --git a/media/2019/omg-climate/discussion.jpg b/media/2019/omg-climate/discussion.jpg
new file mode 100644
index 0000000..28f3e05
Binary files /dev/null and b/media/2019/omg-climate/discussion.jpg differ
diff --git a/media/2019/omg-climate/global-warming-nasa.gif b/media/2019/omg-climate/global-warming-nasa.gif
new file mode 100644
index 0000000..ac7d6fb
Binary files /dev/null and b/media/2019/omg-climate/global-warming-nasa.gif differ
diff --git a/media/2019/omg-climate/green-mafia.jpg b/media/2019/omg-climate/green-mafia.jpg
new file mode 100644
index 0000000..6402e3e
Binary files /dev/null and b/media/2019/omg-climate/green-mafia.jpg differ
diff --git a/media/2019/omg-climate/low-carbon.jpg b/media/2019/omg-climate/low-carbon.jpg
new file mode 100644
index 0000000..0111bce
Binary files /dev/null and b/media/2019/omg-climate/low-carbon.jpg differ
diff --git a/media/2019/omg-climate/presentation.jpg b/media/2019/omg-climate/presentation.jpg
new file mode 100644
index 0000000..7f35a23
Binary files /dev/null and b/media/2019/omg-climate/presentation.jpg differ
diff --git a/media/2020/bullet-journal.jpg b/media/2020/bullet-journal.jpg
new file mode 100644
index 0000000..e21f89e
Binary files /dev/null and b/media/2020/bullet-journal.jpg differ
diff --git a/robots.txt b/robots.txt
new file mode 100644
index 0000000..49b6b2e
--- /dev/null
+++ b/robots.txt
@@ -0,0 +1,4 @@
+User-agent: *
+Disallow:
+Allow: /
+Sitemap: /sitemap.xml
diff --git a/sitemap.xml b/sitemap.xml
new file mode 100644
index 0000000..520d090
--- /dev/null
+++ b/sitemap.xml
@@ -0,0 +1,262 @@
+
+
+
+ /
+
+
+ /blog/
+
+
+ /blog/5-bibliotecas-essenciais-para-desenvolver-react-apps/
+ 2016-03-21T23:00:00
+
+
+ /blog/a-better-es2015-and-jsx-workflow-in-vs-code/
+ 2016-10-30T00:00:00
+
+
+ /blog/a-bit-on-random-numbers-in-javascript/
+ 2016-11-15T16:50:00
+
+
+ /blog/a-cascata-das-variaveis-do-css/
+ 2016-05-30T22:00:00
+
+
+ /blog/a-fantastica-diversidade-do-front-end/
+ 2016-04-09T15:10:00
+
+
+ /blog/a-guide-to-favicons-and-touch-icons/
+ 2015-09-06T10:53:00
+
+
+ /blog/a-minimal-workspace-on-macos/
+ 2017-05-04T19:45:57
+
+
+ /blog/archive/i-travelled-to-photographs/
+ 2017-04-19T10:13:00
+
+
+ /blog/catalysis/
+ 2017-04-13T11:27:00
+
+
+ /blog/choose-life-in-berlin/
+ 2017-05-12T19:15:00
+
+
+ /blog/como-eu-vi-a-braziljs-2015/
+ 2015-08-26T02:10:32
+
+
+ /blog/computer-and-human-languages/
+ 2018-06-20T18:06:00
+
+
+ /blog/creativity/
+ 2018-02-05T21:25:00
+
+
+ /blog/dental-health-and-habits/
+ 2017-12-21T08:58:09
+
+
+ /blog/desmitificando-seletores-complexos/
+ 2013-11-28
+
+
+ /blog/dont-blame-it-on-react-or-redux/
+ 2017-03-18T13:49:00
+
+
+ /blog/encadeamento-de-metodos-em-javascript/
+ 2016-08-06T16:11:32
+
+
+ /blog/expressive-javascript-conditionals/
+ 2017-10-30
+
+
+ /blog/extra/
+
+
+ /blog/fetch-npm-package-without-npm-install/
+ 2024-08-25T16:30:00
+
+
+ /blog/guitar-rig-macos-mojave-setup/
+ 2019-08-18T22:19:05
+
+
+ /blog/horizontal-and-vertical-align-anything-with-css/
+ 2016-11-06T19:10:01
+
+
+ /blog/how-i-lock-my-bike-in-berlin/
+ 2018-08-30T07:00:00
+
+
+ /blog/how-to-exclude-css-images-anything-from-unit-tests/
+ 2016-11-19T09:54:29
+
+
+ /blog/how-to-spy-on-a-prop-with-jest/
+ 2019-10-31T14:15:42
+
+
+ /blog/i-m-tired-of-beautiful-looking-interfaces/
+ 2016-10-23T12:50:35
+
+
+ /blog/isolation-tank/
+ 2018-12-02T08:01:00
+
+
+ /blog/journaling/
+ 2020-04-20T00:10:15
+
+
+ /blog/long-time-no-see/
+ 2023-06-30T11:19:00
+
+
+ /blog/mass-deleting-files-from-slack/
+ 2016-04-17T00:10:15
+
+
+ /blog/multiline-sass-comments/
+ 2015-08-17
+
+
+ /blog/my-hacking-adventure-in-lithuania/
+ 2018-02-15
+
+
+ /blog/o-css-do-futuro/
+ 2016-05-29T23:21:51
+
+
+ /blog/o-que-ha-de-errado-com-a-cultura-jquery/
+ 2015-09-20T09:56:05
+
+
+ /blog/o-til-no-javascript/
+ 2015-10-31
+
+
+ /blog/omg-climate/
+ 2019-05-30T11:39:14
+
+
+ /blog/react-and-form-management-is-redux-form-worth-it/
+ 2018-05-21T18:14:00
+
+
+ /blog/shared-variables-between-javascript-and-css/
+ 2017-01-15T15:00:00
+
+
+ /blog/svg-images-as-react-components-with-webpack/
+ 2016-08-02T22:00:00
+
+
+ /blog/tchau/
+ 2017-05-13T16:12:00
+
+
+ /blog/the-bitter-reality-of-ebooks/
+ 2023-08-16T13:55:00
+
+
+ /blog/ttt/
+ 2018-04-01T23:36:00
+
+
+ /blog/ui-components-that-abstract-mistakes/
+ 2017-10-14T18:06:00
+
+
+ /blog/var-that-this-nah/
+ 2017-03-15T09:00:00
+
+
+ /blog/we-misunderstand-learning/
+ 2024-09-19T13:13:42
+
+
+ /blog/working-better-with-git-for-a-clear-history/
+ 2018-08-04T07:00:00
+
+
+ /blog/writing-mode-in-vs-code/
+ 2018-02-28T02:30:00
+
+
+ /tags/
+
+
+ /tags/activism/
+
+
+ /tags/books/
+
+
+ /tags/climate-change/
+
+
+ /tags/css/
+
+
+ /tags/design/
+
+
+ /tags/digital-rights/
+
+
+ /tags/essay/
+
+
+ /tags/html/
+
+
+ /tags/javascript/
+
+
+ /tags/language/
+
+
+ /tags/music/
+
+
+ /tags/personal/
+
+
+ /tags/productivity/
+
+
+ /tags/pt-br/
+
+
+ /tags/react/
+
+
+ /tags/script/
+
+
+ /tags/software/
+
+
+ /tags/test/
+
+
+ /tags/travel/
+
+
+ /tags/work/
+
+
+ /tags/workflow/
+
+
diff --git a/tags/activism/index.html b/tags/activism/index.html
new file mode 100644
index 0000000..d9a4a67
--- /dev/null
+++ b/tags/activism/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/books/index.html b/tags/books/index.html
new file mode 100644
index 0000000..14c71ff
--- /dev/null
+++ b/tags/books/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/climate-change/index.html b/tags/climate-change/index.html
new file mode 100644
index 0000000..bb9c25f
--- /dev/null
+++ b/tags/climate-change/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/css/index.html b/tags/css/index.html
new file mode 100644
index 0000000..93abb1b
--- /dev/null
+++ b/tags/css/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/design/index.html b/tags/design/index.html
new file mode 100644
index 0000000..4bfc899
--- /dev/null
+++ b/tags/design/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/digital-rights/index.html b/tags/digital-rights/index.html
new file mode 100644
index 0000000..4aea1b8
--- /dev/null
+++ b/tags/digital-rights/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/essay/index.html b/tags/essay/index.html
new file mode 100644
index 0000000..4f22ca6
--- /dev/null
+++ b/tags/essay/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/html/index.html b/tags/html/index.html
new file mode 100644
index 0000000..ba9d299
--- /dev/null
+++ b/tags/html/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/index.html b/tags/index.html
new file mode 100644
index 0000000..84717fc
--- /dev/null
+++ b/tags/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/javascript/index.html b/tags/javascript/index.html
new file mode 100644
index 0000000..e456824
--- /dev/null
+++ b/tags/javascript/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/language/index.html b/tags/language/index.html
new file mode 100644
index 0000000..65c5ec5
--- /dev/null
+++ b/tags/language/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/music/index.html b/tags/music/index.html
new file mode 100644
index 0000000..e4e13df
--- /dev/null
+++ b/tags/music/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/personal/index.html b/tags/personal/index.html
new file mode 100644
index 0000000..1a54363
--- /dev/null
+++ b/tags/personal/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/productivity/index.html b/tags/productivity/index.html
new file mode 100644
index 0000000..a4b26ba
--- /dev/null
+++ b/tags/productivity/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/pt-br/index.html b/tags/pt-br/index.html
new file mode 100644
index 0000000..88c126b
--- /dev/null
+++ b/tags/pt-br/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/react/index.html b/tags/react/index.html
new file mode 100644
index 0000000..36f792a
--- /dev/null
+++ b/tags/react/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/script/index.html b/tags/script/index.html
new file mode 100644
index 0000000..f1a1f06
--- /dev/null
+++ b/tags/script/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/software/index.html b/tags/software/index.html
new file mode 100644
index 0000000..5ea0a16
--- /dev/null
+++ b/tags/software/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/test/index.html b/tags/test/index.html
new file mode 100644
index 0000000..4c3a3b5
--- /dev/null
+++ b/tags/test/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/travel/index.html b/tags/travel/index.html
new file mode 100644
index 0000000..53da6c3
--- /dev/null
+++ b/tags/travel/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/work/index.html b/tags/work/index.html
new file mode 100644
index 0000000..7777e2a
--- /dev/null
+++ b/tags/work/index.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/tags/workflow/index.html b/tags/workflow/index.html
new file mode 100644
index 0000000..eb6a172
--- /dev/null
+++ b/tags/workflow/index.html
@@ -0,0 +1 @@
+