<?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: Heechul Ryu</title>
    <description>The latest articles on DEV Community by Heechul Ryu (@ryuheechul).</description>
    <link>https://dev.to/ryuheechul</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%2F32660%2F75d5582e-f0b5-4036-88a9-003f0657cdd2.jpeg</url>
      <title>DEV Community: Heechul Ryu</title>
      <link>https://dev.to/ryuheechul</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ryuheechul"/>
    <language>en</language>
    <item>
      <title>Don't Give Up on Nix Just Yet</title>
      <dc:creator>Heechul Ryu</dc:creator>
      <pubDate>Thu, 06 May 2021 11:35:24 +0000</pubDate>
      <link>https://dev.to/ryuheechul/don-t-give-up-on-nix-just-yet-37mh</link>
      <guid>https://dev.to/ryuheechul/don-t-give-up-on-nix-just-yet-37mh</guid>
      <description>&lt;p&gt;In my case, I almost did, but I'm glad that I ended up not.&lt;/p&gt;

&lt;p&gt;There are many great articles to show how Nix can be useful, so instead of me repeating those points, I will link them at the bottom of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  WTH is Nix?
&lt;/h2&gt;

&lt;p&gt;Before I go ahead and talk about why I felt like giving up and why you shouldn't, let me describe what's my perspective on Nix and why I'm interested to keep using it.&lt;/p&gt;

&lt;p&gt;You may or may not have come across &lt;a href="https://builtwithnix.org/"&gt;Built with Nix&lt;/a&gt; from something like &lt;a href="https://direnv.net/"&gt;direnv&lt;/a&gt; wondered What &lt;a href="https://nixos.org/"&gt;Nix&lt;/a&gt; is.&lt;/p&gt;

&lt;p&gt;Nix is at least these three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nix, the (programming) language that you write in &lt;code&gt;*.nix&lt;/code&gt; files to let Nix work for your liking.&lt;/li&gt;
&lt;li&gt;Nix, the package manager powered by few binaries like &lt;code&gt;nix&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;NixOS, Linux "distro" that comes with Nix to configure OS itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although I have &lt;a href="https://dev.to/ryuheechul/quickest-way-to-run-nixos-on-your-vmware-fusion-4dn7"&gt;a super tiny experience about NixOS before&lt;/a&gt;, I'm not really using NixOS at the moment so my focus in this post is solely about Nix the package manager and Nix the language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did I even care to try Nix?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;There are multiple motivations and below is one of them.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I don't write Go programs often enough that usually Golang is not installed in my machine.&lt;br&gt;
But when I need to, installing Go was a bit painful and confusing enough for me (surprisingly almost every time!). And my usual approach to deal with this issue is &lt;a href="https://www.docker.com/blog/containerize-your-go-developer-environment-part-1/"&gt;using Docker&lt;/a&gt;. All though I often use containers like in &lt;a href="https://github.com/ryuheechul/gcloud"&gt;a way of using VM&lt;/a&gt; to avoid polluting my host machine, a container is no localhost, so it's limited and it could "force" you to be container "expert" when you don't need to be just yet. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;What you wanted to do was just to write a Go program and run it remember?&lt;/em&gt; 😅&lt;/p&gt;

&lt;p&gt;Then I discovered Nix and I gave it a Go. 😆&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;go &lt;span class="nb"&gt;env&lt;/span&gt;
&lt;span class="go"&gt;zsh: command not found: go

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nix-shell &lt;span class="nt"&gt;-p&lt;/span&gt; go
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;now you are &lt;span class="k"&gt;in &lt;/span&gt;Nix shell
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;[nix-shell:~]$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;go &lt;span class="nb"&gt;env&lt;/span&gt; 
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;span class="go"&gt;GOOS="darwin"
GOPATH="/Users/username/go"
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;...
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;[nix-shell:~]$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; hello.go
&lt;/span&gt;&lt;span class="go"&gt;package main

import "fmt"

func main() {
    fmt.Println("Hello, 세상")
}
EOF

&lt;/span&gt;&lt;span class="gp"&gt;[nix-shell:~]$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;go run hello.go
&lt;span class="go"&gt;Hello, 세상

&lt;/span&gt;&lt;span class="gp"&gt;[nix-shell:~]$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;go
&lt;span class="go"&gt;zsh: command not found: go
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That felt like a breeze to me. I didn't need to do anything like setting the right environment variables and so on. Just &lt;code&gt;nix-shell -p go&lt;/code&gt; then I have it and &lt;code&gt;exit&lt;/code&gt; then I don't!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Technically you still do but it doesn't pollute the environment. &lt;em&gt;The reality is more complicated than that but let's leave it at that for now.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This, my first experience with Nix and it was probably like a year ago or so. But then I didn't go into Nix much yet until recently.&lt;/p&gt;

&lt;p&gt;Since I do like to isolate environments, reuse configurations, and reproduce those setups to multiple devices, I've been using my own &lt;a href="https://github.com/ryuheechul/dotfiles"&gt;dotfiles&lt;/a&gt; and sometimes, &lt;a href="https://github.com/ryuheechul/gcloud"&gt;containers&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  What other tools I used before Nix
&lt;/h3&gt;

&lt;p&gt;Since I didn't want to use all different tools for all different OSes (and their own package managers), Homebrew (and Linuxbrew) was my first choice to install necessary packages.&lt;/p&gt;

