<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: José Muñoz</title>
    <description>The latest articles on Forem by José Muñoz (@josemunoz).</description>
    <link>https://forem.com/josemunoz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F91117%2F54f21f20-9e2c-472d-92f9-642a6d60f77b.jpeg</url>
      <title>Forem: José Muñoz</title>
      <link>https://forem.com/josemunoz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/josemunoz"/>
    <language>en</language>
    <item>
      <title>Pimp your CLI</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Tue, 19 Dec 2023 17:20:25 +0000</pubDate>
      <link>https://forem.com/josemunoz/pimp-your-cli-3i5e</link>
      <guid>https://forem.com/josemunoz/pimp-your-cli-3i5e</guid>
      <description>&lt;p&gt;&lt;em&gt;Also available in &lt;a href="https://dev.to/josemunoz/enchula-mi-consola-5d70"&gt;spanish&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a developer, the command line is one of the tools you will be using most frequently. It can be intimidating to venture into the world of CLI tooling but I can assure you it is one of the most rewarding experiences too. In this post I want to walk ya'll through my personal CLI setup. It is based on 3 technologies which I'll coin as the "Holy Trinity" of the command line: &lt;a href="https://github.com/tmux/tmux/wiki" rel="noopener noreferrer"&gt;TMUX&lt;/a&gt;, &lt;a href="https://www.zsh.org/" rel="noopener noreferrer"&gt;ZSH&lt;/a&gt;, &amp;amp; &lt;a href="https://neovim.io/" rel="noopener noreferrer"&gt;Neovim&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Linux, MacOS, or WSL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your favourite &lt;a href="https://www.nerdfonts.com/font-downloads" rel="noopener noreferrer"&gt;NerdFont&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A decent terminal application (i.e: &lt;a href="https://iterm2.com/" rel="noopener noreferrer"&gt;iterm2&lt;/a&gt;, &lt;a href="https://alacritty.org/" rel="noopener noreferrer"&gt;alacritty&lt;/a&gt;, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;you OS’s equivalent of &lt;code&gt;apt install zsh tmux neovim&lt;/code&gt;,&lt;br&gt;
I'm using Debian for this demo&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TMUX
&lt;/h2&gt;

&lt;p&gt;The cornerstone of the command line experience in my opinion has to be the terminal multiplexer: tmux. &lt;br&gt;
In simple terms (pun intended) tmux allows you to split your terminal into different panes, windows, or sessions. Have you ever ssh'd into a server to start a long running process and the screen-saver killed your session? tmux will keep the session running even if the client disconnects and you can pick up where you left by just attaching to the previous session. There is an entire ecosystem with themes, plugins, and utilities built around tmux. Checkout the &lt;a href="https://tmuxcheatsheet.com/" rel="noopener noreferrer"&gt;tmux cheat sheet&lt;/a&gt; to get familiar with the basic functionality and keyboard shortcuts. This is really just the tip of the iceberg, I encourage you to dive deeper and customize your setup to your liking. By default your experience might not look like much:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FLLIs0Cb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FLLIs0Cb.png" alt="tmux before"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will start by creating a custom tmux configuration by running &lt;code&gt;nvim ~/.tmux.conf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;One of the first life comfort changes I make to my tmux configuration is to set the index to base 1. On your keyboard its easier to switch between the numeric keys in order rather than starting in one end and reaching to the opposite end for the rest of the options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# start windows, sessions, and panes with 1&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; base-index 1
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pane-base-index 1
set-window-option &lt;span class="nt"&gt;-g&lt;/span&gt; pane-base-index 1
set-option &lt;span class="nt"&gt;-g&lt;/span&gt; renumber-windows on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also like to change the leader key combination, you're going to be using this key-combo a lot so make sure you set it to something comfortable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# change prefix&lt;/span&gt;
unbind C-b
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; prefix C-Space
&lt;span class="nb"&gt;bind &lt;/span&gt;C-Space send-prefix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, one of the configs that I personally think should be the default is to open a new pane or window on the Current Wording Directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="c"&gt;# split in cwd&lt;/span&gt;
 &lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; split-window &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"#{pane_current_path}"&lt;/span&gt;
 &lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt; split-window &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"#{pane_current_path}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will provide you with a solid base to configure further on your own, but in order to &lt;em&gt;really&lt;/em&gt; take it to the next level, you have to be able to tap into Tmux's plugin ecosystem. TPM (Tmux Plugin Manager) can be installed by cloning its repository into Tmux's plugins folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after that, you will have to keep this at the very end of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)&lt;/span&gt;
 run &lt;span class="s1"&gt;'~/.tmux/plugins/tpm/tpm'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a list of your desired plugins at the top, starting with tpm of course:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @plugin &lt;span class="s1"&gt;'tmux-plugins/tpm'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I would also recommend adding &lt;code&gt;tmux-plugins/tmux-sensible&lt;/code&gt;, and &lt;code&gt;catppuccin/tmux&lt;/code&gt; for usability and aesthetics. Your &lt;code&gt;.tmux.conf&lt;/code&gt; should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="c"&gt;# List of plugins&lt;/span&gt;
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @plugin &lt;span class="s1"&gt;'catppuccin/tmux'&lt;/span&gt;
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @plugin &lt;span class="s1"&gt;'tmux-plugins/tpm'&lt;/span&gt;
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @plugin &lt;span class="s1"&gt;'tmux-plugins/tmux-sensible'&lt;/span&gt;

 &lt;span class="c"&gt;# split in cwd&lt;/span&gt;
 &lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; split-window &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"#{pane_current_path}"&lt;/span&gt;
 &lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt; split-window &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"#{pane_current_path}"&lt;/span&gt;

 &lt;span class="c"&gt;# start windows, sessions, and panes with 1&lt;/span&gt;
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; base-index 1
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pane-base-index 1
 set-window-option &lt;span class="nt"&gt;-g&lt;/span&gt; pane-base-index 1
 set-option &lt;span class="nt"&gt;-g&lt;/span&gt; renumber-windows on

 &lt;span class="c"&gt;# change prefix&lt;/span&gt;
 unbind C-b
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; prefix C-Space
 &lt;span class="nb"&gt;bind &lt;/span&gt;C-Space send-prefix

 &lt;span class="c"&gt;# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)&lt;/span&gt;
 run &lt;span class="s1"&gt;'~/.tmux/plugins/tpm/tpm'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;assuming you're already running tmux, you can run &lt;code&gt;tmux source-file ~/.tmux.conf&lt;/code&gt; to load the new config. After the new config has been loaded you need to install the plugins by using your new key-combo and &lt;code&gt;Shift+I&lt;/code&gt;. Depending on your font you might have to adjust the font size, 16 is a good default.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Ffv9TlyP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2Ffv9TlyP.png" alt="not too shabby"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If any of the plugins fails to install you can always use this same mechanism of cloning the repo and calling "install" after. Make sure to checkout &lt;a href="https://github.com/rothgar/awesome-tmux" rel="noopener noreferrer"&gt;Tmux's Awesome list&lt;/a&gt; for more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Z Shell
&lt;/h2&gt;

&lt;p&gt;ZShell is an alternative to bash a.k.a. "Bourne-Again SHell". It does everything that bash does and just like Tmux it is extensible via a healthy plugin ecosystem. By this point I hope you have already tried to run &lt;code&gt;zsh&lt;/code&gt; on your terminal. At first it won't look like much has changed but with the right plugins this can become your best friend on the command line.&lt;br&gt;
The first thing we need to do is to install &lt;a href="https://ohmyz.sh" rel="noopener noreferrer"&gt;oh-my-zsh&lt;/a&gt;, a framework on top of zsh that manages configs, plugins, themes, and more.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you complete the installation you should have a new configuration file called &lt;code&gt;.zshrc&lt;/code&gt; on your home folder, if you open it with &lt;code&gt;nvim ~/.zshrc&lt;/code&gt;, you will see that it already has been populated with the default &lt;code&gt;oh-my-zsh&lt;/code&gt; configuration. One of the most essential plugins for me is &lt;code&gt;zsh-autosuggestion&lt;/code&gt; which provides autocomplete functionality, to install you need to add it to the plugins list on the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt; 
    &lt;span class="c"&gt;# other plugins...&lt;/span&gt;
    zsh-autosuggestions
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clone the repo to the &lt;code&gt;oh-my-zsh&lt;/code&gt; plugins folder like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-autosuggestions &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/plugins/zsh-autosuggestions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, you want to source the new config using &lt;code&gt;source ~/.zshrc&lt;/code&gt;, do this every time you edit the config.&lt;/p&gt;

&lt;p&gt;My prefered theme is &lt;a href="https://github.com/romkatv/powerlevel10k#oh-my-zsh" rel="noopener noreferrer"&gt;powerlevel10k&lt;/a&gt;, yup it’s over nine thousand! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FMeJrynw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FMeJrynw.gif" alt="over nine thousand!"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;P10k is a feature-rich theme which has a lot of eye candy, it is very customizable and even has a wizard to help with the first config. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbowsak7ylkggdb37spo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzbowsak7ylkggdb37spo.png" alt="powerlevel10k different styles"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To install it find the current theme on your config and set it to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;ZSH_THEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"powerlevel10k/powerlevel10k"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then clone the repo into your &lt;code&gt;oh-my-zsh&lt;/code&gt; themes folder. Don’t forget to source the new config!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
git clone &lt;span class="nt"&gt;--depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 https://github.com/romkatv/powerlevel10k.git &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/themes/powerlevel10k

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to checkout &lt;a href="https://github.com/unixorn/awesome-zsh-plugins" rel="noopener noreferrer"&gt;Zsh's Awesome List&lt;/a&gt; for more.&lt;/p&gt;

&lt;h2&gt;
  
  
  NeoVIM
&lt;/h2&gt;

&lt;p&gt;NeoVim was released in 2014 as a fork of VIM that adds support for Lua. Just like its predecessor, there is quite the learning curve, but the payoff as a keyboard-first editor is truly rewarding. You have endless options to customize your setup and I encourage you to start by changing individual things to your liking (like tabs vs spaces) and to make a custom configuration of your own. Lua is already popular as a systems language so it was a good replacement for vimscript and it makes it easier to write plugins in comparison which means there is a good selection of plugins available for Neovim. Its easy to get option paralysis with the vast amount of customization and plugins, so there’s popular configurations of neovim that put together a nice UI with modern IDE functionalities and we can start with those like &lt;a href="https://astronvim.com/" rel="noopener noreferrer"&gt;AstroNvim&lt;/a&gt; and &lt;a href="https://nvchad.com/" rel="noopener noreferrer"&gt;NvChad&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Mtgo-nP_r8Y" rel="noopener noreferrer"&gt;&lt;br&gt;
  &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.ytimg.com%2Fvi%2FMtgo-nP_r8Y%2Fmaxresdefault.jpg"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to install a custom config you’re going to (you guessed it) clone the repository into the config folder and run &lt;code&gt;nvim&lt;/code&gt; to load the new config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://github.com/AstroNvim/AstroNvim ~/.config/nvim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://github.com/NvChad/NvChad ~/.config/nvim 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are switching between configs it is recommended to make a backup of your current config by running the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; ~/.config/nvim ~/.config/nvim.bak
&lt;span class="nb"&gt;mv&lt;/span&gt; ~/.local/share/nvim ~/.local/share/nvim.bak
&lt;span class="nb"&gt;mv&lt;/span&gt; ~/.local/state/nvim ~/.local/state/nvim.bak
&lt;span class="nb"&gt;mv&lt;/span&gt; ~/.cache/nvim ~/.cache/nvim.bak
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The basic plugins will be downloaded on the first run using &lt;a href="https://github.com/folke/lazy.nvim" rel="noopener noreferrer"&gt;Lazy&lt;/a&gt;, a package manager for Neovim that loads only the necessary plugins as you use them. Once it's done you should be looking at a full-fledged IDE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FCEHh02Y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FCEHh02Y.png" alt="final setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are some &lt;em&gt;quality-of-life&lt;/em&gt; improvements I like to add to my setup in order to have Neovim across the whole system. First I update the global editor settings for git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config —global core.editor nvim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lot of things on the command line default to &lt;code&gt;vi&lt;/code&gt; as their editor, so I like to alias it to &lt;code&gt;nvim&lt;/code&gt; to make sure I get a consistent experience&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;vi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;“nvim”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sometimes you want to edit something that requires privileged access and you run &lt;code&gt;sudo nvim&lt;/code&gt; only to be surprised with the default config. This is because nvim loads config from the user's home folder and that context changes when you run something as root. To fix this you can run &lt;code&gt;sudo&lt;/code&gt; with option &lt;code&gt;-E&lt;/code&gt; to include the current environment variables. Add it to your &lt;code&gt;.zshrc&lt;/code&gt; as a &lt;em&gt;quality-of-life&lt;/em&gt; improvement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias sudo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;“sudo &lt;span class="nt"&gt;-E&lt;/span&gt;”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to checkout &lt;a href="https://github.com/rockerBOO/awesome-neovim" rel="noopener noreferrer"&gt;Neovim's Awesome List&lt;/a&gt; for more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Having a nice environment helps when you're spending time on the command-line. It took me a while to figure out that you could do so much with CLI applications. I hope that this becomes the starting point of your command-line journey. Let me know if you have any other utilities I can add to my CLI setup on the comments! &lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;If you want to take your SSH to the next level I highly recommend you read &lt;a href="https://carlosbecker.com/posts/ssh-tips-and-tricks/" rel="noopener noreferrer"&gt;Carlos Becker's SSH Tips and Tricks&lt;/a&gt; blog post.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Enchula Mi Consola</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Tue, 19 Dec 2023 17:20:21 +0000</pubDate>
      <link>https://forem.com/josemunoz/enchula-mi-consola-5d70</link>
      <guid>https://forem.com/josemunoz/enchula-mi-consola-5d70</guid>
      <description>&lt;p&gt;&lt;em&gt;disponible en &lt;a href="https://dev.to/josemunoz/pimp-your-cli-3i5e"&gt;ingles&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Como desarrollador, la consola (o terminal) es una de las herramientas mas se usan a lo largo de tu carrera. Puede que sea intimidante adentrarse al mundo de las herramientas de consola pero es tambien una de las mejores experiencias que uno puede tener. En este articulo quiero mostrarles mi propia configuración para terminal. Esta basada en las 3 tecnologias que me gusta llamarles la "santísima trinidad" de la terminal: &lt;a href="https://github.com/tmux/tmux/wiki"&gt;TMUX&lt;/a&gt;, &lt;a href="https://www.zsh.org/"&gt;ZSH&lt;/a&gt;, &amp;amp; &lt;a href="https://neovim.io/"&gt;Neovim&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisitos:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Linux, MacOS, or WSL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Una fuente bonita de &lt;a href="https://www.nerdfonts.com/font-downloads"&gt;NerdFont&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Un emulador de terminal decente (i.e: &lt;a href="https://iterm2.com/"&gt;iterm2&lt;/a&gt;, &lt;a href="https://alacritty.org/"&gt;alacritty&lt;/a&gt;, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;El equivalente a &lt;code&gt;apt install zsh tmux neovim&lt;/code&gt; en tu sistema, yo voy a usar Debian.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TMUX
&lt;/h2&gt;

&lt;p&gt;La primera piedra en la experience de consola tiene que ser el multiplexor de terminal: &lt;code&gt;tmux&lt;/code&gt;. &lt;br&gt;
En pocas palabras &lt;code&gt;tmux&lt;/code&gt; te permite separar tu terminal en paneles, ventanas, o sesiones. ¿Alguna vez te has conectado a traves de SSH a un servidor para correr un proceso largo y el salva pantallas te mato la sesión? Tmux te mantiene la sesion corriendo aun si la conexion SSH se corta! En cualquier momento podes re-abrir la sesion previa y es como si nada hubiese pasado.&lt;/p&gt;

&lt;p&gt;Hay una gran comunidad que hace temas, plugins, y diferentes utilidades basadas en Tmux. Les recomiendo leer &lt;a href="https://tmuxcheatsheet.com/"&gt;tmux cheat sheet&lt;/a&gt; para familiarizarse con las funcionalidad y las combinaciones de teclas. Y este es solo la punta del iceberg, hay tantas cosas que probar. Los animo a que investiguen mas por su parte y configuren todo a su gusto ya que la experiencia que viene por defecto no es muy buena.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s8cKea_G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/LLIs0Cb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s8cKea_G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/LLIs0Cb.png" alt="tmux por defecto" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lo primero es crear un archivo de configuración corriendo &lt;code&gt;nvim ~/.tmux.conf&lt;/code&gt; y una de las mejoras que me gusta hacer inmediatamente es cambiar el indice a base 1 ya que hace mas comodo navegar pestañas con el teclado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# start windows, sessions, and panes with 1&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; base-index 1
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pane-base-index 1
set-window-option &lt;span class="nt"&gt;-g&lt;/span&gt; pane-base-index 1
set-option &lt;span class="nt"&gt;-g&lt;/span&gt; renumber-windows on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tmux usa una combinación de teclas para llamar las funciones, y por defecto esto siempre empieza con &lt;code&gt;Ctrl + b&lt;/code&gt; pero no me parece muy comodo, asi que yo cambio la combinación lider a &lt;code&gt;Ctrl + Space&lt;/code&gt; que se me hace mas fácil de hacer de manera constante.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# change prefix&lt;/span&gt;
unbind C-b
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; prefix C-Space
&lt;span class="nb"&gt;bind &lt;/span&gt;C-Space send-prefix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por ultimo, algo que me parece que debería ser así por defecto es que cuando abra un panel nuevo me abra la sesion en donde estaba originalmente y no en la raiz.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="c"&gt;# split in cwd&lt;/span&gt;
 &lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; split-window &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"#{pane_current_path}"&lt;/span&gt;
 &lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt; split-window &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"#{pane_current_path}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con esto pueden ir modificando y añadiendole a esta configuración a medida vayan usando tmux para hacer su propia configuración. Pero para poder sacarle bien el jugo a &lt;code&gt;tmux&lt;/code&gt; hay que aprovechar los &lt;em&gt;plugins&lt;/em&gt; a traves de TPM (Tmux Plugin Manager). Para instalar TPM se necesita clonar el repositorio dentro de la carpeta de plugins de tmux&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ponerlo en la lista de plugins en la configuración&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @plugin &lt;span class="s1"&gt;'tmux-plugins/tpm'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y luego añadir estas lineas de codigo al final del archivo&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)&lt;/span&gt;
 run &lt;span class="s1"&gt;'~/.tmux/plugins/tpm/tpm'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Les puedo recomendar tambien &lt;code&gt;tmux-plugins/tmux-sensible&lt;/code&gt; y &lt;code&gt;catppuccin/tmux&lt;/code&gt; para tener mejor funcionalidad y estetica. Al final la configuración les debe quedar así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="c"&gt;# List of plugins&lt;/span&gt;
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @plugin &lt;span class="s1"&gt;'catppuccin/tmux'&lt;/span&gt;
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @plugin &lt;span class="s1"&gt;'tmux-plugins/tpm'&lt;/span&gt;
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @plugin &lt;span class="s1"&gt;'tmux-plugins/tmux-sensible'&lt;/span&gt;

 &lt;span class="c"&gt;# split in cwd&lt;/span&gt;
 &lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; split-window &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"#{pane_current_path}"&lt;/span&gt;
 &lt;span class="nb"&gt;bind&lt;/span&gt; &lt;span class="s1"&gt;'%'&lt;/span&gt; split-window &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"#{pane_current_path}"&lt;/span&gt;

 &lt;span class="c"&gt;# start windows, sessions, and panes with 1&lt;/span&gt;
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; base-index 1
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pane-base-index 1
 set-window-option &lt;span class="nt"&gt;-g&lt;/span&gt; pane-base-index 1
 set-option &lt;span class="nt"&gt;-g&lt;/span&gt; renumber-windows on

 &lt;span class="c"&gt;# change prefix&lt;/span&gt;
 unbind C-b
 &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; prefix C-Space
 &lt;span class="nb"&gt;bind &lt;/span&gt;C-Space send-prefix

 &lt;span class="c"&gt;# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)&lt;/span&gt;
 run &lt;span class="s1"&gt;'~/.tmux/plugins/tpm/tpm'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si no has corrido todavía &lt;code&gt;tmux&lt;/code&gt; en la consola, la nueva configuración va a cargar automaticamente. Para actualizar la configuración estando ya dentro de tmux basta con correr &lt;code&gt;tmux source-file ~/.tmux.conf&lt;/code&gt; para actualizar la configuración y los plugins se instalan con &lt;code&gt;Shift + I&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xcLXS4WP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/fv9TlyP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xcLXS4WP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/fv9TlyP.png" alt="not too shabby" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dependiendo de la fuente que uses, habra que ajustar el tamaño de la letra, muchas configuraciónes asumen que usas &lt;code&gt;16&lt;/code&gt; o mas. Si alguno de los plugins no se instala bien, siempre se puede instalar manualmente clonandolo a la carpeta de plugins como lo hicimos para instalar &lt;code&gt;tpm&lt;/code&gt;. Hay mas recursos en: &lt;a href="https://github.com/rothgar/awesome-tmux"&gt;Tmux's Awesome list&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Z Shell
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;zsh&lt;/code&gt; (tambien conocido como ZSHell) es una alternativa a &lt;code&gt;bash&lt;/code&gt; (tambien conocido como "Bourne-Again SHell"). En funcionlidad básica hacen lo mismo, pero &lt;code&gt;zsh&lt;/code&gt; tiene mucha mas funcionalidad sobre lo que se puede hacer con bash, y al igual que TMUX, hay un gran ecosistema con plugins, temas, y mas. Cuando corras &lt;code&gt;zsh&lt;/code&gt; por primera vez, no va a hacer cambiado mucho, pero con los plugins adecuados &lt;code&gt;zsh&lt;/code&gt; puede convertirse en tu mejor amigo en la terminal. Para empezar vamos a instalar &lt;a href="https://ohmyz.sh"&gt;oh-my-zsh&lt;/a&gt;, un framework basado en &lt;code&gt;zsh&lt;/code&gt; que administra configuraciones, temas, plugins, y mas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez completado el instalador vamos a tener un nuevo archivo de configuración llamado &lt;code&gt;.zshrc&lt;/code&gt; en la carpeta raíz,&lt;br&gt;
si lo editamos con &lt;code&gt;nvim ~/.zshrc&lt;/code&gt; podemos ver que ya tiene bastantes secciones con comentarios y varias opciones ya configuradas. Les puedo recomendar el plugin &lt;code&gt;zsh-autosuggestion&lt;/code&gt; que hace que la terminal te de autocomplete basado en tu historial. Para instalarlo hay que agregarlo a la lista de plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt; 
    &lt;span class="c"&gt;# other plugins...&lt;/span&gt;
    zsh-autosuggestions
&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;hay que clonar el repositorio a la carpeta de plugins de &lt;code&gt;oh-my-zsh&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-autosuggestions &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/plugins/zsh-autosuggestions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y por ultimo hay que cargar la nueva configuración corriendo &lt;code&gt;source ~/.zshrc&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Mi tema preferido para &lt;code&gt;oh-my-zsh&lt;/code&gt; es &lt;a href="https://github.com/romkatv/powerlevel10k#oh-my-zsh"&gt;powerlevel10k&lt;/a&gt;, asi es, mas de nueve mil!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nlGvWtY4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://i.imgur.com/MeJrynw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nlGvWtY4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://i.imgur.com/MeJrynw.gif" alt="mas de nueve mil" width="352" height="288"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Viene con un instalador que te ayuda a configurar paso a paso cada opcion del tema, con muchos iconos, información y colores. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mRvNVIX8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbowsak7ylkggdb37spo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mRvNVIX8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbowsak7ylkggdb37spo.png" alt="powerlevel10k different styles" width="765" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para instalarlo hay que clonar el repositorio a la carpeta de temas de &lt;code&gt;oh-my-zsh&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
git clone &lt;span class="nt"&gt;--depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 https://github.com/romkatv/powerlevel10k.git &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/themes/powerlevel10k

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;hay que cambiar el tema en &lt;code&gt;.zshrc&lt;/code&gt; y recargar la configuración.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;ZSH_THEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"powerlevel10k/powerlevel10k"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hay mas recursos en: &lt;a href="https://github.com/unixorn/awesome-zsh-plugins"&gt;Zsh's Awesome List&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  NeoVIM
&lt;/h2&gt;

&lt;p&gt;Neovim fue lanzado en 2014 como un fork de Vim que lo extiende con soporte para Lua. Lua ya es un lenguaje establecido en el ambito del desarrollo de sistemas linux, lo que lo hace un reemplazo ideal para vimscript lo que hace mas facil para la comunidad que hace plugins. Al igual que Vim, no es facil acostumbrarse a usar Neovim, pero el cambio a trabajar principalmente con el teclado es lo mas productivo que se puede ser con un editor de texto. Inclusive, los editores modernos tienen plugins para poder usar configuraciones de teclado estilo VIM, asi que una vez que se aprende este modo de trabajo se puede traducir a otros editores facilmente.&lt;/p&gt;

&lt;p&gt;Hay miles de opciones para configurar en este editor y hacerlo tan util como VSCode. Podemos empezar con opciones basicas como tabs o espacios e ir haciendo una configuración personalizada. Es facil paralizarse con tantas opciones que aprender, pero la comunidad tiene varias configuraciones populares para tener una buena funcionalidad e interfaz sin mucho que hacer como &lt;a href="https://astronvim.com/"&gt;AstroNvim&lt;/a&gt; y &lt;a href="https://nvchad.com/"&gt;NvChad&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=Mtgo-nP_r8Y"&gt;&lt;br&gt;
  &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kKxH9X69--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/Mtgo-nP_r8Y/maxresdefault.jpg" width="800" height="450"&gt;&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para instalar una configuración basta con clonar el repositorio a la carpeta de configuración de Neovim&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://github.com/AstroNvim/AstroNvim ~/.config/nvim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ó&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 https://github.com/NvChad/NvChad ~/.config/nvim 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al cambiar de configuración hay que hacer los siguientes respaldos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv&lt;/span&gt; ~/.config/nvim ~/.config/nvim.bak
&lt;span class="nb"&gt;mv&lt;/span&gt; ~/.local/share/nvim ~/.local/share/nvim.bak
&lt;span class="nb"&gt;mv&lt;/span&gt; ~/.local/state/nvim ~/.local/state/nvim.bak
&lt;span class="nb"&gt;mv&lt;/span&gt; ~/.cache/nvim ~/.cache/nvim.bak
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cuando abrís &lt;code&gt;nvim&lt;/code&gt; la primera vez despues de cambiar la configuración se van a instalar los plugins basicos con &lt;a href="https://github.com/folke/lazy.nvim"&gt;Lazy&lt;/a&gt; el manejador de paquetes para Neovim que carga los plugins a medida se van necesitando.&lt;br&gt;
Una vez terminada la instalación el editor se ve como un IDE completo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A5qYU9OQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/CEHh02Y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A5qYU9OQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/CEHh02Y.png" alt="final setup" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algunas &lt;a href="https://www.youtube.com/watch?v=rpDVBZqCXXE&amp;amp;t=8s"&gt;cosirijillas&lt;/a&gt; que me hacen la vida mas facil es configurar mi editor global de git que sea &lt;code&gt;nvim&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config —global core.editor nvim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Muchos programas usan &lt;code&gt;vi&lt;/code&gt; como el editor por defecto, asi que una manera de tomar un atajo y cambiarlos todos es hacerle un alias apuntando a &lt;code&gt;nvim&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;vi&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;“nvim”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A veces hay que editar un archivo con privilegios y al correr &lt;code&gt;sudo nvim&lt;/code&gt; te aparece la configuración inicial sin temas ni nada. Esto es porque Neovim carga su configuración con las variables de ambiente del usuario, para pasarlas con sudo se usa la opción &lt;code&gt;-E&lt;/code&gt;. Se le puede hacer un alias para hacerte la vida mas facil.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias sudo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;“sudo &lt;span class="nt"&gt;-E&lt;/span&gt;”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hay mas recursos en: &lt;a href="https://github.com/rockerBOO/awesome-neovim"&gt;Neovim's Awesome List&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Cuando vas a pasar mucho tiempo usando un programa es importante que tenga buena interfaz y funcionalidad. Aventurarse a la consola puede ser intimidante pero con una buena interfaz muchas cosas se vuelven digeribles.&lt;br&gt;
Comenten sus recomendaciones de herramientas de consola, les agradezco de antemano.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra
&lt;/h2&gt;

&lt;p&gt;Si queres enchular tu SSH también, te recomiendo los &lt;a href="https://carlosbecker.com/posts/ssh-tips-and-tricks/"&gt;SSH Tips and Tricks&lt;/a&gt; en el blog de Carlos Becker&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>español</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Git Conflict resolution made simple</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Sat, 03 Jul 2021 19:58:37 +0000</pubDate>
      <link>https://forem.com/josemunoz/git-conflict-resolution-made-simple-1jac</link>
      <guid>https://forem.com/josemunoz/git-conflict-resolution-made-simple-1jac</guid>
      <description>&lt;p&gt;Have you ever tried to merge a Pull Request and it seems to have a conflict on file that you changed intentionally?&lt;/p&gt;

&lt;p&gt;When it comes to conflict resolution, it can be a painful experience sometimes, even when you all you’re doing is accepting the incoming changes.&lt;/p&gt;

&lt;p&gt;Git can be intimidating sometimes, and most people tend to prefer a GUI to manage their versioning and source control. But sometimes using the CLI can be the better option.&lt;/p&gt;

&lt;p&gt;I’m the kind of weird that likes to do things on the CLI when possible, so I have a small life-hack that has saved me so much time during conflict resolution.&lt;/p&gt;

&lt;p&gt;In this example we are going to imagine we are trying to make a PR from &lt;code&gt;development&lt;/code&gt; to &lt;code&gt;staging&lt;/code&gt;, once you’ve created the PR you notice there is a few conflicts and the PR can’t be merged right away. Don’t panic, we can fix this with the power of the CLI! &lt;/p&gt;

&lt;p&gt;Make sure you have the latest version of your destination branch (in this case &lt;code&gt;staging&lt;/code&gt;) checked out on your local environment.&lt;/p&gt;

&lt;p&gt;Go to your source branch (in this case its &lt;code&gt;development&lt;/code&gt;) and run: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;git pull origin staging —strategy ours&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will accept the history of the source branch over the destination branch and resolve the conflicting files  for you. Now you can safely push the resolution to your remote and the PR you submitted should now be mergeable.&lt;/p&gt;

&lt;p&gt;The CLI can be an intimidating place, but sometimes it can be the fastest way to achieve a task. Merge strategies are one of the most powerful options you can use from the git source control system, and there’s many more strategies that allow you to get even more flexibility from these options, I’ll leave a couple of links below where you can learn more about git merge strategies, thanks for reading!&lt;/p&gt;

&lt;p&gt;Links: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/docs/merge-strategies"&gt;https://git-scm.com/docs/merge-strategies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.atlassian.com/git/tutorials/using-branches/merge-strategy"&gt;https://www.atlassian.com/git/tutorials/using-branches/merge-strategy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>git</category>
      <category>productivity</category>
      <category>lifehack</category>
    </item>
    <item>
      <title>WebRTC and React-Native</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Tue, 12 May 2020 05:24:04 +0000</pubDate>
      <link>https://forem.com/josemunoz/webrtc-and-react-native-52pi</link>
      <guid>https://forem.com/josemunoz/webrtc-and-react-native-52pi</guid>
      <description>&lt;p&gt;It is a strange time to be a developer, with most countries going into lock-down, the need for communication technologies has sparked.&lt;/p&gt;

&lt;p&gt;One of the technologies that has been readily available for web developers to create this solutions is the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API" rel="noopener noreferrer"&gt;WebRTC API&lt;/a&gt; which web browsers have implemented &lt;a href="https://caniuse.com/#search=webrtc" rel="noopener noreferrer"&gt;almost across the board&lt;/a&gt;. The next step for these kind of technologies is to make a jump to mobile, either with PWA or a Native application. The former could be considered already viable but the features that the public expects with video apps has only become more and more complex.&lt;/p&gt;

&lt;p&gt;For React-Native Developers the WebRTC solutions have historically had a high barrier of entry. Expo has not yet (as of May 2020) integrated the &lt;code&gt;react-native-webrtc&lt;/code&gt; native module into their framework despite having &lt;a href="https://expo.canny.io/feature-requests/p/webrtc" rel="noopener noreferrer"&gt;demand for it&lt;/a&gt;. Of course it is not Expo's responsibility to implement the things that we claim for, that is not how open source works.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to have WebRTC on your React-Native project you &lt;em&gt;must&lt;/em&gt; go with the official &lt;code&gt;npx react-native&lt;/code&gt; CLI. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Setup
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;react-native-webrtc&lt;/code&gt;'s documentation has been neglected by the community, as it is one of the least favourite parts of a developer's tasks, but an essential task nonetheless. You can follow the installation guides for both &lt;a href="https://github.com/react-native-webrtc/react-native-webrtc/blob/master/Documentation/AndroidInstallation.md" rel="noopener noreferrer"&gt;Android&lt;/a&gt; and &lt;a href="https://github.com/react-native-webrtc/react-native-webrtc/blob/master/Documentation/iOSInstallation.md" rel="noopener noreferrer"&gt;iOS&lt;/a&gt; but in this post I will try to guide you through a much much simpler process that is made possible thanks to the auto-linking features that came with &lt;code&gt;react-native@0.60&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting From Scratch
&lt;/h2&gt;

&lt;p&gt;My purpose here is to lower the entrance barrier for people to explore WebRTC technologies, for this reason I will approach this from the perspective of a greenfield project, the typical &lt;code&gt;npx react-native init myApp&lt;/code&gt; will do.&lt;/p&gt;

&lt;p&gt;Once you have a boilerplate project we need add &lt;code&gt;react-native-webrtc&lt;/code&gt; as a dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; react-native-webrtc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;From here on our next step is going to be to integrate &lt;code&gt;react-native-webrtc&lt;/code&gt; with each platform. &lt;/p&gt;

&lt;p&gt;The high-level overview of this setup is: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;glue the native module to each platform&lt;/li&gt;
&lt;li&gt;ask for the necessary permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;I highly recommend you use a physical device to debug. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  iOS
&lt;/h2&gt;

&lt;p&gt;The iOS integration is the simplest one because &lt;em&gt;cocoapods&lt;/em&gt; will do most of the legwork.&lt;/p&gt;

&lt;p&gt;On the project's root, locate the podfile under &lt;code&gt;./ios/podfile&lt;/code&gt;, the first line is where we set the platform version, we will change this to version 10: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;platform :ios, '10.0'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;On the podfile, locate your project's target pods and add the following line:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pod 'react-native-webrtc', :path =&amp;gt; '../node_modules/react-native-webrtc'&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Once you've made these changes save everything and open a terminal on your project's root and run &lt;code&gt;npx pod-install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now that you've completed the first step, it's time to ask (nicely) for some permissions, locate the &lt;code&gt;info.plist&lt;/code&gt; file under &lt;code&gt;./ios/myApp&lt;/code&gt; and add the following lines after the first &lt;code&gt;&amp;lt;dict&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;NSCameraUsageDescription&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Camera Permission&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;NSMicrophoneUsageDescription&lt;span class="nt"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;Microphone Permission&lt;span class="nt"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And that completes the iOS setup portion, easy right? If you only care about the iOS platform then all you need to do now is to run the project on an iPhone.&lt;/p&gt;
&lt;h2&gt;
  
  
  Android
&lt;/h2&gt;

&lt;p&gt;The setup process for Android is inherently more complex but we will try to keep it as simple as possible. &lt;/p&gt;

&lt;p&gt;On the project's root locate graddle settings under &lt;code&gt;./android/settings.graddle&lt;/code&gt; and replace the last line with the following:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;include ':WebRTCModule', ':app'
project(':WebRTCModule').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webrtc/android')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the ideal world we would add permissions and be done with it, but bear with me &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FzlEH6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FzlEH6.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Locate the project's graddle properties under &lt;code&gt;./android/graddle.properties&lt;/code&gt; and add the following line: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;android.enableDexingArtifactTransform.desugaring=false&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Locate Android's build properties under &lt;code&gt;./android/build.graddle&lt;/code&gt; and look for the buildscript dependencies, make sure the tooling is on version &lt;em&gt;3.5.2&lt;/em&gt;: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;classpath("com.android.tools.build:gradle:3.5.2")&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;On different build properties located under &lt;code&gt;./android/app/build.graddle&lt;/code&gt; locate the dependencies and add the following line within its scope: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;compile project(':WebRTCModule')&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Go into the project's Android &lt;code&gt;MainApplication.java&lt;/code&gt; located at &lt;code&gt;./android/app/src/java/com/all/the/things/&lt;/code&gt; and add the namespace for &lt;code&gt;react-native-webrtc&lt;/code&gt; by adding the following import:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.oney.WebRTCModule.WebRTCModulePackage&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally we can ask (nicely) for permissions, locate the project's &lt;code&gt;AndroidManifest.xml&lt;/code&gt; under &lt;code&gt;./android/app/src/main&lt;/code&gt; and add the permissions on the same scope as the &lt;code&gt;&amp;lt;application&amp;gt;&lt;/code&gt; tag with the following lines:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt; &lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.INTERNET"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.ACCESS_NETWORK_STATE"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.MODIFY_AUDIO_SETTINGS"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.RECORD_AUDIO"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.WAKE_LOCK"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.WRITE_EXTERNAL_STORAGE"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.CAMERA"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;uses-feature&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.hardware.camera"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="nt"&gt;&amp;lt;uses-feature&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.hardware.camera.autofocus"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once this is in place we are ready to run the project on a device for testing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;react-native-webrtc&lt;/code&gt;'s installation guides while not completely up-to-date, they have valuable information that is still useful for some people. I've made a template application that has been setup for WebRTC broadcasting and includes a simple socket implementation of a signaling server (required to start the Peer Connections), The sample itself is written using hooks and its linked below:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jdmg94" rel="noopener noreferrer"&gt;
        jdmg94
      &lt;/a&gt; / &lt;a href="https://github.com/jdmg94/react-native-webrtc-example" rel="noopener noreferrer"&gt;
        react-native-webrtc-example
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An example app for `react-native-webrtc` using React 0.60 or newer
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;What do you think about video broadcasting technologies? What other uses could Real Time Communication technologies be applied to? Have you baked bread during this quarantine yet? Thanks for reading!&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>webrtc</category>
    </item>
    <item>
      <title>Converting JSON with Elm</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Tue, 10 Dec 2019 06:32:50 +0000</pubDate>
      <link>https://forem.com/josemunoz/converting-json-with-elm-3pci</link>
      <guid>https://forem.com/josemunoz/converting-json-with-elm-3pci</guid>
      <description>&lt;p&gt;&lt;em&gt;Photo by TimJ on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I've been getting into &lt;a href="//elm-lang.org"&gt;Elm&lt;/a&gt; in the last few weeks. I feel like I've been getting too comfortable with React and I wanted to get into something that was more &lt;a href="https://en.wikipedia.org/wiki/Functional_programming" rel="noopener noreferrer"&gt;&lt;em&gt;Functional&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So far I have been enjoying my experience, the concepts that the language encourages are fascinating to me, a lot of them I was already using in Javascript and it made my code better in a way that was hard to explain to my peers.&lt;/p&gt;

&lt;p&gt;Today I want to tackle a simple task, something that literally every web application does to a certain degree, I want to call an API and present some of the data fetched. I'm using &lt;a href="https://randomuser.me" rel="noopener noreferrer"&gt;Random User API&lt;/a&gt; which is a free service that is consumed as REST. The final product can be found  &lt;a href="https://jdmg94.github.io/elm-user-card-app/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the source  is linked below:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jdmg94" rel="noopener noreferrer"&gt;
        jdmg94
      &lt;/a&gt; / &lt;a href="https://github.com/jdmg94/elm-user-card-app" rel="noopener noreferrer"&gt;
        elm-user-card-app
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A simple elm application that fetches user data and presents a social card.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;elm-user-card-app&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;A simple elm application that fetches user data and presents a social card. this is an exercise on parsing and transforming JSON structures we get from services that we may not have control over.
it uses tailwind as its css framework, you can generate styles via &lt;code&gt;yarn styles&lt;/code&gt; you can open a hot-reloading dev server via &lt;code&gt;yarn dev&lt;/code&gt; it takes the same options as &lt;code&gt;elm make&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/jdmg94/elm-user-card-app" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; &lt;br&gt;
I am still learning Elm, I don't think I'm qualified to teach anyone about it, however these are my thoughts and experience with it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I won't be able to take advantage of &lt;strong&gt;&lt;em&gt;all&lt;/em&gt;&lt;/strong&gt; the data that this nice API provides and make some complicated profile builder, I would like to just show a card with a name, a picture, a handle maybe. But the response we get is rather extense:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"gender"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"female"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mrs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lucy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"last"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cruz"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"street"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5454&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fincher Rd"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bundaberg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New South Wales"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Australia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"postcode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6462&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"coordinates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-87.1460"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"149.9745"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"timezone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"offset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+1:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Brussels, Copenhagen, Madrid, Paris"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lucy.cruz@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"login"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"92878432-b5ee-4539-92ae-b3bc44880832"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"whitepanda288"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"padres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"salt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"t34unJhk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"md5"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"6bbd926216c8ba43e619b6a33c3b0fa0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"sha1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"f2beb504929ef81d8846d8007c2ef72f5ff8f574"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"sha256"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"d4671f10b485c7e8531d70d726e1e07be4a68eb4b75c2589262abb3f36d6aefe"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dob"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1983-02-22T00:20:05.732Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"registered"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2015-08-05T13:35:58.976Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"02-5505-2105"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cell"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0430-474-187"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TFN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"251930914"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"picture"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"large"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://randomuser.me/api/portraits/women/29.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"medium"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://randomuser.me/api/portraits/med/women/29.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"thumbnail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://randomuser.me/api/portraits/thumb/women/29.jpg"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AU"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"info"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"seed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"001e6b8cb1b5ecfa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.3"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to get what we need out of this large response object we need to understand &lt;a href="https://guide.elm-lang.org/types/type_aliases.html" rel="noopener noreferrer"&gt;&lt;em&gt;decoders&lt;/em&gt;&lt;/a&gt; and &lt;a href="https://guide.elm-lang.org/types/type_aliases.html" rel="noopener noreferrer"&gt;&lt;em&gt;type aliases&lt;/em&gt;&lt;/a&gt;. Decoders are Elm's way of handling JSON data, they provide instructions on how to handle a JSON input. Type Aliases are a schema of the data we intend on getting out of this bunch. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;note:&lt;/strong&gt;&lt;br&gt;
I'll leave the boilerplate aside for all examples, however all examples should be interpreted as living in the same file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;first, let's define the data we want to receive on the view, the &lt;em&gt;ideal scenario&lt;/em&gt; from the perspective of a view function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="k"&gt;alias&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;firstName&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lastName&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;picture&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now that we have our type alias, we can define a model, very simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Loading&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kt"&gt;Fail&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Success&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;Success&lt;/code&gt; is encapsulated with our &lt;code&gt;User&lt;/code&gt; type alias, elm supports the concept of &lt;a href="https://guide.elm-lang.org/core_language.html#tuples" rel="noopener noreferrer"&gt;tuples&lt;/a&gt; that allows us to bind 2 or 3 types as a single element, parenthesis are optional.&lt;/p&gt;

&lt;p&gt;We'll come back to types, however, for now I want to transition to &lt;em&gt;Decoders&lt;/em&gt;, since we are working on a hypothetical &lt;em&gt;ideal&lt;/em&gt; scenario with our declarations above, we need to transform our JSON data. The first thing we're going to do is to pick the fields from the first result item, where the data resides. Type aliases are also functions, and they are initialized with their paths as curried parameters.&lt;br&gt;
If your schema is rather complicated you may want to look into &lt;code&gt;Json.Decode.Pipeline&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;userDecoder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Decoder&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;
&lt;span class="n"&gt;userDecoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;map4&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;first"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;login"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;picture"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;large"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we're declaring &lt;code&gt;userDecoder&lt;/code&gt; twice, the first one is the function's &lt;em&gt;prototype declaration&lt;/em&gt; which is going to tell the compiler what to expect from this function. The latter is the function's body, and in it we want to use the &lt;code&gt;map&lt;/code&gt; function to return the &lt;strong&gt;4&lt;/strong&gt; fields we need to initialize a &lt;code&gt;User&lt;/code&gt; record, remember to send them in the order of declaration.&lt;/p&gt;

&lt;p&gt;Now that we have the &lt;code&gt;userDecoder&lt;/code&gt; ready we can start thinking about how to get there from the real world, we need to make a request to the server and then unpack the results object before we can use our &lt;code&gt;userDecoder&lt;/code&gt;, in order to achieve that we will write another decoder to unwrap the results from our non-existent request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;resultsDecoder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Decoder&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;
&lt;span class="n"&gt;resultsDecoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;results"&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="n"&gt;userDecoder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This decoder is also going to return a User record, but it is going to help us unwrap the layers we don't really need before extracting our data.&lt;br&gt;
In order to accomplish this we're going to use the &lt;code&gt;userDecoder&lt;/code&gt; we declared a moment ago, Decoders are just functions and being able to compose them like this really helps splitting tasks like this very easy.&lt;/p&gt;

&lt;p&gt;Alright, I think we've done well so far with our decoders, before we can make our request I need another type that will allow me to update the application's state, and I want to give my users the option to &lt;em&gt;refetch&lt;/em&gt; as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anotherOne&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;gotUser&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Result&lt;/span&gt; &lt;span class="kt"&gt;Error&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of these enumerations of type &lt;code&gt;Msg&lt;/code&gt; will serve as a loading flag, another one will handle when the task is done. Notice the latter is a &lt;em&gt;touple&lt;/em&gt;, that as another &lt;em&gt;touple&lt;/em&gt; as its second element. With that in place let's make our request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;&lt;span class="n"&gt;getRandomProfile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
&lt;span class="n"&gt;getRandomProfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://randomuser.me/api"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expectJson&lt;/span&gt; &lt;span class="n"&gt;gotUser&lt;/span&gt; &lt;span class="n"&gt;resultsDecoder&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;get&lt;/code&gt; method of the &lt;code&gt;Http&lt;/code&gt; package, we can pass a record with 2 members, the &lt;em&gt;url&lt;/em&gt; to send the request, and what to expect from it's response, the &lt;code&gt;Http&lt;/code&gt; package has other helpful functions for this, in our case we will call &lt;code&gt;expectJson&lt;/code&gt; because that's what our decoders expect, and with that in place we can pull it together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elm"&gt;&lt;code&gt;  &lt;span class="n"&gt;browser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subscriptions&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;init&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Loading&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getRandomProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Sub&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
  &lt;span class="n"&gt;subscriptions&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Sub&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;

  &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; 
      &lt;span class="kt"&gt;AnotherOne&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Loading&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getRandomProfile&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="kt"&gt;GotUser&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; 
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; 
          &lt;span class="kt"&gt;Ok&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Success&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="kt"&gt;Err&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Fail&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Cmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Model&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Html&lt;/span&gt; &lt;span class="kt"&gt;Msg&lt;/span&gt;
  &lt;span class="n"&gt;view&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; 
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt;
      &lt;span class="kt"&gt;Loading&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loader&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
      &lt;span class="kt"&gt;Fail&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;loader&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
      &lt;span class="kt"&gt;Success&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; 
        &lt;span class="n"&gt;onTheLeft&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;roundedImage&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;picture&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;detail&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;firstName&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;subtitle&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@"&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="n"&gt;profile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;refresh&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;onClick&lt;/span&gt; &lt;span class="n"&gt;anotherOne&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Elm has the right paradigms to succeed, but for now React's roadmap is looking brighter. The advantage that Elm has over React is that React had to steer the community towards the right patterns (i.e: functional components over class components) to make concurrency work. Elm by its functional nature is already capable of concurrency, but at this point its not taking advantage of it in the way that React is, and in the future, when React Concurrent mode is released the difference is going to be accentuated. If elm wants to compete in the frontend world concurrency is going to be fundamental to its longevity, nonetheless it is an enjoyable language with the right paradigms, I think this would be a great first language for someone getting into web development.&lt;/p&gt;

</description>
      <category>elm</category>
      <category>functional</category>
      <category>webdev</category>
    </item>
    <item>
      <title>React Hooks as an Enabler for Concurrent mode</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Fri, 01 Nov 2019 20:04:09 +0000</pubDate>
      <link>https://forem.com/josemunoz/react-hooks-as-an-enabler-for-concurrent-mode-4paf</link>
      <guid>https://forem.com/josemunoz/react-hooks-as-an-enabler-for-concurrent-mode-4paf</guid>
      <description>&lt;p&gt;React Conf 2019 happened last week and we got some great content from all the speakers. However, I can't shake the feeling of walking away with last's years promise.&lt;/p&gt;

&lt;p&gt;I'm not implying that the React team has been slacking or something, there was a lot of work done to prove the concept for concurrent mode and I'm glad they're taking their time to deliver something stable and proven on the real world. I had the chance to be at this (and last year's) React Conf and talk with some of the people behind the React projects and these are just my thoughts from this experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The React That Was Promised
&lt;/h2&gt;

&lt;p&gt;Last year, Dan Abramov delivered a memorable talk titled "Beyond React 16" about concurrent rendering aka "Time slicing"&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/nLF0n9SACd4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Later that same year Jared Palmer introduced us to the benefits of concurrent rendering on his talk "Moving to React Suspense"&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/SCQgE4mTnjU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Fast Forward a full year later and this year's React Conf gives us a deep dive into Concurrent mode and how the teams at Facebook are taking advantage of it to improve initial load times and time to interactive in lower end devices through techniques like selective hydration, server-side rendering and html streaming. &lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/uXEEL9mrkAQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  But what exactly is Concurrent Mode?
&lt;/h3&gt;

&lt;p&gt;quoting the &lt;a href="https://reactjs.org/docs/concurrent-mode-intro.html#what-is-concurrent-mode"&gt;Official React Docs&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Concurrent Mode is a set of new features that help React apps stay responsive and gracefully adjust to the user’s device capabilities and network speed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In simple terms, this will allow React to manage time more efficiently by  performing several tasks at the same time in a non-blocking way. So when a component isn't ready to display yet, React will do something else instead. This will enable an array of user interactions where before we would only had a frozen loading state.&lt;/p&gt;

&lt;p&gt;With concurrent mode &lt;em&gt;fast&lt;/em&gt; devices increase in responsiveness giving a synchronous accessed data kind of feeling. In &lt;em&gt;slow&lt;/em&gt; devices, the non-blocking nature of concurrent mode would provide responsiveness even with few resources, server-side rendering should take some of the load for slow devices to render the initial view, and selective hydration would increase perceived performance by prioritizing work based on user interaction heuristics.&lt;/p&gt;

&lt;p&gt;For developers coordinating resources, data, and side-effects would become simpler, making a fluid and responsive app that scales is now easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  How is this related to hooks?
&lt;/h2&gt;

&lt;p&gt;Last year at React Conf the Hooks API was announced, and it got a lot of hype and well deserved attention, it basically out-shined the more &lt;em&gt;"experimental"&lt;/em&gt; Suspense presentations. &lt;/p&gt;

&lt;p&gt;Hooks made it easier for developers to take advantage of the functional components as more than just presentational and encouraging the transition from class-based components to functional components.&lt;/p&gt;

&lt;p&gt;Functional components enable better tree-shaking and more predictable change tracking which helped &lt;em&gt;a lot&lt;/em&gt; with the developer tooling and fast refresh, also announced in this year's conference, it enables the people working on React to take advantage of functional programming concepts that create a better developer experience and increase your application's performance.&lt;/p&gt;

&lt;p&gt;A year later hooks has taken by storm the repositories both the general public and major OSS libraries, and now that hooks has pushed functional style into the spotlight, the community is ready for the next step: Parallelism&lt;/p&gt;

&lt;h2&gt;
  
  
  It's important we think about Parallelism
&lt;/h2&gt;

&lt;p&gt;We're reaching the physical limits to which we can optimize chip design.&lt;br&gt;
year after year Intel (as market leader) has struggled to scale down their transistors, forcing them to present new products with more cores instead. These are things that the web can take advantage of, and the React team has presented the right patterns for us developers to also benefit from that without getting into all the pitfalls of traditional "multi-threading".&lt;/p&gt;

&lt;p&gt;The concepts that React has pushed have historically changed with the real world, and I think it is part of React's success.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now that the landscape has changed, React is ready to give us more tools from the functional shed, with &lt;a href="https://stackoverflow.com/questions/12788858/parallelism-in-functional-languages"&gt;parallelism&lt;/a&gt; being the focus of this year we have to consider, why is this still on the &lt;em&gt;experimental&lt;/em&gt; channel? will the third time be the charm for Concurrent mode? I'm excited to see what comes next.&lt;/p&gt;

</description>
      <category>react</category>
      <category>suspense</category>
      <category>concurrentmode</category>
      <category>reactconf</category>
    </item>
    <item>
      <title>Writing Code for Others to Read</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Mon, 10 Jun 2019 22:06:04 +0000</pubDate>
      <link>https://forem.com/josemunoz/writing-code-for-others-to-read-82b</link>
      <guid>https://forem.com/josemunoz/writing-code-for-others-to-read-82b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Most software engineers primarily focus on becoming great at writing code. And this makes perfect sense. This is an essential step to become a great engineer within a reasonably sized team.&lt;/p&gt;

&lt;p&gt;Successful companies, however, grow continuously. Sooner or later, the software engineering team will be beyond a few dozen people, where everyone can easily talk with everyone else. People will be split across different floors. New offices in different locations will be opened. Face-to-face communication starts to be insufficient. Channels like email, chat or video calls become more important. The pace of which this growth happens varies by company: for some, it takes years. For some of the really successful companies, it happens much more rapidly.&lt;/p&gt;

&lt;p&gt;-Gergely Orosz &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you get your first gig as a developer you will inevitably be reading, understanding, and maintaining other people's code. Coding is an expression of one's logical abilities, and every mind is a world of its own, so as you gain experience, you will learn to identify people by their coding style. On a small team, this is no biggie, but as people come and go this starts to become an issue. &lt;/p&gt;

&lt;p&gt;In the ideal situation, the organization maintains a &lt;a href="https://github.com/airbnb/javascript"&gt;style-guide&lt;/a&gt; and this helps to keep the code-base homogeneous, if this isn't your case, your code should express intent, tell a story, this will make bugs easier to identify and locate. there are a few of things that we can do to keep our code &lt;em&gt;clean&lt;/em&gt;. The following observations are my personal, over-simplified take on &lt;code&gt;The Clean Code&lt;/code&gt; book series by Robert C. Martin with just the right amount of empiric bias.&lt;/p&gt;

&lt;h1&gt;
  
  
  Use Meaningful Names
&lt;/h1&gt;

&lt;p&gt;Variable names should express intent, be explicit on what that variable is going to be used for. Don't be afraid of using long names, just make sure you're following the language's casing convention. Variables should be named within their context, loosely-coupled logic rarely has several resources doing the same thing, so naming things within context allows you to re-use variable names that make sense in another file. Function names should be thought of as verbs, a reaction to an event. when naming a function think about &lt;em&gt;what&lt;/em&gt; is the function going to be used for.&lt;/p&gt;

&lt;p&gt;Instead of writing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;anchor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;anchor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;download&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my download.pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;anchor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/some/resource/url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="nx"&gt;anchor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you could write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;downloadPdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;// some implementation&lt;/span&gt;
&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;downloadPdf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Currying is your friend
&lt;/h1&gt;

&lt;p&gt;Currying is the technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions, each with a single argument. Curried functions are particularly useful in the context of function composition, which allows us to create specialized &lt;a href="https://www.sitepoint.com/higher-order-functions-javascript/"&gt;higher-order functions&lt;/a&gt; that can provide more semantic sense. &lt;/p&gt;

&lt;p&gt;Instead of writing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SomeComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
      &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;somewhere-else&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you could write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SomeComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;goTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;
      &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;goTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;somewhere-else&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Comments can be functions too!
&lt;/h1&gt;

&lt;p&gt;If you're writing a large portion of logic you may feel like you need to explain what that code does, it is natural to think about leaving a comment for another collaborator to read when working around that file. Every time you find yourself writing a comment to explain the reasoning behind a portion of code, think about it as an opportunity to refactor that portion of code into its own function with a meaningful name. This doesn't mean that comments are bad, there are valid cases for comments where legacy code can't be refactored or notes for things that need to be revisited like &lt;code&gt;//#TODO: vacuum cat&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Instead of writing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myBigImperativeFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

 &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isCold&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clothes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/clothes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clothes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sweater&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
     &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clothes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sweater&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;thickness&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
       &lt;span class="nx"&gt;clothes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sweater&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/sweaters?thickness=4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;clothes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sweater&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/sweater&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;coffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/beverages/coffee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;energy&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;cofee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you could write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wearWarmSweater&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;//some implementation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getSomeCoffee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;//some implementation&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isCold&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;wearWarmSweater&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getSomeCoffee&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Keep things DRY
&lt;/h1&gt;

&lt;p&gt;Logical reduction is one of the most powerful tools on any developer's belt. The thing about code with lots of flow control is that, it is hard to detect duplicate efforts but now that your code is explicitly expressing its intent, it is easier to spot things that can be reduced and re-used. &lt;/p&gt;

&lt;p&gt;Instead of writing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rightIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0064D2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leftIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;minus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0064D2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you could write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;smallCeruleanSign&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0064D2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rightIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;smallCeruleanSign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;leftIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;smallCeruleanSign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;minus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Writing clean code makes everyone's life easier, your users will benefit of the increased productivity that having readable and understandable code will provide. Even on a personal level, clean code allows us to understand our projects 6 months down the line, it allows teams to onboard new engineers faster, and it helps spot efforts that could be optimized in a granular fashion. Let me know what you do to keep your code clean, I would love to learn a couple of tricks from the comment section.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Declarative Resource Loading with React</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Mon, 15 Apr 2019 04:38:35 +0000</pubDate>
      <link>https://forem.com/josemunoz/declarative-resource-loading-with-react-51pc</link>
      <guid>https://forem.com/josemunoz/declarative-resource-loading-with-react-51pc</guid>
      <description>&lt;p&gt;^(photo by @alexjones on unsplash.com)&lt;/p&gt;

&lt;h1&gt;
  
  
  Loading Stuff is Hard
&lt;/h1&gt;

&lt;p&gt;how many of you write the word &lt;em&gt;isLoading&lt;/em&gt; 10x a day? Often times we want to make our application responsive even in slow connections, so we have loading indicators to give the user feedback that the app is working. If you think about your application, a lot of time and energy is focused on coordinating when stuff comes in, when it comes out, and what to show the user. This is any resource our browser uses, even resources that we don't fetch explicitly like images, fonts, code, etc. impact our time to interactive and UX. In this post, we'll take a look at a few approaches to load resources in our apps and how this is going to play in the near future.&lt;/p&gt;

&lt;h1&gt;
  
  
  Code Splitting
&lt;/h1&gt;

&lt;p&gt;Code splitting is when you only send the code that’s required to load the page you are visiting, and then the rest of the code is sent to the client as the user navigates. Although there are a lot of other ways of achieving this, React has a couple of APIs which help us split the bundle into chunks of code that are grouped in the most efficient way to reduce their file size. The first API we need in order to split our application is called lazy, it is super simple, it takes a function that returns a dynamic import and then that’s a drop-in replacement for your component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fewbka5r18kuhg1mp45jt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fewbka5r18kuhg1mp45jt.png" alt="lazy example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the other API is called Suspense. Suspense helps us determine if the resources we are trying to call are available to use and displays an alternative loading state while the resource becomes available. In other words, Suspense is a declarative loading state API.&lt;/p&gt;

&lt;h1&gt;
  
  
  Data Fetching
&lt;/h1&gt;

&lt;p&gt;Look at the following example of a traditional class-based data fetching component:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6d4ua56fv60k7ijplo7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6d4ua56fv60k7ijplo7i.png" alt="class exampled"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;it initializes the state on the constructor, fetches the data on-mount, and when it renders it evaluates if there is data to present or if it's ok to display a loader fallback instead. You must be thinking, of course using hooks would make it better right?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F54qlum4imud6nyejqiem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F54qlum4imud6nyejqiem.png" alt="hooks example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With Hooks, you fetch data using effects and imperatively checking the loading state to display a loader until the resource becomes available. We reduced some boilerplate code and made it cleaner, but it is still the same process, it still imperatively decides whether to present a loader or content.&lt;/p&gt;

&lt;p&gt;Until now, we have only been able to use Suspense to load dynamic code with lazy, but in reality, we can use it for other types of resources too. You can suspend any element in your component hierarchy, if the calling resource can’t suspend the rendering of that subtree and provide a fallback it will look up the tree until it finds one that can or it errors out, it works exactly like an error boundary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmqzprzqe9fz85eg4wvvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmqzprzqe9fz85eg4wvvw.png" alt="suspense example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Suspense allows async resources to behave as if they had sync access. We don't even have a loader on our fetching component now, we just let React know that the resource ain't ready yet and Suspense will provide a fallback somewhere along the tree to wait for our resources to be ready to render.&lt;/p&gt;

&lt;p&gt;Not only does Suspense improve our DX by reducing our lines of code exponentially but it also allows for a smoother transition between loading states like when your app goes from lazy loading the code to fetching data.&lt;/p&gt;

&lt;h1&gt;
  
  
  Other Resources
&lt;/h1&gt;

&lt;p&gt;Another great example is images, sometimes our pages render and some images are missing, the requests for those resources can be on the heavier side. Let's do our new trick and load an image using Suspense.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0kvgygcg6a5dpaia1is7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0kvgygcg6a5dpaia1is7.png" alt="suspense image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, you don't have to do this yourself, &lt;a href="https://github.com/palmerhq/the-platform" rel="noopener noreferrer"&gt;the-platform&lt;/a&gt; is a nifty library that has your back with wrapped components for images and other resources that are Suspense-ready.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh17zoyqkrhvu0waolk6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh17zoyqkrhvu0waolk6z.png" alt="suspense with thumbnail"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a fallback, you could have a regular &lt;code&gt;&amp;lt;img/&amp;gt;&lt;/code&gt; tag with a lower-res thumbnail instead of a spinner and it will provide a smooth transition between the thumbnail and the full-size image.&lt;/p&gt;

&lt;h1&gt;
  
  
  Strict Mode
&lt;/h1&gt;

&lt;p&gt;So now we have a few resources loading and our application might start to feel slow if we keep that loader going, we need to decide how much are we willing to wait for each resource. I definitely need to retrieve the code and data first, but I could get away with showing a low-res thumbnail for a few seconds longer in order to deliver an almost complete UI. Suspense provides us with a second prop called &lt;code&gt;maxDuration&lt;/code&gt; and this prop allows us to specify in milis how much should it wait till it provides a fallback or content. &lt;code&gt;maxDuration&lt;/code&gt; will only work when certain conditions are met, this is where things get a little tricky. &lt;/p&gt;

&lt;p&gt;In order for React to appropriately evaluate what is going on, there should be no deprecated APIs in the suspended tree. to help us identify possible issues React exposes a tag called &lt;code&gt;StrictMode&lt;/code&gt;. Strict mode is a stable API and you can use it right now in production, nothing will break, however, if there are any deprecated APIs used within its children you will be getting errors on your browser's console.&lt;/p&gt;

&lt;h1&gt;
  
  
  Concurrent Rendering
&lt;/h1&gt;

&lt;p&gt;If you wrapped your app in strict-mode and your console is still clear, congratulations! You are now able to activate concurrent mode and start taking advantage of &lt;code&gt;maxDuration&lt;/code&gt;. But what exactly is &lt;em&gt;Concurrent mode&lt;/em&gt;? In the words of Dan Abramov:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Concurrent Mode lets React apps be more responsive by rendering component trees without blocking the main thread. It is opt-in and allows React to interrupt a long-running render (for example, rendering a new feed story) to handle a high-priority event (for example, text input or hover). Concurrent Mode also improves the user experience of Suspense by skipping unnecessary loading states on fast connections.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are 2 ways of enabling concurrent mode in your application, again, these features are experimental and expected to ship sometime around Q2 2019. React-dom exposes a function called &lt;code&gt;createRoot&lt;/code&gt; (currently &lt;em&gt;unstable_createRoot&lt;/em&gt;), it receives the dom reference to the element where the app will be rendered, you can chain a &lt;code&gt;render&lt;/code&gt; method with the app instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fyfxcv4essjs8cr1ntjgi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fyfxcv4essjs8cr1ntjgi.png" alt="create root"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an opt-in feature, React exposes a tag called &lt;code&gt;ConcurrentMode&lt;/code&gt; which you can use to wrap subsections of your app to enable concurrent rendering only in their subtrees. &lt;/p&gt;

&lt;p&gt;For a demo visit &lt;a href="https://sdjs-demo.jdmg94.now.sh" rel="noopener noreferrer"&gt;https://sdjs-demo.jdmg94.now.sh&lt;/a&gt;&lt;br&gt;
For the full source visit:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/jdmg94" rel="noopener noreferrer"&gt;
        jdmg94
      &lt;/a&gt; / &lt;a href="https://github.com/jdmg94/sdjs-suspense-demo" rel="noopener noreferrer"&gt;
        sdjs-suspense-demo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A Simple Data Fetch Demo using Classes, Hooks, and Suspense. Circa 2019
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;San Diego JS React Monthly Demo&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A quick data fetching demo, illustrates data fetching with classes, hooks, and suspense. Includes code-splitting with React &lt;em&gt;lazy&lt;/em&gt;, Concurrent mode, and both Data and Image fetching using suspense.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Usage&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;the options are displayed on the main page, both classes and hooks work in virtually the same way, they are both loading data on mount and imperatively so if things don't come through in a timely manner, you can see a small &lt;em&gt;'jump'&lt;/em&gt; on the loader. By contrast, using Suspense, not only do we reduce the code boilerplate even further, but allows us to treat the data as if it was a synchronous operation, it will use the algebraic effect of an error boundary to find the nearest fallback up its tree and wait until everything is ready to render taking advantage of concurrent mode.&lt;/p&gt;
&lt;p&gt;If you open the suspense example page, you will…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/jdmg94/sdjs-suspense-demo" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>react</category>
      <category>suspense</category>
      <category>webdev</category>
      <category>experimental</category>
    </item>
    <item>
      <title>Why is No One Talking About Razzle?</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Sat, 30 Mar 2019 17:03:37 +0000</pubDate>
      <link>https://forem.com/josemunoz/why-is-no-one-talking-about-razzle-1c07</link>
      <guid>https://forem.com/josemunoz/why-is-no-one-talking-about-razzle-1c07</guid>
      <description>&lt;p&gt;I love working in React, as most people do, I started with Create-React-App (CRA).&lt;br&gt;
This provided a big cushion for me to just start working and forget about setting up the environment, I think most of us would agree that if we could just open an editor and start spitting out JSX without setting up babel/webpack, it would make our lives simpler. One of the things I enjoy the most about React is using client-side routing with react-router-dom. When looking for SSR solutions, I noticed the market forced me to abandon my way of doing routing, which meant I couldn't benefit from all the APIs that I get for free with my router. This was a big turn off for me, I had to think about my existing projects, which had gained a certain level of complexity, and re-structure everything to fit in either Next's way of doing routing, or Gatsby's way of using templates for static content. &lt;/p&gt;

&lt;p&gt;I am NOT a fan of tools that force you to think around them and don't enable your creativity, that's one of the main reasons I abandoned Angular after v2 came out.&lt;br&gt;
So SSR for me was a deal breaker for some time, I needed the SEO benefits, but I wasn't going to re-factor my whole app to do so.&lt;/p&gt;

&lt;p&gt;I needed more flexibility from my tools. So I started doing my research and I found &lt;a href="https://github.com/jaredpalmer/razzle" rel="noopener noreferrer"&gt;Razzle&lt;/a&gt; which is an isomorphic SSR solution. Razzle even has its own CLI, Create-Razzle-App (also CRA?), which meant I could get going by just calling it like the original Create-React-App. Razzle grew on me really fast, it's config-less mode meant I could start prototyping quickly just like I would with CRA, but I had all the extensibility I needed without having to adapt my workflow to it. &lt;/p&gt;

&lt;p&gt;If I wanted to change the ESLint config, I could do so by just adding a &lt;code&gt;.eslintrc&lt;/code&gt; file to the project, the babel config could be changed the same way, add a plugin with a &lt;code&gt;.babelrc&lt;/code&gt; and Razzle will pick it up and add it to the default config, if I needed to modify the webpack config just add a &lt;code&gt;razzle.config.js&lt;/code&gt; file, which provides a no-hassle, extensible, default webpack config. I didn't have to buy into a new framework, I didn't have to refactor my whole app (much). I could keep using React-router-dom just like I did with CRA, so the learning curve is basically non-existent. In fact, the only thing I had to do in order to add SEO to my apps now was to copy paste the SEO component from Gatsby, that was it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgflip.com%2F2xcfb5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgflip.com%2F2xcfb5.jpg" alt="But wait! There's more."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because of the way Razzle works, you can use it with Vue, Angular, or React.&lt;br&gt;
By default, Razzle comes with React's config, but you could easily change the config to use any other frontend framework.&lt;/p&gt;

&lt;p&gt;So How does Razzle work?&lt;/p&gt;

&lt;p&gt;Razzle bundles both your client and server code using two different webpack instances running with Hot Module Replacement in parallel. While your server is bundled and run on whatever port you specify in src/index.js (3000 is the default), the client bundle (i.e. entry point at src/client.js) is served via webpack-dev-server on a different port (3001 by default) with its publicPath explicitly set to localhost:3001 (and not / like many other setups do).&lt;/p&gt;

&lt;p&gt;Razzle was created by Jared Palmer, the mind behind Formik, Backpack, and After.js, with support from other prominent OSS contributors like Dan 'the man' Abramov, and Jari Zwarts and many others. Give Razzle a try, I'm sure you're going to love it!&lt;/p&gt;

</description>
      <category>react</category>
      <category>angular</category>
      <category>vue</category>
      <category>ssr</category>
    </item>
    <item>
      <title>How to Easily Center stuff with Flexbox</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Wed, 02 Jan 2019 20:09:18 +0000</pubDate>
      <link>https://forem.com/josemunoz/how-to-easily-center-stuff-with-flexbox-1gp3</link>
      <guid>https://forem.com/josemunoz/how-to-easily-center-stuff-with-flexbox-1gp3</guid>
      <description>&lt;p&gt;&lt;em&gt;Photo by Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Brief History of the CSS struggle
&lt;/h2&gt;

&lt;p&gt;Centering elements on a web page has been historically cumbersome and harder than it should be. In ye olde days, tables reigned supreme as they were the only HTML element that allowed centering to some degree. &lt;/p&gt;

&lt;p&gt;In November 1994 a CSS Proposal was announced at the Web Conference in Chicago. This was the beginning of the web as we know it but it still had a long way to become what we know today.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JM-1_IzB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/7n5rHG8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JM-1_IzB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.imgur.com/7n5rHG8.png" alt="" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you go to 1998 google using the &lt;a href="https://web.archive.org/web/19981202230410/http://www.google.com:80/"&gt;wayback machine&lt;/a&gt; you can check the source and see that it was only an &lt;code&gt;img&lt;/code&gt; tag and some tables. &lt;/p&gt;

&lt;p&gt;Centering elements on the web was a lot easier once automatic margins were introduced, on later versions of CSS. In theory, you could throw auto margins at any element in the box model and it should automagically center itself within their scope, however, this only worked partially since it was hard to work with the vertical axis of this solution. This was a major pain point for most web developers in the early 2000s, how to &lt;em&gt;vertically&lt;/em&gt; center elements in using the box model.&lt;/p&gt;

&lt;p&gt;It wasn't until 2013 that W3C released a working draft of Flexbox which was promised to solve this and other long-standing pain points.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We're Here
&lt;/h2&gt;

&lt;p&gt;I know you didn't come here for a history lesson, especially one that happened some 30 years ago, let's get our hands dirty with some real world 2019 methods of centering elements on your web page.&lt;/p&gt;

&lt;p&gt;Horizontal centering is pretty straightforward depending on your needs. You can get away with slapping auto margins on your element and it would work most of the time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.item&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your ambitions go beyond centering a single element, flexbox is here to save the day. In this case, you won't make a rule for the elements you want to center, you will make rules for its container and everything inside will fall along the lines of those rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  Horizontal Axis
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.row&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* 
   * all children are automatically
   * considered columns
   */&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Vertical Axis
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.column&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* 
   * all children are automatically
   * considered rows
   */&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once your container has the right direction, we can center the items along the main axis of our container by setting &lt;code&gt;justify-content: center;&lt;/code&gt;, this is cool we now have our content centered along either axis of the container, but, why not both?&lt;br&gt;
This could be useful to display centered elements on a fullscreen container, or to make a grid system, we are not going that deep into flexbox's possibilities in this post, if you want to see what could be accomplished with flexbox as a grid system I recommend you check the &lt;a href="https://bulma.io"&gt;Bulma CSS Framework&lt;/a&gt;, it's one of my favorites. What we are trying to accomplish here is much more trivial, center our elements in both its axis, we just need to add &lt;code&gt;align-items: center;&lt;/code&gt; and this will change the alignment in the perpendicular axis. By joining both &lt;code&gt;justify-content&lt;/code&gt; and &lt;code&gt;align-items&lt;/code&gt; we can have our child elements centered in both the X and Y planes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.centered&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want something in the center of the screen all you need to add is &lt;code&gt;height: 100vh;&lt;/code&gt; and your content will be there.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/Jdmg94/embed/dwJmvJ?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A few years ago, having elements in the exact middle of the screen was a mere illusion that very crafty web devs created through complicated and often rigid solutions, nowadays you can toss 6 lines of CSS and make it happen.&lt;/p&gt;

&lt;p&gt;Happy 2019 🎉 would you like to continue reading about the history of CSS? &lt;br&gt;
You can check out &lt;a href="https://www.w3.org/Style/CSS20/history.html"&gt;W3's History of CSS&lt;/a&gt; which was used to help write this post. For more information about flexbox visit &lt;a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/"&gt;CSS-Tricks' Complete Guide to Flexbox&lt;/a&gt; which is a great resource.&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>flexbox</category>
    </item>
    <item>
      <title>Bootstrapping a React library with Parcel Bundler</title>
      <dc:creator>José Muñoz</dc:creator>
      <pubDate>Thu, 20 Sep 2018 17:48:28 +0000</pubDate>
      <link>https://forem.com/josemunoz/bootstrapping-a-react-library-with-parcel-bundler-4l50</link>
      <guid>https://forem.com/josemunoz/bootstrapping-a-react-library-with-parcel-bundler-4l50</guid>
      <description>&lt;h5&gt;
  
  
  &lt;em&gt;Photo by Jøn on Unsplash&lt;/em&gt;
&lt;/h5&gt;

&lt;p&gt;Often while working on a project I get to create some neat components that I would like to re-use in the future and keep it in a presentable repo for anyone interested. Most of these side-projects end up in a repo graveyard or not even get split from their original project. Configuring webpack and babel to transpile and expose a UMD module and a demo page can be a daunting task. Although Webpack 4 has introduced config-less operation, today I want to share my experience with &lt;a href="https://parceljs.org/"&gt;Parcel-bundler&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Parcel runs config-less by default, and it is a very fast and flexible bundler that works seamlessly with Babel 7. I want to show you how easy it is to achieve that painless library setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Folder Structure
&lt;/h2&gt;

&lt;p&gt;First, we need to create our root folder with the name of our project and initialize it with yarn (or NPM if that's what you're into).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir my-awesome-component 
cd my-awesome-component
yarn init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the folder has been initialized we need to add a couple of things&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;lib
&lt;span class="nb"&gt;mkdir &lt;/span&gt;example/src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These folders will hold both our source code and the example we're going to write.&lt;br&gt;
These are not the only folders we are going to work with but for now, this is all we need.&lt;/p&gt;
&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;p&gt;I'm only going to talk about the general dependencies you would need to accomplish an environment that provides most of the functionality you get from &lt;a href="https://github.com/facebook/create-react-app"&gt;CRA&lt;/a&gt; with a minimal setup using babel 7 and Parcel. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE: At the time writing this Parcel 1.10 is in beta, so I'll be using the beta since the current stable build does not support babel 7.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the most basic level, we need babel to: transpile to ES5, polyfill generators, and support the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax"&gt;object-spread syntax&lt;/a&gt;. We are also going to add parcel as our bundler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; @babel/cli @babel/core @babel/plugin-proposal-object-rest-spread @babel/plugin-transform-regenerator @babel/plugin-transform-runtime parcel-bundler@^1.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use &lt;a href="https://lodash.com"&gt;lodash.js&lt;/a&gt; or &lt;a href="https://momentjs.com"&gt;moment.js&lt;/a&gt; you may want to add the babel plugins to shave off those extra KBs from your bundle as well.&lt;/p&gt;

&lt;p&gt;Since we are talking about React in here, I'm going to add the obligatory dependencies. Note that &lt;em&gt;react-dom&lt;/em&gt; is added to be used in our demo and not necessarily on our library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add react react-dom prop-types
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring Babel 7
&lt;/h2&gt;

&lt;p&gt;Parcel provides a default babel config and it will do most of the things for you. However, you can define your own &lt;em&gt;.babelrc&lt;/em&gt; and Parcel will pick it up and add it to their config. Parcel will automatically add some presets like &lt;em&gt;env&lt;/em&gt; and &lt;em&gt;react&lt;/em&gt; so we don't need to set that up if you check the babel dependencies we didn't even need to include a preset, so we are here just to set up our plugins. I'm using atom, feel free to use your favorite editor!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; atom .babelrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then add&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;plugins&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/transform-runtime&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/transform-regenerator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@babel/proposal-object-rest-spread&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that was it for Babel!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scripts
&lt;/h2&gt;

&lt;p&gt;Now the fun part begins. We need to set up the scripts that are going to bring our project to life! open your &lt;em&gt;package.json&lt;/em&gt; and head to the &lt;em&gt;scripts&lt;/em&gt; section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; atom package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need a &lt;em&gt;start&lt;/em&gt; script that watches our source for changes and compiles it live to &lt;em&gt;/dist&lt;/em&gt; (or however you want to call it I'm going for the default).&lt;/p&gt;

&lt;p&gt;We need a &lt;em&gt;build&lt;/em&gt; script that compiles and minifies our bundle and makes it ready for shipping.&lt;/p&gt;

&lt;p&gt;we need a &lt;em&gt;start-demo&lt;/em&gt; script which watches the source of our example in &lt;em&gt;examples/src&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We need a &lt;em&gt;build-demo&lt;/em&gt; so our demo can also be bundled and get ready to be served on &lt;a href="https://pages.github.com/"&gt;github pages&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also need a &lt;em&gt;publish-demo&lt;/em&gt; script so we can push the bundle to GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parcel watch lib/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parcel build lib/index.js --global my-awesome-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;start-demo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parcel example/src/index.html --out-dir examples/dist --open&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build-demo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parcel build example/src/index.html --out-dir examples/dist --public-url ./&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;publish-demo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gh-pages -d examples/dist&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;NOTE: the &lt;strong&gt;--global&lt;/strong&gt; option denotes the UMD package name, so you need to provide the name your NPM package is going to have. Also, make sure your examples' &lt;strong&gt;index.html&lt;/strong&gt; has a script tag referencing your &lt;strong&gt;index.jsx&lt;/strong&gt; and parcel will take care of the rest&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra
&lt;/h2&gt;

&lt;p&gt;Source maps are generated by default using Parcel, and they can be a powerful tool to analyze and optimize your bundle size. Let's take advantage of them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/danvk/source-map-explorer"&gt;Source-map-explorer&lt;/a&gt; is a CLI that generates a report based on your existing source maps, we are going to use this tool to generate a visual representation of our bundle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; source-map-explorer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now let´s add a script to generate the HTML representation of our source map.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;view-source-map&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;source-map-explorer --html dist/index.js dist/index.map &amp;gt; source.html &amp;amp;&amp;amp; open source.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now you can open &lt;em&gt;source.html&lt;/em&gt; on your browser and figure out where you can shave off those extra KBs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE: If you are running windows you need to remove &lt;strong&gt;open&lt;/strong&gt; to launch the generated html to your default browser&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With the configuration we've discussed here, you can throw in something you cooked up in CRA with minimal changes and publish it as its own library with a nice demo hosted on GitHub pages. I hope this can encourage other devs to start using parcel and get their ideas published faster. Thanks for reading if you got this far, please leave a comment to share your thoughts!&lt;/p&gt;

</description>
      <category>parcel</category>
      <category>react</category>
      <category>github</category>
      <category>webpack</category>
    </item>
  </channel>
</rss>
