<?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>DEV Community: Emilia</title>
    <description>The latest articles on DEV Community by Emilia (@synecdokey).</description>
    <link>https://dev.to/synecdokey</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%2F447115%2F17cd69a6-9b89-454f-a1d2-8551d9f078dd.png</url>
      <title>DEV Community: Emilia</title>
      <link>https://dev.to/synecdokey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/synecdokey"/>
    <language>en</language>
    <item>
      <title>Nixing Homebrew: Streamlining package management on your machine</title>
      <dc:creator>Emilia</dc:creator>
      <pubDate>Mon, 18 Sep 2023 03:08:44 +0000</pubDate>
      <link>https://dev.to/synecdokey/nix-on-macos-2oj3</link>
      <guid>https://dev.to/synecdokey/nix-on-macos-2oj3</guid>
      <description>&lt;p&gt;As someone who deals with package management on the daily, whether it’s &lt;code&gt;pnpm&lt;/code&gt; or &lt;code&gt;cargo&lt;/code&gt;, I have grown tired of &lt;code&gt;brew&lt;/code&gt; rather lacklustre proposition. If you’re happy with &lt;code&gt;brew&lt;/code&gt;, by all means, stick with it! I’m not vibing with it anymore though.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I do consider brew so lacking
&lt;/h2&gt;

&lt;p&gt;There are quite a few reasons for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It’s slow. I don’t think ruby itself is the main reason, but the rather simplistic nature of brew’s architecture plays a part.&lt;/li&gt;
&lt;li&gt;You can only interact with the CLI. This is pretty bad, as there’s no file that declares your dependencies like a &lt;code&gt;package.json&lt;/code&gt; or a &lt;code&gt;Cargo.toml&lt;/code&gt;. This makes multi-machine management an exercise in frustration.&lt;/li&gt;
&lt;li&gt;As a consequence of this, managing versions is… not exactly ideal either. Yes, things like &lt;code&gt;fnm&lt;/code&gt;, &lt;code&gt;virtualenv&lt;/code&gt;, and &lt;code&gt;rustup&lt;/code&gt; are cool, but they only exist to fill a gap in most OS package managers. And that’s just programming languages, sometimes I want to avoid upgrading a binary, like postgres.&lt;/li&gt;
&lt;li&gt;Another missing feature is the lack of lock files.  &lt;code&gt;yarn&lt;/code&gt; ’s release was a transformative moment in the javascript ecosystem. It established how important these were, at a time where &lt;code&gt;npm&lt;/code&gt; did not provide them.&lt;/li&gt;
&lt;li&gt;Auto upgrades can be harmful. This is due to the lack of versioning, but I’ve had breakage in my dev environment because adding a package also upgraded majors on other packages. This behaviour can be improved with &lt;code&gt;HOMEBREW_NO_INSTALL_UPGRADE&lt;/code&gt; or &lt;code&gt;HOMEBREW_NO_AUTO_UPDATE&lt;/code&gt;, but they introduce other problems, and they aren’t the default.&lt;/li&gt;
&lt;li&gt;It doesn’t handle configuration management. In my dotfiles, I still have to invoke &lt;code&gt;stow&lt;/code&gt; . And even if I use a script, &lt;code&gt;stow&lt;/code&gt; sometimes generates its symbolic links too eagerly, bothersome when applications clutter their configuration directory. Yes, looking at you &lt;code&gt;fish&lt;/code&gt; 😠&lt;/li&gt;
&lt;li&gt;It’s a mess on apple silicon. Once you’re past the initial humps, it’s okay-ish. OS upgrades will still be painful, and the intel experience remains simpler.&lt;/li&gt;
&lt;li&gt;It’s less nice than linux package managers, and I run/manage linux machines aside from my MBP, so I’d love a common tool, or something at least on par. My only BSD is a truenas server which I manage via a local web interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And yes, homebrew bundle exists, and fixes some of these issues. But that means it sits in an awkward space, where it fills some of the expectations, but falls short due to the parent tool not catering to that paradigm. And the fact that you can inadvertently work around it is not helping. It’s also mentioned once on brew.sh, which does not inspire confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting an alternative
&lt;/h2&gt;

&lt;p&gt;There aren’t a lot of package managers that can fill that void. Fink and MacPorts are pretty much macOS only, and linux package managers tend to be linux-only. They can run on macOS, but it’s a path full of pain, and it’s a lot of manual steps. Which is the opposite of what I’m looking for, automation is the name of the game here. The only viable solution I was able to find was nix. Nix is many things beyond a simple package manager, but I want to stay simple for now. The goal is to manage my applications, and my dotfiles. There might be something else I’m not aware of, in which case I’d love to hear about it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting on with nix
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installing nix
&lt;/h3&gt;