&lt;p&gt;But I find some issues with it in my use case, as it's often the case with any other tools.&lt;/p&gt;

&lt;p&gt;To list some:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;installing specific versions with Homebrew can be challenging. (Especially when you need both at the same time)&lt;/li&gt;
&lt;li&gt;many times, it feels slow to update new formulae (&lt;code&gt;brew update&lt;/code&gt;) which it always seems to run when I &lt;code&gt;brew install [package]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enter &lt;a href="https://github.com/asdf-vm/asdf"&gt;asdf&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;asdf&lt;/code&gt; solves those issues mostly for programming language packages.&lt;/p&gt;

&lt;p&gt;But in my opinion, Asdf is more of a runtime version manager than a package manager.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;However I'm going to skip explaining about &lt;code&gt;asdf&lt;/code&gt; since this is a post about Nix! But you should definitely check it out if you are interested :)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, remember that I mentioned that I used Nix briefly before? At this point, I felt like Nix can be a tool that can complement both tools in a "new way".&lt;/p&gt;

&lt;p&gt;So I decided to try Nix to see if it's possible to replace other tools. Therefore my &lt;a href="https://github.com/ryuheechul/dotfiles/commit/ad24cc15bbf22027479e8894f357466a42379f31"&gt;dotfiles started to add Nix files&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I felt like giving up
&lt;/h2&gt;

&lt;p&gt;So it felt like everything was actually going ok until it didn't. I reached the point one package didn't install properly on macOS, while it was fine on Linux with the unstable channel. While this can be fixed over time I wanted to make an exception just for few packages only for Darwin (macOS) platform.&lt;/p&gt;

&lt;p&gt;And I couldn't manage to actually make that happen for a while.&lt;/p&gt;

&lt;p&gt;Why? Because I wanted to do this kind of advanced stuff without actually understanding the language first.&lt;/p&gt;

&lt;p&gt;Why did I do that? I think because that's how I approached with other tools.&lt;/p&gt;

&lt;p&gt;I usually learn tools first by knowing which command and arguments to use to do this and that.&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;Brewfile&lt;/code&gt; (in case of &lt;code&gt;brew&lt;/code&gt;) and &lt;code&gt;.tool-versions&lt;/code&gt; (in case of &lt;code&gt;asdf&lt;/code&gt;) are extra that comes after just typing commands. I'm pretty sure I'm not alone on this. &lt;/p&gt;

&lt;p&gt;But in the case of Nix, using Nix the language properly could be essential very fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  What advanced stuff that I tried to do?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Optional overlaying for Darwin
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;if any of this stuff doesn't make any sense to you feel free to skip to the next section&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a typical top line you may come across with &lt;code&gt;.nix&lt;/code&gt; files&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="o"&gt;?&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&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;What if you want to overlay some packages conditionally? You can try something like the below.&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="o"&gt;?&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;# to simplify the code, we import `overlay.nix` for now which you will get to see in a minute&lt;/span&gt;
  &lt;span class="nv"&gt;overlays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&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;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;optionals&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;stdenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;isDarwin&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./overlay.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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But how do I get &lt;code&gt;pkgs.lib&lt;/code&gt; and &lt;code&gt;pkgs.stdenv&lt;/code&gt; if I'm in the import section that doesn't know about &lt;code&gt;pkgs&lt;/code&gt; yet?&lt;/p&gt;

&lt;p&gt;You can actually &lt;code&gt;import&lt;/code&gt; inside &lt;code&gt;import&lt;/code&gt; (with &lt;code&gt;let ... in&lt;/code&gt; in this case) like below.&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="o"&gt;?&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&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;let&lt;/span&gt;
    &lt;span class="nv"&gt;unstable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="nv"&gt;stdenv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;unstable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="p"&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;unstable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;in&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;overlays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&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;optionals&lt;/span&gt; &lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;isDarwin&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./overlay.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;p&gt;Seems too many &lt;code&gt;import&lt;/code&gt;s in the first &lt;code&gt;import&lt;/code&gt; section and it looks confusing? Also, can you even do that? &lt;/p&gt;

&lt;p&gt;Yes, it might look weird but this is very valid in Nix. Inside &lt;code&gt;()&lt;/code&gt; it just expects any valid Nix expression. Therefore, &lt;code&gt;let ... in { ... }&lt;/code&gt; is a perfectly valid because &lt;code&gt;{...} # AttributeSet&lt;/code&gt; is expected after &lt;code&gt;import &amp;lt;nixpkgs&amp;gt;&lt;/code&gt;. Why &lt;code&gt;import &amp;lt;nixpkgs&amp;gt;&lt;/code&gt; expect AttributeSet? We will get to that in the &lt;strong&gt;Demystifying Nix files&lt;/strong&gt; below for details.&lt;/p&gt;

&lt;p&gt;Now we solved the issue but because it could look confusing I split the files below.&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;# my-pkgs.nix&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="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./fallback/darwin/optional-overlaying.nix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;

&lt;span class="c"&gt;# ...&lt;/span&gt;