&lt;p&gt;You might be tempted to use the command that nixos.org recommends, but will be better off using another path: the Determinate Nix installer. The reasons are detailed on the &lt;a href="https://zero-to-nix.com/concepts/nix-installer"&gt;Zero to Nix website&lt;/a&gt;. It offers a cleaner install/uninstall experience, essential when trying something out. To use it, type the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--proto&lt;/span&gt; &lt;span class="s1"&gt;'=https'&lt;/span&gt; &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="nt"&gt;-sSf&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; https://install.determinate.systems/nix | sh &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should bring nix to your machine, using the optimal setup for macOS, and that's it. You now have a working nix installation on your Mac. To check that things are in working order, you can type the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nix search nixpkgs neovim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we’re done with the installation, this is where a lot of tutorials would tell you to install nix-darwin. Don’t bother: it’s a lot of additional complexity, in an intrusive package. It allows you to tweak things at the OS level, but you pay too big a price. What’s worth it though, is &lt;a href="https://github.com/nix-community/home-manager"&gt;&lt;code&gt;home-manager&lt;/code&gt;&lt;/a&gt;. Using a flake, it’ll allow us to forget (or rather never learn) about a lot of nix commands, and get a pre-packaged shell with all the stuff you declared.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing home-manager
&lt;/h3&gt;

&lt;p&gt;Home-manager is what is going to be handling my dotfiles. It also enabling me to let a flake manage everything rather than editing nix’s configuration. Here’s the minimal configuration I went with, separated in two files. Replace &lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt; with whatever yours is to get going (&lt;code&gt;echo $USER&lt;/code&gt; will tell you what you username is if you aren’t sure):&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;flake.nix&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Emilia's dotfiles"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c"&gt;# inputs are other flakes you use within your own flake, dependencies&lt;/span&gt;
  &lt;span class="c"&gt;# if you will&lt;/span&gt;
  &lt;span class="nv"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;# unstable has the 'freshest' packages you will find, even the AUR&lt;/span&gt;
    &lt;span class="c"&gt;# doesn't do as good as this, and it's all precompiled.&lt;/span&gt;
    &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:nixos/nixpkgs/nixpkgs-unstable"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;home-manager&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:nix-community/home-manager"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nv"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;follows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nixpkgs"&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="c"&gt;# In this context, outputs are mostly about getting home-manager what it&lt;/span&gt;
  &lt;span class="c"&gt;# needs since it will be the one using the flake&lt;/span&gt;
  &lt;span class="nv"&gt;outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;home-manager&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;homeConfigurations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"&amp;lt;username&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;home-manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;homeManagerConfiguration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;# darwin is the macOS kernel and aarch64 means ARM, i.e. apple silicon&lt;/span&gt;
        &lt;span class="nv"&gt;pkgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;legacyPackages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;aarch64-darwin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;modules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="sx"&gt;./home.nix&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;home.nix&lt;/code&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;# This is required information for home-manager to do its job&lt;/span&gt;
  &lt;span class="nv"&gt;home&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;stateVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"23.11"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;username&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;homeDirectory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/Users/&amp;lt;username&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="o"&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="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;home-manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;# I use fish, but bash and zsh work just as well here. This will setup&lt;/span&gt;
  &lt;span class="c"&gt;# the shell to use home-manager properly on startup, neat!&lt;/span&gt;
  &lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;fish&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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 these files exist in the directory of your choice, then you can run:&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;# if your directory is part of a git repo, flake will only use files that&lt;/span&gt;
&lt;span class="c"&gt;# are properly tracked. This caught me off-guard multiple times!&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="c"&gt;# This will run home-manager after downloading it, the same way npx would&lt;/span&gt;
&lt;span class="c"&gt;# in JS land.&lt;/span&gt;
nix run github:nix-community/home-manager &lt;span class="nt"&gt;--&lt;/span&gt; switch &lt;span class="nt"&gt;--flake&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install everything necessary by reading your &lt;code&gt;flake.nix&lt;/code&gt;, create a &lt;code&gt;flake.lock&lt;/code&gt; to ensure reproducibility, and do all the necessary setup. Restart with a new shell to get all the necessary goodies. To make sure it all worked: &lt;code&gt;home-manager&lt;/code&gt; should now be in your &lt;code&gt;PATH&lt;/code&gt;, and can be invoked on the command line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding your packages
&lt;/h3&gt;