&lt;span class="c"&gt;# fallback/darwin/optional-overlaying.nix&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;unstable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="nv"&gt;stdenv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;unstable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="p"&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;unstable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;overlays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&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;optionals&lt;/span&gt; &lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;isDarwin&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./overlay.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="c"&gt;# fallback/darwin/overlay.nix&lt;/span&gt;
&lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;super&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="c"&gt;# different channel to fallback&lt;/span&gt;
  &lt;span class="nv"&gt;fallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs-fallback-darwin&lt;/span&gt;&lt;span class="o"&gt;&amp;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;fallback&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt; &lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;# imagine these two are broken for Darwin in your main channel, `&amp;lt;nixpkgs&amp;gt;`,&lt;/span&gt;
  &lt;span class="c"&gt;# now you can fallback to a different channel, `&amp;lt;nixpkgs-fallback-darwin&amp;gt;` that may work for Darwin&lt;/span&gt;
  &lt;span class="kn"&gt;inherit&lt;/span&gt; &lt;span class="nv"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;inherit&lt;/span&gt; &lt;span class="nv"&gt;bash&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;Like I said earlier if these don't make much sense yet it's ok and the section X will help you&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Is Nix the language difficult?
&lt;/h2&gt;

&lt;p&gt;Not really, once you get to know it, it's quite simple but it did look foreign and scary to me for a bit initially.&lt;/p&gt;

&lt;p&gt;Because even though it's simple but also it's very flexible like lego blocks.&lt;/p&gt;

&lt;p&gt;Nix is an actual programming language not like much simpler configuration files like &lt;code&gt;Brewfile&lt;/code&gt; or &lt;code&gt;.tool-versions&lt;/code&gt; and even though I've been writing code for a while I couldn't help but notice myself asking but why the whole (programming) language to manage packages?&lt;/p&gt;

&lt;p&gt;And not just language itself in a file but also each file look somehow different to each other. For example, why &lt;code&gt;default.nix&lt;/code&gt; looks different than &lt;code&gt;shell.nix&lt;/code&gt; and all other &lt;code&gt;.nix&lt;/code&gt;.  What's really expected in &lt;code&gt;.nix&lt;/code&gt; files? I got confused.&lt;/p&gt;

&lt;p&gt;Therefore I somehow resisted embracing the Nix language. It also didn't even "look" good until I got the aha moment.&lt;/p&gt;

&lt;p&gt;Turns out it's because Nix is super flexible. Anything that is a valid Nix expression can be &lt;code&gt;.nix&lt;/code&gt; file. Even just the number &lt;code&gt;3&lt;/code&gt; is a valid Nix expression and you can import it to other &lt;code&gt;.nix&lt;/code&gt; files and do anything with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demystifying Nix files
&lt;/h2&gt;

&lt;p&gt;After this section, you will get to know why all nix files kind of somewhat don't look similar to each other except they all look Nix-y.&lt;/p&gt;

&lt;p&gt;I tried to come up with why and this is one of my speculations that we are quite used to somewhat (implicitly) structured files.&lt;/p&gt;

&lt;p&gt;Some example implicit structure scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;maybe &lt;code&gt;main.xxx&lt;/code&gt; file has to exist in order for your program to work&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;import&lt;/code&gt; lines should be on the top of the file&lt;/li&gt;
&lt;li&gt;main function somewhere &lt;/li&gt;
&lt;li&gt;have to have one function in a file at least&lt;/li&gt;
&lt;li&gt;could be even a whole main class should exist&lt;/li&gt;
&lt;li&gt;can't just have the number &lt;code&gt;3&lt;/code&gt; as a whole file content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With Nix, we may need to rethink that, and to simply put, &lt;code&gt;.nix&lt;/code&gt; files just need to be valid Nix expression and that's it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For example, these are all valid.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;you can just have &lt;code&gt;3&lt;/code&gt; and that's it&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;# number-three.nix&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;just a list if you want&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;# list-simple.nix&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;import&lt;/code&gt; can be anywhere, I mean literally&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;# list-with-import.nix&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./number-three.nix&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c"&gt;# [ 1 2 3 ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can think of what &lt;code&gt;import&lt;/code&gt; does as simply embedding the source file to the target file.&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;# attributeset-with-import.nix&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;three&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./number-three.nix&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;or&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;# attributeset-with-import-2.nix&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;number_three&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./number-three.nix&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;one&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;two&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;three&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;number_three&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;even this can be valid&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;# function-mirror.nix or function-identity.nix&lt;/span&gt;
&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you can use like this&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;# import-identity.nix&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./function-identity.nix&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c"&gt;# 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for two arguments, you can:&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;# function-add.nix&lt;/span&gt;
&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="c"&gt;# import-add.nix&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./function-add.nix&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="c"&gt;# 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;maybe AttributeSet as an argument&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;# function-arg-as-attr.nix&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;argInAttr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;secondArg&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;"with the default value"&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;
&lt;span class="nv"&gt;argInAttr&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="nv"&gt;secondArg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="c"&gt;# import-arg-as-attr.nix&lt;/span&gt;
&lt;span class="c"&gt;# I skip secondArg because it's with default value&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./function-arg-as-attr.nix&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nv"&gt;argInAttr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"I skip secondArg because it's "&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;now you should know these are nothing special&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;# just a function that has two arguments called `self` and `super`&lt;/span&gt;
&lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;super&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="c"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="c"&gt;# just a function that expect AttributeSet that may have `pkgs`, if not `import &amp;lt;nixpkgs&amp;gt; {}` is the default value&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="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;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;# ...&lt;/span&gt;

&lt;span class="c"&gt;# perhaps this way helps you to see it better&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="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&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;But why &lt;code&gt;import &amp;lt;nixpkgs&amp;gt; {}&lt;/code&gt;, why &lt;code&gt;{}&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;&amp;lt;nixpkgs&amp;gt;&lt;/code&gt; will be evaluated to a function that expects AttributeSet as a parameter that can be empty.&lt;/p&gt;

&lt;p&gt;For example, let's look at another file below that is a function.&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;# https://github.com/NixOS/nixpkgs/blob/master/pkgs/tools/misc/exa/default.nix&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;fetchFromGitHub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;rustPlatform&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;cmake&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pandoc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pkg-config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;zlib&lt;/span&gt;
&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;Security&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;libiconv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;installShellFiles&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt;
&lt;span class="c"&gt;# it's just this file is expecting to be called by consumer that will provide all these attributes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far when I've been with other tools, usually command line proficiency first and conf file after.&lt;br&gt;
With nix, I think it's inevitable to need to be comfortable with Nix language to unleash the potential of Nix. And that's why I think there is a whole programming language to a package manager.&lt;/p&gt;

&lt;p&gt;You can find good resources for the language:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nixcloud.io/tour"&gt;nixcloud.io/tour&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55"&gt;Nix by example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/search?l=Nix&amp;amp;q=language%3ANix&amp;amp;type=code"&gt;Any nix code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learnxinyminutes.com/docs/nix/"&gt;Learn Nix in Y minutes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The good thing about Nix is that there are tons of examples you can find on Github. &lt;a href="https://github.com/search?l=Nix&amp;amp;q=language%3ANix&amp;amp;type=code"&gt;Go ahead&lt;/a&gt; and get yourself familiar with them!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;OK, so maybe you are convinced that Nix the language is not something we should be afraid of but is that why should I use Nix, though?&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of getting started with Nix
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fresh way of doing things
&lt;/h3&gt;

&lt;p&gt;It could be refreshing if you are willing to learn a new of doing things, just like embracing FP for the first time!&lt;/p&gt;

&lt;h3&gt;
  
  
  Nix language is actually interesting
&lt;/h3&gt;

&lt;p&gt;you might not welcome less familiar syntax but they actually could help you decouple how you think with syntax.&lt;/p&gt;

&lt;p&gt;Nix could look foreign at first just because it's different from what you are used to but it's actually quite simple and works like lego blocks. I hope that becomes more clear in the previous section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Good opportunity for getting used to Functional Programming
&lt;/h3&gt;

&lt;p&gt;Have you been wanting to use/learn FP but haven't had a chance yet? &lt;br&gt;
Then maybe it could be even more interesting to you.&lt;br&gt;
I don't think I mentioned that Nix is a functional programming language and it is.&lt;br&gt;
It can be a good opportunity to get used to FP since, with Nix, it's very easy to start small.&lt;/p&gt;

&lt;h3&gt;
  
  
  You don't have to use NixOS or anything else that you don't need/want yet
&lt;/h3&gt;

&lt;p&gt;Start small with &lt;code&gt;nix-shell&lt;/code&gt; or &lt;code&gt;nix repl&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  You get to learn how your packages are built
&lt;/h3&gt;

&lt;p&gt;For example, this is how &lt;code&gt;ponysay&lt;/code&gt; is built, &lt;a href="https://github.com/NixOS/nixpkgs/blob/d600f006643e074c2ef1d72e462e218b647a096c/pkgs/tools/misc/ponysay/default.nix"&gt;https://github.com/NixOS/nixpkgs/blob/d600f006643e074c2ef1d72e462e218b647a096c/pkgs/tools/misc/ponysay/default.nix&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Nix usages so far
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A cheap and fast way of installing or trying out new packages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ nix-shell -p cowsay
[nix-shell:~/tmp]$ cowsay hi
 ____
&amp;lt; hi &amp;gt;
 ----
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  My home that comes with all the packages I want/need across all my devices
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/ryuheechul/dotfiles/blob/master/nix/home.nix"&gt;https://github.com/ryuheechul/dotfiles/blob/master/nix/home.nix&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Also it's reusable to do something else like Building a Docker image
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/ryuheechul/dotfiles-launchpad/blob/2d70fc6a48a4781e281d579457a0ea5287960252/Dockerfile#L10"&gt;https://github.com/ryuheechul/dotfiles-launchpad/blob/2d70fc6a48a4781e281d579457a0ea5287960252/Dockerfile#L10&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using it in a project
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/ryuheechul/jmdstack/tree/master/crossplane"&gt;https://github.com/ryuheechul/jmdstack/tree/master/crossplane&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So much more you can do
&lt;/h2&gt;

&lt;p&gt;So far I'm not using many things like NixOS, nix-darwin, etc. but you can, whenever you want.&lt;/p&gt;

&lt;p&gt;There are also multiple ways of installing your packages even just within Nix ecosystem&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nixos.org/"&gt;nix-os&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nix-community/home-manager"&gt;home-manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nixos.org/manual/nix/unstable/command-ref/nix-env.html"&gt;nix-env&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nixos.org/manual/nix/unstable/command-ref/nix-shell.html"&gt;nix-shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/LnL7/nix-darwin"&gt;nix-darwin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;There is nothing wrong with existing tools depends on your perspective/usage.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And of course, I'm still using other package managers like &lt;code&gt;apt-get&lt;/code&gt; and &lt;code&gt;brew&lt;/code&gt;, &lt;code&gt;asdf&lt;/code&gt;, etc. They are good when trying everything with Nix is not quite smooth, but Nix certainly became my default package manager and reduced the usages of other tools significantly!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm just glad that I've embraced this new way of managing packages and my environments.&lt;/p&gt;