&lt;p&gt;Before installing a package, we need to find it. Finding it can be done one of two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the nixOS website: &lt;a href="https://search.nixos.org/packages"&gt;NixOS Search&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;On the command-line: &lt;code&gt;nix search nixpkgs &amp;lt;package&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you’ve determined what the package is, get its name, and then we can go add stuff to our &lt;code&gt;home.nix&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="c"&gt;# We add pkgs since it's available as an argument, thanks to our inputs&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;home&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;stateVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"23.11"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"emiliazapata"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;homeDirectory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/Users/emiliazapata"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c"&gt;# Then we add the packages we want in the array using pkgs.&amp;lt;name&amp;gt;&lt;/span&gt;
    &lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;git&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;neovim&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="c"&gt;# This is to ensure programs are using ~/.config rather than&lt;/span&gt;
  &lt;span class="c"&gt;# /Users/&amp;lt;username/Library/whatever&lt;/span&gt;
  &lt;span class="nv"&gt;xdg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;home-manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;fish&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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 you’re done, you can run this command to install these packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;home-manager switch &lt;span class="nt"&gt;--flake&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding your configuration
&lt;/h3&gt;

&lt;p&gt;To manage your dotfiles, it’s going to be in the &lt;code&gt;home.nix&lt;/code&gt; file again. There are two ways to go about it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leverage &lt;code&gt;home-manager&lt;/code&gt; and the nix language to the max, by putting the entire configuration in nix files. And figure out what needs to go where with its… questionable documentation&lt;/li&gt;
&lt;li&gt;Tell it to put specific files in specific places. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re gonna go with the second option, as it’s a lot less work, and doesn’t tie you to the nix ecosystem.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;home&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;stateVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"23.11"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"emiliazapata"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;homeDirectory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/Users/emiliazapata"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;git&lt;/span&gt;
      &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;neovim&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="c"&gt;# Tell it to map everything in the `config` directory in this&lt;/span&gt;
    &lt;span class="c"&gt;# repository to the `.config` in my home directory&lt;/span&gt;
    &lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;".config"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;./config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;recursive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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="nv"&gt;xdg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;home-manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;programs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;fish&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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 now, don’t forget to &lt;code&gt;git add&lt;/code&gt; all the necessary files. Home manager will also not override files it hasn’t managed, and will ignore that silently. You will need to remove the files in your &lt;code&gt;.config&lt;/code&gt;, in order to get home-manager to manage them. Once you’ve checked everything, same command as last time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;home-manager switch &lt;span class="nt"&gt;--flake&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it! You now have a nix-managed dotfiles repository, with declared packages. To ensure it all went without a hitch, you can &lt;code&gt;ls -a&lt;/code&gt; in one of the configuration directory you handled. It should show the symbolic links pointing to somewhere in &lt;code&gt;/nix/store/&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lrwxr-xr-x@ 1 username  staff    84B 17 Sep 11:38 init.lua@ -&amp;gt; /nix/store/7svm3r3xpwhgnfsp2g0wmpycai1fvxan-home-manager-files/.config/nvim/init.lua
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s a pretty lengthy article, but I wanted to be thorough and explain the &lt;strong&gt;why&lt;/strong&gt; which tends to be hand-waved away, especially in the nix ecosystem! You can find my dotfiles and the recent changes I made in my &lt;a href="https://github.com/synecdokey/dotfiles"&gt;dotfiles repo&lt;/a&gt; if you’re wondering what it ended up looking like in my case.&lt;/p&gt;

&lt;p&gt;One last note: The &lt;a href="https://discord.gg/RbvHtGa"&gt;nix discord community&lt;/a&gt; is pretty okay, and they helped me figure a lot of that stuff out. If you feel adventurous enough to try nix out, you might want to come hang there.&lt;/p&gt;

</description>
      <category>nix</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Building my own router</title>
      <dc:creator>Emilia</dc:creator>
      <pubDate>Wed, 26 Aug 2020 22:50:00 +0000</pubDate>
      <link>https://dev.to/synecdokey/building-my-own-router-bhh</link>
      <guid>https://dev.to/synecdokey/building-my-own-router-bhh</guid>
      <description>&lt;p&gt;I don't want to use &lt;code&gt;react-router&lt;/code&gt; on my personal projects. Mostly because of the bloat you incur for the high degree of compatibility (even the shiny version 6 still has a fair amount of cruft).&lt;/p&gt;

&lt;p&gt;I looked at alternatives, but truth be told, no one really wants to reinvent the wheel, and for good reasons! It works, and Facebook is probably a bigger issue if we're talking ethics. But hey, it's nonetheless a fun exercise to get acquainted with what browsers can do nowadays.&lt;/p&gt;

&lt;h3&gt;
  
  
  It's about leaving things behind
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;react-router&lt;/code&gt; relies on their own &lt;code&gt;history&lt;/code&gt; package, because it wants to be compatible with react native and Internet Explorer. I do not need nor want that, so there are a fairly consequential number of wins to be had just there. Though there's a gotcha: the history API can drive events in specific cases, but you'll still need some wrapping in the cases an event is not fired.&lt;/p&gt;

&lt;h3&gt;
  
  
  One way to do things
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;react-router&lt;/code&gt; affords you flexibility, as it's not opinionated in how you build your routes, but that means that different codebases can look very different. I often need to jump projects at work, and the lack of consistency due to that freedom is a curse I'd rather not deal with. Having a single way to do things is simpler to explain and learn, simpler to use, and simpler to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing &lt;code&gt;itsy-bitsy-router&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;An evergreen-browser barebones routing solution that only offers a hook-based API, and a &lt;code&gt;Link&lt;/code&gt; component for convenience. There's a &lt;a href="https://itsy-bitsy-router.netlify.app"&gt;documentation website&lt;/a&gt; available to get started quickly, and while it's not expansive yet, it does the job quite well, and allows me to dog-food the router with just itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;p&gt;I went with a very familiar API. It works, and does the job in a very simple manner. It supports url matching the way you'd expect: &lt;code&gt;path/to/:match/&lt;/code&gt;. It's fairly simple to use, and should cater to most use-cases! If not, that's probably something that can be improved, and &lt;a href="https://github.com/synecdokey/itsy-bitsy-router/issues"&gt;opening an issue&lt;/a&gt; could make a difference.&lt;/p&gt;

&lt;p&gt;It's also really lightweight, at &lt;a href="https://bundlephobia.com/result?p=itsy-bitsy-router@0.2.2"&gt;around 1kb gzipped&lt;/a&gt;. This is especially valuable when considering that a router is going to be part of your initial payload no matter what.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;As &lt;code&gt;history.pushState()&lt;/code&gt; and &lt;code&gt;history.replaceState()&lt;/code&gt; do not fire any events, we need the &lt;code&gt;useNavigate()&lt;/code&gt; hook to handle navigation in places where &lt;code&gt;Link&lt;/code&gt; is not desirable. &lt;code&gt;history.forward()&lt;/code&gt; and &lt;code&gt;history.back()&lt;/code&gt; do work and trigger
rerenders as expected though.&lt;/li&gt;
&lt;li&gt;TypeScript can't really play nice with something like &lt;code&gt;useParams()&lt;/code&gt;, and probably never will. So we're stuck with &lt;code&gt;Record&amp;lt;string, string&amp;gt;&lt;/code&gt; as the return type, instead of having something that relates to the current component. I don't see an easy way out of this one given we rely on string-defined properties with the &lt;code&gt;/path/to/:id&lt;/code&gt; API pattern. There may be an alternative API, focused on Typescript to be found at some point, but one of the selling points right now is to enable a quick opt-in/opt-out.&lt;/li&gt;
&lt;li&gt;SSR is something that probably doesn't work as-is (Maybe?), haven't really tried. But with gatsby and next already equipped with their own routing, I'm not really willing to spend time investigating this.&lt;/li&gt;
&lt;li&gt;There's no support for React Native. That's definitely not something I need, and I want to keep things as lean as I can.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;I want to get a feel for the API as it is, and maybe adjust a few things along the way, but this should be fairly final. The one thing I really want to integrate before cutting a v1 is React's Concurrent Mode, as routing is one of the rare occasions where it really shines.&lt;/p&gt;

&lt;p&gt;I mainly did this for myself, and for fun, but I feel like this could go further than that! If you liked it, do let me know ✨&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
    <item>
      <title>TailwindCSS is a keeper</title>
      <dc:creator>Emilia</dc:creator>
      <pubDate>Mon, 17 Aug 2020 08:46:42 +0000</pubDate>
      <link>https://dev.to/synecdokey/tailwindcss-is-a-keeper-3mh</link>
      <guid>https://dev.to/synecdokey/tailwindcss-is-a-keeper-3mh</guid>
      <description>&lt;p&gt;Let's be honest, I was a bit dubious about Tailwind at first. I was slightly put off by the idea of not writing CSS anymore, and replacing it with terse classes. But mostly because drawbacks were never really discussed, and that's usually a red flag. No technology or paradigm is perfect, there's always a downside. Tailwind is no different!&lt;/p&gt;