&lt;p&gt;It feels clearer what exactly I need and how it's being installed and what are the dependencies and so on.&lt;/p&gt;

&lt;p&gt;It was hard to feel that way with &lt;code&gt;apt-get&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;I'm not sure if I will ever be a Nix "expert", but I'm pretty sure Nix will be still useful in anyways.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'm also collecting useful links for Nix here, &lt;a href="https://gist.github.com/ryuheechul/a0bd4e4b69565da86301ee8cc26311e1"&gt;https://gist.github.com/ryuheechul/a0bd4e4b69565da86301ee8cc26311e1&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>nix</category>
      <category>darwin</category>
      <category>linux</category>
    </item>
    <item>
      <title>Quickest Way to Run NixOS on Your VMWare Fusion</title>
      <dc:creator>Heechul Ryu</dc:creator>
      <pubDate>Wed, 06 Jan 2021 00:02:11 +0000</pubDate>
      <link>https://dev.to/ryuheechul/quickest-way-to-run-nixos-on-your-vmware-fusion-4dn7</link>
      <guid>https://dev.to/ryuheechul/quickest-way-to-run-nixos-on-your-vmware-fusion-4dn7</guid>
      <description>&lt;p&gt;It is all started from this tweet. &lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1346136404682625024-723" src="https://platform.twitter.com/embed/Tweet.html?id=1346136404682625024"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1346136404682625024-723');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1346136404682625024&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Even though I'm already pretty happy with macOS itself. I was intrigued about using (and learning) NixOS in a way he would.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start using it with VMWARE Fusion
&lt;/h2&gt;

&lt;p&gt;Oh boy. Let me tell you, it's not straightforward at all.&lt;/p&gt;

&lt;p&gt;You can download ISO image from here, &lt;a href="https://nixos.org/download.html" rel="noopener noreferrer"&gt;https://nixos.org/download.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And (attempt to) install it via creating a new VM with the image.&lt;/p&gt;

&lt;p&gt;Please tell me that I wasn't the only one that was completely lost after booting via the (CD) image.&lt;/p&gt;

&lt;p&gt;After clicking this and that and rebooting SEVERAL times, my poor soul later discovered that there is actually no (automatic) installation is provided by this image, unlike Ubuntu! I have to do that all by myself!&lt;/p&gt;

&lt;p&gt;Alright, maybe it's time to learn all the low-level goodies of doing everything from scratch. Let me read the documentation, &lt;a href="https://nixos.org/manual/nixos/stable/index.html#sec-installation" rel="noopener noreferrer"&gt;https://nixos.org/manual/nixos/stable/index.html#sec-installation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You know what, I'm not ready to do that just yet especially when I just wanted to have a taste of what it's like to use it as a guest VM (on VMWare Fusion).&lt;/p&gt;

&lt;p&gt;Thanks to this blog, &lt;a href="https://davedellacosta.com/posts/2019-03-29-why-nixos-is-hard-and-how-to-fix.html" rel="noopener noreferrer"&gt;https://davedellacosta.com/posts/2019-03-29-why-nixos-is-hard-and-how-to-fix.html&lt;/a&gt; I feel better about myself not being able to do this as if it was a trivial thing. Also, it links me to &lt;a href="https://nixos.wiki/wiki/NixOS" rel="noopener noreferrer"&gt;https://nixos.wiki/wiki/NixOS&lt;/a&gt; which introduced me to &lt;a href="https://github.com/jeaye/nixos-in-place" rel="noopener noreferrer"&gt;https://github.com/jeaye/nixos-in-place&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nixos-in-place&lt;/code&gt; sounds all nice but I would still need another VM that is already installed with other distros if I were to avoid installing anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staying lazy
&lt;/h2&gt;

&lt;p&gt;You know what? VMWare actually can import VirtualBox VM and NixOS provides ready-to-run VM on VirtualBox already. Why don't I just import it? &lt;/p&gt;

&lt;p&gt;Yes, it worked.&lt;/p&gt;

&lt;p&gt;Whether you are playing with the pure ISO image or imported VM for VirtualBox, you will soon notice one thing that is very annoying. Which is your mouse gets trapped in VM as soon as you hover your mouse on VM.&lt;/p&gt;

&lt;p&gt;I got a hint here though about what to do. &lt;a href="https://discourse.nixos.org/t/nixos-as-vmware-guest/7441" rel="noopener noreferrer"&gt;https://discourse.nixos.org/t/nixos-as-vmware-guest/7441&lt;/a&gt; which was not very straightforward as a newcomer to NixOS. But I still found out what to do with googling. You will need to add in a configuration file via &lt;code&gt;[sudo] nano /mnt/etc/nixos/configuration.nix&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once you edited that, you can apply this by &lt;code&gt;sudo nixos-rebuild switch&lt;/code&gt;. You will probably also have to reboot your (virtual) machine via &lt;code&gt;reboot&lt;/code&gt;. After that, amazingly your mouse doesn't get trapped anymore 🎉.&lt;/p&gt;

&lt;p&gt;That's good enough for me to feel I accomplished something today, I guess 😅.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Btw, if you didn't know or worried about the cost of VMWare instead of the free of charge that VirtualBox offers, VMWare Fusion actually offers a free license as well, &lt;a href="https://my.vmware.com/web/vmware/evalcenter?p=fusion-player-personal" rel="noopener noreferrer"&gt;https://my.vmware.com/web/vmware/evalcenter?p=fusion-player-personal&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vmware</category>
      <category>nixos</category>
    </item>
    <item>
      <title>My First *.rs Other Than main.rs</title>
      <dc:creator>Heechul Ryu</dc:creator>
      <pubDate>Sat, 05 Dec 2020 11:10:52 +0000</pubDate>
      <link>https://dev.to/ryuheechul/my-first-rs-other-than-main-rs-md3</link>
      <guid>https://dev.to/ryuheechul/my-first-rs-other-than-main-rs-md3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In this post, I assume that you played with Rust at least a little bit.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When you first create a project with &lt;code&gt;cargo init my-project&lt;/code&gt;, this is what you get out of the box.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❯ tree my-project
my-project/
├── src/
│  └── main.rs
└── Cargo.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you start writing code and it may look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/main.rs&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nn"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Greet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// you may have some fields here&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Greet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// let's pretend you have 100 more lines of some functions below&lt;/span&gt;
  &lt;span class="c1"&gt;//&lt;/span&gt;
  &lt;span class="c1"&gt;// fn foo(...) {&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// and there might be other stuff here for `main.rs`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You check if this actually runs by &lt;code&gt;cargo run&lt;/code&gt; and it outputs &lt;code&gt;Hello, world!&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It works OK but there are a couple of issues that may bug you.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📜 the code for &lt;code&gt;Greet&lt;/code&gt; struct is quite long (it's more than 100 lines!)&lt;/li&gt;
&lt;li&gt;🍯 you don't want to couple &lt;code&gt;Greet&lt;/code&gt; struct and the other purpose functioning codes in &lt;code&gt;main.rs&lt;/code&gt; which might happen without realizing if you keep them in the same file for long enough&lt;/li&gt;
&lt;li&gt;🏠 you don't want to read code for &lt;code&gt;Greet&lt;/code&gt; stuff when you want to edit just &lt;code&gt;main.rs&lt;/code&gt; and vice versa&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So now you want the &lt;code&gt;Greet&lt;/code&gt; struct to be on its own file so you moved things and it looks like these now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/main.rs&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nn"&gt;Greet&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// `Greet` struct moved out from here&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/comm.rs (comm for communication)&lt;/span&gt;

&lt;span class="c1"&gt;// there are moved from `main.rs`&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Greet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Greet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&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 &lt;code&gt;cargo run&lt;/code&gt; again but it doesn't work anymore. Does it?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At this point when I search google about how to split a struct into another file, I get all sorts of information and I'm sure they are very helpful but all I wanted to do right now is simply splitting a file into two or more so I can manage the code better. I don't know about you, but I'm not interested in learning about crates and all the other stuff just yet.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;OK, let me see if I can make minimal changes to make it work... and tada!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;  // src/main.rs

  // acknowledge `comm` module which corresponds to `comm.rs`
&lt;span class="gi"&gt;+ mod comm; 
&lt;/span&gt;
  // use `Greet` struct from `comm` module
&lt;span class="gi"&gt;+ use comm::Greet;
&lt;/span&gt;
  fn main() {
    Greet::hello();
  }

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;  // src/comm.rs

  // we add `pub`s for things to be accessible from other files like `main.rs`