&lt;p&gt;I decided to give it a fair shake after seeing it used in front of me in a convincing manner. I used it a a small prototype, where I thought the quick iteration everyone raves about would help me be done with the prototype quicker. And therein lied my first surprise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The learning curve is minimal
&lt;/h2&gt;

&lt;p&gt;This is dependent on your editor, but vim offers &lt;a href="https://github.com/iamcco/coc-tailwindcss"&gt;intellisense completion&lt;/a&gt; and the framework website offers a powerful and quick search for its great documentation. Both of these allow you to dive in quickly, and keep being useful in the long run.&lt;/p&gt;

&lt;p&gt;But that's not the end of Tailwind's strengths. I have since used it on personal projects and at work to great effect. &lt;/p&gt;

&lt;h2&gt;
  
  
  The good
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Normalised values ensure consistency
&lt;/h3&gt;

&lt;p&gt;Most designs call for consistent spacing/sizing, and having pre-determined values help tremendously in keeping the experience consistent. If you were writing CSS, chances are mistakes will happen at some stage, and some spacing will slip through the cracks and not use your CSS/Sass variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS creep can't happen
&lt;/h3&gt;

&lt;p&gt;CSS is really easy to add, but a lot more complex to remove, because of the degree of separation between code and styles/layout. This means that websites tend to see the size of their CSS balloon over time. Since Tailwind uses a purging mechanism to ensure you only get the minimal subset of necessary CSS, you avoid the ballooning problem. Especially since removing a class attribute from a component will not affect the rest of your app, no matter what (This is also true with BEM, but BEM is only enforced by your own vigilance, CSS-in-JS and CSS modules do avoid that issue completely though).&lt;/p&gt;

&lt;h3&gt;
  
  
  Long classes are a good thing, actually
&lt;/h3&gt;

&lt;p&gt;It's one of the things that kept me from trying it in the first place, but there is something nice about being able to see what a component does in terms of layout and style at a glance. The naming is indeed terse, but still explicit enough to be readable! The added benefit, if using jsx-like syntax, is that you effectively consolidated HTML/CSS/JS in a single location without the usual downsides. I said location, not file, because even templated frameworks do keep CSS separated inside the file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexibility is there
&lt;/h3&gt;

&lt;p&gt;Don't like the default colours, or need to map them to whatever colours the designer picked, or create new colours? It's a small change in the config. Not happy with the spacing? Same deal. Need a specific CSS attribute not handled? Can be added in the config. It's a lot more flexible than it looks. But you know what? I've never had to do more than a couple tweaks, the package is fairly complete.&lt;/p&gt;

&lt;h3&gt;
  
  
  A lot less things to name
&lt;/h3&gt;

&lt;p&gt;Let's be honest for a minute, naming things is hard. When going for your traditional BEM naming convention, you need to name a lot of things. With Tailwind? You use the classes on offer, one less thing to worry about!&lt;/p&gt;

&lt;p&gt;But like I said earlier, it can't be all roses.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bad
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A complete paradigm shift
&lt;/h3&gt;

&lt;p&gt;Since things are so different from usual CSS methodologies, it makes it hard to integrate on an existing project without forcing you to check things in two places, and keep two ways of doing things in mind, which can make the cohabitation period somewhat painful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup is slightly involved
&lt;/h3&gt;

&lt;p&gt;Since Tailwind has to generate the right css file from your build, it's not plug-and-play. You really don't want to use the CDN version for any production environment, it's a whopping 1M of CSS right there, so you'll need to wrangle some configuration no matter what. The documentation does a good job of presenting you with most of the cases you may encounter, but if your stack is fairly complex, this will need a fair bit of messing around. PS: You'll almost certainly want to &lt;a href="https://tailwindcss.com/docs/preflight#disabling-preflight"&gt;disable the preflight&lt;/a&gt; when introducing it to an old codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  The missing bits
&lt;/h3&gt;

&lt;p&gt;Tailwind doesn’t support pseudo elements, it’s honestly a bit of a bummer. But I truly don't see a way to integrate those that wouldn't feel incredibly verbose or overly terse. Especially when pretty much all of Tailwind classes are only really impacting the component itself. I guess that's what &lt;code&gt;@apply&lt;/code&gt; is for. 🤷‍♀️ It's also not super flexible in terms of grid layouts, but I have never needed more than what's on offer when implementing a designer's vision.&lt;/p&gt;

&lt;p&gt;All in all, this paints a fairly good picture of Tailwind, but I tend to hold my opinions fairly loosely, which has probably helped tremendously getting behind the idea of atomic CSS and the Tailwind approach. It may not be for you or your team, but it's really one of those "you need to try it to form an opinion" kind of thing. If you have the bandwidth to try it, it comes highly recommended.&lt;/p&gt;

</description>
      <category>css</category>
      <category>design</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Leaving VSCode</title>
      <dc:creator>Emilia</dc:creator>
      <pubDate>Wed, 05 Aug 2020 21:25:20 +0000</pubDate>
      <link>https://dev.to/synecdokey/leaving-vscode-4c34</link>
      <guid>https://dev.to/synecdokey/leaving-vscode-4c34</guid>
      <description>&lt;p&gt;Spoiler alert: I'm old. Old enough that uni assignments would be mostly done by ssh'ing into the mainframe computer and work there. At a time where the editor ecosystem was quite frankly... not there. Sublime didn't exist at the time, and nano felt underwhelming compared to vim, especially with our professors handing out vim tips as we'd go through stuff.&lt;/p&gt;

&lt;p&gt;So I learnt vim, and modal editing. And never left that knowledge behind. I feel it's quite useful if you take the time to learn it, the same way your capacities grow as you learn shortcuts for your favorite editor. Vim just placed it at the forefront. Given that most editors support vi bindings, it's not knowledge that goes to waste if you leave vim behind.&lt;/p&gt;

&lt;p&gt;Which is what I've done for a while now! First for Emacs, which has the best vi emulation layer, and would argue edges out vim in places! It was fun while it lasted, but as I moved towards a frontend-focused role, VSCode autocomplete was too appealing a deal to think about not  using it. The bindings were adequate. Limited and not super nicely integrated, yes, but adequate. The completion magic really sold it despite the modal layer shortcomings.&lt;/p&gt;

&lt;p&gt;But let's be honest for a minute. Microsoft sucks. They went to great length to change their image, but the fact remains that the company is collaborating with rather unsavoury actors, and still struggles to treat their employees decently, especially when it comes to their marginalised workers. And I'm not ok with that. It's not really my job to fix Microsoft issues, and it's probably not something that can be fixed under our current economic system. But the fact remains that I am uncomfortable using their products, and that's the thing I can do something about, especially when it's not something that would hamper my visibility nor something that my workplace uses extensively like github. VSCode fits the bill, and so we said our goodbyes.&lt;/p&gt;

&lt;p&gt;I tried going back to Emacs, but their LSP integration is still slow unless you're willing to go on the bleeding edge, and even then, things look uncertain when it comes to protocol extensions. A lot of the really magical stuff happens in those, and these niceties are hard to forget about. I thought that vim did not handle these either, &lt;a href="https://github.com/rust-analyzer/rust-analyzer/issues/2518#issuecomment-618828465"&gt;as YCM has no appetite in doing so&lt;/a&gt;. But I was wrong! &lt;a href="https://github.com/neoclide/coc.nvim"&gt;coc.nvim&lt;/a&gt; is a fully featured LSP implementation that strives to offer the same capabilities as VSCode (Not just the LSP) all in the comfort of a native modal editor. Javascript and Typescript are part of the default bundle, but other LSPs are readily available too, and work quite nicely.&lt;/p&gt;

&lt;p&gt;I gained a lot in the transition. I don't need to leave the terminal anymore, it feels a lot snappier, which I find especially important on something I use on daily. I got back to a modal model that just works, without any quirks, and a very minimal interface to leave space for what matters: the code.&lt;/p&gt;

&lt;p&gt;I'll probably continue fluttering around over the years to be honest, unless I actually manage to write &lt;a href="https://github.com/synecdokey/viper"&gt;my own thing&lt;/a&gt;, that works the way I want it to!&lt;/p&gt;

&lt;p&gt;PS: I use Neovim, and you probably should too. Vim is trying to diverge more and more from Neovim, but goes in a direction that looks a lot less appealing than &lt;a href="https://neovim.io/roadmap/"&gt;Neovim's roadmap&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>vim</category>
    </item>
  </channel>
</rss>