- struct Greet {
&lt;span class="gi"&gt;+ pub struct Greet {
&lt;/span&gt;    // ...
  }

  impl Greet {
&lt;span class="gd"&gt;-   fn hello() {
&lt;/span&gt;&lt;span class="gi"&gt;+   pub fn hello() {
&lt;/span&gt;      println!("Hello, world!");
    }

    // ...
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you &lt;code&gt;cargo run&lt;/code&gt; it should work like a charm :)&lt;/p&gt;

&lt;p&gt;You probably have some questions about why &lt;code&gt;mod comm;&lt;/code&gt; corresponds to &lt;code&gt;comm.rs&lt;/code&gt;, and the answer is here, &lt;a href="https://doc.rust-lang.org/rust-by-example/mod/split.html"&gt;https://doc.rust-lang.org/rust-by-example/mod/split.html&lt;/a&gt; and the specific chunk in the link are below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This declaration will look for a file named `my.rs` or `my/mod.rs` and will&lt;/span&gt;
&lt;span class="c1"&gt;// insert its contents inside a module named `my` under this scope&lt;/span&gt;
&lt;span class="k"&gt;mod&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;I hope this was helpful (I actually wrote it for the future myself who always tends to forget particular details). Since I'm still a Rust (re)beginner, I might have not understood things correctly. When you have improvement suggestions on terms and expressions I used here or even a better way to approach the same problem, please let me know!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>module</category>
    </item>
    <item>
      <title>Developing React components with (completely) dark-themed Storybook</title>
      <dc:creator>Heechul Ryu</dc:creator>
      <pubDate>Sun, 28 Jun 2020 20:53:14 +0000</pubDate>
      <link>https://dev.to/ryuheechul/developing-react-components-with-completely-dark-themed-storybook-1g3</link>
      <guid>https://dev.to/ryuheechul/developing-react-components-with-completely-dark-themed-storybook-1g3</guid>
      <description>&lt;p&gt;&lt;em&gt;Hey, this is my first post at Dev.to!!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;I'm a developer but not a professional React (or Web) developer. I've still developed small open source web apps before though because I like Web (tech)!. One of them is called &lt;a href="https://rainist.github.io/galley"&gt;Galley&lt;/a&gt; which was developed in 2017 (why does it feel so old... 😭) and it was for helping my YAML engineering back then.&lt;/p&gt;

&lt;p&gt;Although it was not quite a complex app, I enjoyed developing it by learning and using the new tech like &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;, &lt;a href="https://reasonml.github.io/"&gt;ReasonML&lt;/a&gt;, &lt;a href="https://grommet.io/"&gt;Grommet&lt;/a&gt;, &lt;a href="https://rxjs.dev/guide/overview"&gt;RxJS&lt;/a&gt;,and &lt;a href="https://github.com/rainist/galley#technologies"&gt;others&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'm currently a full-time DevOps Engineer working with &lt;a href="https://kubernetes.io/"&gt;Kubernetes&lt;/a&gt; &amp;amp; &lt;a href="https://helm.sh/"&gt;Helm&lt;/a&gt; and other DevOps tools such as Terraform.&lt;/p&gt;

&lt;p&gt;I recently came up with an idea to build an open-source tool that would help to debug Helm (template) development (to be more efficient at YAML engineering 😅).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;the tool that I mentioned that I wanted to build is actually quite irrelevant for the rest of the post so we can focus on setting the ground up React component dev environment here&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Instead of planning the "perfect" app design first, I wanted to develop the idea further by actually building it.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI stuff
&lt;/h3&gt;

&lt;p&gt;I'm not following very closely with bleeding-edge web tech. So I chose React for a safe bet. I used &lt;code&gt;create-react-app&lt;/code&gt; for the first time to kick start quickly.&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;$ &lt;/span&gt;yarn create react-app darkbook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time I wanted to use a different React UI framework than Grommet. I chose &lt;a href="https://chakra-ui.com/"&gt;Chakra UI&lt;/a&gt; after some research because it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;supports dark mode&lt;/li&gt;
&lt;li&gt;looks nice out of the box&lt;/li&gt;
&lt;li&gt;has no CSS dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  UI first approach for prototyping
&lt;/h3&gt;

&lt;p&gt;Unlike what I did for Galley, I wanted to work on UI parts first before working on any real business logic so that I can concern less of other stuff and focus better on prototyping to enable me to feel what would an app actually could look like.&lt;/p&gt;

&lt;p&gt;At first, I considered using &lt;a href="https://testing-library.com/docs/react-testing-library/intro"&gt;a testing library&lt;/a&gt; just because of the white background of the web page was too bright for me at night - &lt;em&gt;Yeah, my open sourcing activity is happening mostly at night when I'm free of day time duties ✌🏼&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;also because initially, I struggle to get started with Chakra UI with a dark mode which you will see later&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After a while, I quickly realized that the testing library isn't really for visual development. So I started looking for alternatives and eventually I was considering &lt;a href="https://storybook.js.org/"&gt;Storybook&lt;/a&gt; for the first time.&lt;/p&gt;

&lt;p&gt;Every new stuff can be intimidating at all different levels. To overcome this, I first made myself familiar with Storybook by going through an official tutorial and it was easy and simple enough to follow. Storybook itself also supports dark mode which is another great point!&lt;/p&gt;

&lt;p&gt;After the tutorial, I integrated it into the app I just generated with &lt;code&gt;create-react-app&lt;/code&gt; earlier.&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;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;darkbook
&lt;span class="nv"&gt;$ &lt;/span&gt;npx &lt;span class="nt"&gt;-p&lt;/span&gt; @storybook/cli sb init
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commands above will open the basic light-themed Storybook web page.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I played with some code files under &lt;code&gt;src/stories&lt;/code&gt; to understand how it actually works and I discovered that Storybook is quite well structured and easy to use even though it was new to me.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I also added &lt;code&gt;manager.js&lt;/code&gt; to enable the dark mode on Storybook.&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="c1"&gt;// .storybook/manager.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addons&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/addons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;themes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@storybook/theming&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;addons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;themes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dark&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;
  
  
  Working with Chakra UI
&lt;/h2&gt;

&lt;p&gt;If you are not familiar with it, I encourage you to visit &lt;a href="https://chakra-ui.com/getting-started"&gt;the website&lt;/a&gt;. It looks quite nice.&lt;/p&gt;

&lt;p&gt;I will be honest with you though. Even though it looked nice and the documentation initially seemed fine enough, later I actually struggled quite a bit. Especially when I was trying to enable the dark mode by default.&lt;/p&gt;

&lt;p&gt;And that struggle was actually why I decided to post this article hoping this post might be helpful for the first time Chakra UI users like me.&lt;/p&gt;

&lt;h3&gt;
  
  
  The glimpse of struggles
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;which you can skip if you are not interested to hear about&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I followed the getting started page which essentially running 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;# I recommend you not to do this though and you will see why&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @chakra-ui/core @emotion/core @emotion/styled emotion-theming
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And tried to enable the dark mode by default by following this page, &lt;a href="https://chakra-ui.com/color-mode"&gt;https://chakra-ui.com/color-mode&lt;/a&gt;.&lt;br&gt;
However, I couldn't find the way to do it except for toggling the light and the dark mode (which I didn't want)&lt;/p&gt;

&lt;p&gt;After trying and looking at this and that, I finally discovered &lt;a href="https://github.com/chakra-ui/chakra-ui/issues/692#issuecomment-628911965"&gt;this issue&lt;/a&gt;, which shows a history of struggles of others as well for enabling dark mode by default. And it also was a hint that indicating it might be dealt with the version &lt;code&gt;1.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So I started looking at &lt;a href="https://github.com/chakra-ui/chakra-ui/releases"&gt;Releases&lt;/a&gt; page and found &lt;a href="https://github.com/chakra-ui/chakra-ui/releases/tag/%40chakra-ui%2Fcore"&gt;the pre release&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This pre-release looked much more promising than the current stable version and the instruction made more sense so I followed the instruction from it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Getting actually oriented with Chakra UI
&lt;/h3&gt;

&lt;p&gt;I basically installed Chakra UI like this instead.&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;$ &lt;/span&gt;yarn add @chakra-ui/core@1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You will probably be prompted to choose the correct version and I chose &lt;code&gt;1.0.0-next.2&lt;/code&gt; which was the latest pre-release at the time of writing this post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To enable the dark mode for every Story, I added &lt;code&gt;preview.js&lt;/code&gt;.&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="c1"&gt;// .storybook/preview.js&lt;/span&gt;
&lt;span class="c1"&gt;// which is modified off from https://github.com/chakra-ui/chakra-ui/blob/657103491bc70194fdd62dcf6ef7e16648c2a6c3/.storybook/preview.tsx&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CSSReset&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@chakra-ui/css-reset&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../src/chakra&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ChakraProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Box&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@chakra-ui/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;addDecorator&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newTheme&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="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;initialColorMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;useSystemColorMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Chakra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ChakraProvider&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newTheme&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CSSReset&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Box&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;5&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="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Box&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ChakraProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;addDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;StoryFn&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Chakra&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StoryFn&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Chakra&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;.storybook/preview.js&lt;/code&gt; basically allows you to have the "layout" page for every Story. Now it feels like we are going somewhere.&lt;/p&gt;

&lt;p&gt;Not so fast. Don't forget to actually fetch the theme.&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;# in ./src&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npx chakra-cli init &lt;span class="nt"&gt;--theme&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see there is a lot of files downloaded that are required to be committed to your own repo and supposedly this will make it a lot easier to customize your own theme according to the Chakra UI and I agree with it too.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Although this can be a bit of bad news for minimalists like me since I also didn't plan to change much of the theme yet. Perhaps let's ignore this issue and be generous about it for now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are almost there. It's time to make a few changes to stories to actually use Chakra UI components&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; src/stories/1-Button.stories.js

-import { Button } from '@storybook/react/demo';
&lt;span class="gi"&gt;+import { Button } from '@chakra-ui/core';
&lt;/span&gt;
# src/stories/0-Welcome.stories.js

-import { Welcome } from '@storybook/react/demo';
&lt;span class="gi"&gt;+import { Box, Link } from '@chakra-ui/core'
+
+const Welcome = ({showApp}) =&amp;gt; (
+  &amp;lt;&amp;gt;
+    &amp;lt;Box&amp;gt;
+      This is a custom welcome message using Chakra UI
+    &amp;lt;/Box&amp;gt;
+    &amp;lt;Link onClick={showApp} color="teal.500"&amp;gt;
+      Let's go to see the button
+    &amp;lt;/Link&amp;gt;
+  &amp;lt;/&amp;gt;
+)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Was it enough?&lt;/p&gt;

&lt;h3&gt;
  
  
  Yes, it was!
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Welcome /&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3j_VoowI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pchgoy6l8gjxfrjossz6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3j_VoowI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pchgoy6l8gjxfrjossz6.png" alt="Welcome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt; with text&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tzf_pTXJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e5lzlxtmy48zwu156koj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tzf_pTXJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e5lzlxtmy48zwu156koj.png" alt="Button Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt; with emoji&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nR3jUGEY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/se21c9d91ezr7kvh6vwq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nR3jUGEY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/se21c9d91ezr7kvh6vwq.png" alt="Button Emoji"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means I finally managed to fully set up the environment that I can develop UI components in a way it's completely dark-themed!!!&lt;/p&gt;

&lt;p&gt;Here is &lt;a href="https://github.com/ryuheechul/helm-live/tree/chakra-storybook"&gt;the repo&lt;/a&gt; that you can take a look for the code and commits in case you want to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Storybook wasn't much of overhead even though it was a new tool to me&lt;/li&gt;
&lt;li&gt;enabling dark mode was much more of a (mental) hassle than I thought but I'm quite happy now that it works!&lt;/li&gt;
&lt;li&gt;I'm quite excited to create all the new components and get my hands dirty with all these tools&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Misc.
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;if you don't see stories that have a dark background, make sure to try different browsers.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In my case, Safari kept resetting the page back to the light mode after few milliseconds somehow. So I switched to chrome and worked.&lt;br&gt;
&lt;em&gt;Also, you might need to refresh the page or restart the storybook.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it for now and thanks for reading!&lt;/p&gt;

</description>
      <category>react</category>
      <category>storybook</category>
      <category>chakraui</category>
      <category>darkmode</category>
    </item>
  </channel>
</rss>
