nextjs_daan.fyi.rss.xml - sfeed_tests - sfeed tests and RSS and Atom files
 (HTM) git clone git://git.codemadness.org/sfeed_tests
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       nextjs_daan.fyi.rss.xml (83182B)
       ---
            1 <?xml version="1.0" encoding="utf-8"?>
            2 <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
            3     <channel>
            4         <title>Daan Debie</title>
            5         <link>https://www.daan.fyi/</link>
            6         <description>This is a feed of all posts on the website of Daan Debie</description>
            7         <lastBuildDate>Mon, 29 Nov 2021 20:04:24 GMT</lastBuildDate>
            8         <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
            9         <generator>NextJS + feed package</generator>
           10         <language>en</language>
           11         <image>
           12             <title>Daan Debie</title>
           13             <url>https://www.daan.fyi/images/banner.png</url>
           14             <link>https://www.daan.fyi/</link>
           15         </image>
           16         <copyright>Copyright 2021 - Daan Debie</copyright>
           17         <item>
           18             <title><![CDATA[Customzing Pyenv Behavior with Hooks]]></title>
           19             <link>https://www.daan.fyi/writings/pyenv-hooks</link>
           20             <guid>https://www.daan.fyi/writings/pyenv-hooks</guid>
           21             <pubDate>Sun, 28 Nov 2021 00:00:00 GMT</pubDate>
           22             <description><![CDATA[You can customize the behavior of pyenv or its plugins - like pyenv virtualenv - by using hooks. These are simple (bash) scripts that are run at specific points when pyenv commands are run.]]></description>
           23             <content:encoded><![CDATA[<p class="chakra-text css-rszk63">I use <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/pyenv/pyenv">pyenv</a> to manage different Python versions on my laptop. It
           24 also comes with an <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/pyenv/pyenv-virtualenv">official plugin</a> that lets you manage
           25 <em>virtualenvs</em> through pyenv, which I find very convenient. Basically, virtualenvs are treated as
           26 just different Python versions by pyenv.</p> <p class="chakra-text css-rszk63">One thing that bothered me is that, whenever I create a new virtualenv and use <code class="chakra-code css-4m8w8z">pip</code> in it, I am
           27 inevitably greeted by a message telling me <code class="chakra-code css-4m8w8z">pip</code> is out-of-date:</p><pre><code>WARNING: You are using pip version 21.2.3; however, version 21.3.1 is available.
           28 You should consider upgrading via the '~/.pyenv/versions/3.10.0/envs/test/bin/python3.10 -m pip install --upgrade pip' command.
           29 </code></pre> <p class="chakra-text css-rszk63">So I end up always having to upgrade pip after creating a new virtualenv. Wouldn’t it be nice if
           30 this could be automated?</p> <p class="chakra-text css-rszk63">Turns out, we actually <em>can</em> by leveraging <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/pyenv/pyenv/wiki/Authoring-plugins#pyenv-hooks"><em>pyenv hooks</em></a>.</p> <h2 class="chakra-heading css-13bekiy" id="pyenv-hooks"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/pyenv-hooks#pyenv-hooks"><span class="icon icon-link"></span></a>Pyenv Hooks</h2> <p class="chakra-text css-rszk63">pyenv hooks are scripts that are executed by pyenv whenever certain commands are run. These can be
           31 regular pyenv commands like <code class="chakra-code css-4m8w8z">pyenv install</code> or <code class="chakra-code css-4m8w8z">pyenv rehash</code> for example. But what is not
           32 apparent from the pyenv documentation, is that you can also create hooks for plugins, like
           33 <code class="chakra-code css-4m8w8z">pyenv virtualenv</code>.</p> <p class="chakra-text css-rszk63">You can create a hook by creating a script at the following location:</p><pre class="language-bash"><code class="language-bash"><span class="token variable">$PYENV_ROOT</span>/pyenv.d/<span class="token operator"><</span>hook-name<span class="token operator">></span>/<span class="token operator"><</span>whatever<span class="token operator">></span>.bash
           34 </code></pre> <p class="chakra-text css-rszk63"> <code class="chakra-code css-4m8w8z">hook-name</code> here can be any of: <code class="chakra-code css-4m8w8z">exec</code>, <code class="chakra-code css-4m8w8z">rehash</code>, <code class="chakra-code css-4m8w8z">which</code>, <code class="chakra-code css-4m8w8z">install</code> — which are all regular pyenv
           35 commands — but it can also be a plugin command, like <code class="chakra-code css-4m8w8z">virtualenv</code>. The filename of the script doesn’t
           36 matter, and neither does the extension. I use <code class="chakra-code css-4m8w8z">.bash</code> here to make it explicit that this is a bash
           37 script, but pyenv hooks can be written in any language.</p> <p class="chakra-text css-rszk63">To create a hook that upgrades <code class="chakra-code css-4m8w8z">pip</code> and some other default packages, you can create a new script
           38 as follows:</p><pre class="language-bash"><code class="language-bash"><span class="token function">mkdir</span> -p <span class="token variable">$PYENV_ROOT</span>/pyenv.d/virtualenv/
           39 <span class="token variable">$EDITOR</span> <span class="token variable">$PYENV_ROOT</span>/pyenv.d/virtualenv/after.bash
           40 </code></pre> <p class="chakra-text css-rszk63">Where <code class="chakra-code css-4m8w8z">$EDITOR</code> is your favorite editor (like <code class="chakra-code css-4m8w8z">vim</code>, <strong>RIGHT?!</strong>)</p> <p class="chakra-text css-rszk63">Then add the following contents:</p><pre class="language-bash"><code class="language-bash">after_virtualenv <span class="token string">'PYENV_VERSION="<span class="token variable">$VIRTUALENV_NAME</span>" pyenv-exec pip install --upgrade pip setuptools wheel'</span>
           41 </code></pre> <p class="chakra-text css-rszk63"> <code class="chakra-code css-4m8w8z">after_virtualenv</code> is the command that tells pyenv <em>when</em> to execute the following command. In this
           42 case its defined by the <code class="chakra-code css-4m8w8z">pyenv virtualenv</code> plugin. First we set the pyenv version to the name
           43 of the virtualenv we just created. This is set by pyenv virtualenv as <code class="chakra-code css-4m8w8z">$VIRTUALENV_NAME</code>. Then we
           44 install/upgrade <code class="chakra-code css-4m8w8z">pip</code> itself and <code class="chakra-code css-4m8w8z">setuptools</code> and <code class="chakra-code css-4m8w8z">wheel</code>.</p> <p class="chakra-text css-rszk63">That is all there is to it! Now any time you create a new virtualenv using <code class="chakra-code css-4m8w8z">pyenv virtualenv</code>, the
           45 aforementioned packages will be automatically upgraded after the virtualenv was created.</p><span></span>]]></content:encoded>
           46         </item>
           47         <item>
           48             <title><![CDATA[Static Duck Typing in Python with Protocols]]></title>
           49             <link>https://www.daan.fyi/writings/python-protocols</link>
           50             <guid>https://www.daan.fyi/writings/python-protocols</guid>
           51             <pubDate>Fri, 19 Nov 2021 00:00:00 GMT</pubDate>
           52             <description><![CDATA[Duck typing is considered to be one of Python's strengths. If you want to have the benefits of duck typing but also want your types statically checked, Protocols offer an excellent solution.]]></description>
           53             <content:encoded><![CDATA[<p class="chakra-text css-rszk63">At <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://source.ag/">Source</a>, we write most of our code in Python. It’s a language that both our
           54 Software Engineers and Data Scientists are equally at home in. It’s easy to be productive in Python,
           55 in part due to its dynamic nature. Not having to think too much about the types of your variables
           56 and functions, can make it easier to experiment, especially if you’re not entirely clear yet
           57 on how you’re going to solve a particular problem.</p> <p class="chakra-text css-rszk63">When moving our code to production however, we want to have more guarantees about the behaviour of
           58 our code. Writing (unit) tests is one way to get those guarantees, but we also make heavy use of <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.python.org/dev/peps/pep-0484/">type hints</a> to give us more confidence in our code.
           59 Type hints can also provide a productivity boost, because not only humans can reason better about
           60 type hinted code, your editor can as well!</p> <p class="chakra-text css-rszk63">Sometimes though, using type hints everywhere can feel like you’re losing out on a lot of the magic
           61 and speed that a dynamic type system brings you. One particular trait of dynamic typing that is
           62 pretty idiomatic in Python, is <strong>duck typing</strong>.</p> <h2 class="chakra-heading css-13bekiy" id="duck-typing"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/python-protocols#duck-typing"><span class="icon icon-link"></span></a>Duck Typing</h2> <p class="chakra-text css-rszk63"> <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://en.wikipedia.org/wiki/Duck_typing">Duck typing</a> is a philosophy in programming where you
           63 care more about the behaviour and properties of an object than its stated type to determine if that
           64 object is useful in a certain situation. Duck typing is inspired by the <em>duck test</em>:</p> <blockquote class="css-p56y4k"> <p class="chakra-text css-rszk63">If it walks like a duck and it quacks like a duck, then it must be a duck</p></blockquote> <p class="chakra-text css-rszk63">In practice this means that when you write a function that receives a certain input, you care only
           65 about the behaviour and/or attributes of that input, not the explicit <em>type</em> of that input.</p> <p class="chakra-text css-rszk63">One interesting question that arises is: if you don’t want to be strict about the type of the
           66 parameters a function receives, are there still any <em>static type guarantees</em> to be had?</p> <p class="chakra-text css-rszk63">And the other way around is interesting as well: if you have a function with statically typed
           67 inputs, can you <em>loosen up</em> those parameters to make the function more universally useful, the way
           68 duck typing does?</p> <p class="chakra-text css-rszk63">As it turns out, Python provides a neat way to have our cake and eat it too!</p> <h2 class="chakra-heading css-13bekiy" id="protocols-to-the-rescue"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/python-protocols#protocols-to-the-rescue"><span class="icon icon-link"></span></a>Protocols to the Rescue</h2> <p class="chakra-text css-rszk63">When reviewing some code recently, I came across a function that looked roughly like this:</p><pre class="language-python"><code class="language-python"><span class="token keyword">def</span> <span class="token function">calculate_windowed_avg</span><span class="token punctuation">(</span>
           69         measurements<span class="token punctuation">:</span> Union<span class="token punctuation">[</span>List<span class="token punctuation">[</span>TemperatureMeasurement<span class="token punctuation">]</span><span class="token punctuation">,</span> List<span class="token punctuation">[</span>HumidityMeasurement<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
           70         window_size<span class="token punctuation">:</span> timedelta<span class="token punctuation">,</span>
           71         field_name<span class="token punctuation">:</span> <span class="token builtin">str</span>
           72     <span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> Dict<span class="token punctuation">[</span>datetime<span class="token punctuation">,</span> <span class="token builtin">float</span><span class="token punctuation">]</span><span class="token punctuation">:</span>
           73     window_upper_bound <span class="token operator">=</span> measurements<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>timestamp <span class="token operator">+</span> window_size
           74     current_window <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
           75     window_averages <span class="token operator">=</span> OrderedDict<span class="token punctuation">(</span><span class="token punctuation">)</span>
           76     <span class="token keyword">for</span> m <span class="token keyword">in</span> measurements<span class="token punctuation">:</span>
           77         <span class="token comment"># various calculations happen here</span>
           78         <span class="token comment"># based on the timestamp of each measurement</span>
           79         <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
           80     <span class="token keyword">return</span> window_averages
           81 </code></pre> <p class="chakra-text css-rszk63">The goal of this function is to calculate the average of a certain field (identified by <code class="chakra-code css-4m8w8z">field_name</code>) in a rolling window. At the time of writing this function, we were using it for
           82 <code class="chakra-code css-4m8w8z">TemperatureMeasurement</code> and <code class="chakra-code css-4m8w8z">HumidityMeasurement</code>, but it is very likely we’ll want to use it for
           83 different types of measurements in the future.</p> <p class="chakra-text css-rszk63">If we look closely at how the function uses the input, it turns out that the only thing we want to
           84 be guaranteed of, is that the items we pass into the function have a <code class="chakra-code css-4m8w8z">timestamp</code> field. So instead
           85 of specifying each different type that has adheres to this contract, we’d like to tell the type
           86 checker that we only care about having a <code class="chakra-code css-4m8w8z">timestamp</code> field to work with.</p> <p class="chakra-text css-rszk63"> <code class="chakra-code css-4m8w8z">Protocol</code> from the <code class="chakra-code css-4m8w8z">typing</code> module lets us do that. Just like with duck typing, <strong>Protocols</strong> let
           87 you specify the behaviour or attributes you expect, without caring about the type. Here is what
           88 that looks like:</p><pre class="language-python"><code class="language-python{4,5,8}"><span class="token keyword">from</span> typing <span class="token keyword">import</span> Protocol<span class="token punctuation">,</span> List<span class="token punctuation">,</span> Dict
           89 <span class="token keyword">from</span> datetime <span class="token keyword">import</span> datetime
           90 
           91 <div class="mdx-marker"><span class="token keyword">class</span> <span class="token class-name">MeasurementLike</span><span class="token punctuation">(</span>Protocol<span class="token punctuation">)</span><span class="token punctuation">:</span>
           92 </div><div class="mdx-marker">    timestamp<span class="token punctuation">:</span> datetime
           93 </div>
           94 <span class="token keyword">def</span> <span class="token function">calculate_windowed_avg</span><span class="token punctuation">(</span>
           95 <div class="mdx-marker">        measurements<span class="token punctuation">:</span> List<span class="token punctuation">[</span>MeasurementLike<span class="token punctuation">]</span><span class="token punctuation">,</span>
           96 </div>        window_size<span class="token punctuation">:</span> timedelta<span class="token punctuation">,</span>
           97         field_name<span class="token punctuation">:</span> <span class="token builtin">str</span>
           98     <span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> Dict<span class="token punctuation">[</span>datetime<span class="token punctuation">,</span> <span class="token builtin">float</span><span class="token punctuation">]</span><span class="token punctuation">:</span>
           99     window_upper_bound <span class="token operator">=</span> measurements<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">.</span>timestamp <span class="token operator">+</span> window_size
          100     <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
          101 </code></pre> <p class="chakra-text css-rszk63">Now the type checker doesn’t know <em>exactly</em> what the type is of whatever is provided as <code class="chakra-code css-4m8w8z">measurements</code> but it <em>does</em> know what those items have a <code class="chakra-code css-4m8w8z">timestamp</code> field because they adhere to
          102 the <code class="chakra-code css-4m8w8z">MeasurementLike</code> Protocol.</p> <p class="chakra-text css-rszk63">In a sense, a Protocol acts like one side of an <em>Interface</em> as we know it from Java or Typescript.
          103 Instead of having to specify the behaviour and properties both on a <em>type</em> and on the functions
          104 that use it, we only have to specify it on a function, without caring about the types of the objects
          105 that are provided to the function.</p> <h2 class="chakra-heading css-13bekiy" id="protocol-and-generics"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/python-protocols#protocol-and-generics"><span class="icon icon-link"></span></a>Protocol and Generics</h2> <p class="chakra-text css-rszk63">You can also use Protocols together with <code class="chakra-code css-4m8w8z">TypeVar</code> for even more generic functions that are still
          106 type checked to some extend. One use-case that comes to mind, is when you don’t care about the
          107 input type to a function, as long as it follows a protocol, but you also want to guarantee that
          108 the <em>output</em> of the function is of the same type as the <em>input</em>, no matter what the exact type is.</p> <p class="chakra-text css-rszk63">This works as follows:</p><pre class="language-python"><code class="language-python"><span class="token keyword">from</span> typing <span class="token keyword">import</span> Protocol<span class="token punctuation">,</span> TypeVar
          109 <span class="token keyword">from</span> datetime <span class="token keyword">import</span> datetime
          110 
          111 <span class="token keyword">class</span> <span class="token class-name">MeasurementLike</span><span class="token punctuation">(</span>Protocol<span class="token punctuation">)</span><span class="token punctuation">:</span>
          112     timestamp<span class="token punctuation">:</span> datetime
          113 
          114 M <span class="token operator">=</span> TypeVar<span class="token punctuation">(</span><span class="token string">'M'</span><span class="token punctuation">,</span> bound<span class="token operator">=</span>MeasurementLike<span class="token punctuation">)</span>
          115 
          116 <span class="token keyword">def</span> <span class="token function">measurement_as_timezone</span><span class="token punctuation">(</span>measurement<span class="token punctuation">:</span> M<span class="token punctuation">,</span> tz<span class="token punctuation">:</span> tzinfo<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> M<span class="token punctuation">:</span>
          117     measurement<span class="token punctuation">.</span>timestamp <span class="token operator">=</span> measurement<span class="token punctuation">.</span>timestamp<span class="token punctuation">.</span>astimezone<span class="token punctuation">(</span>tz<span class="token punctuation">)</span>
          118     <span class="token keyword">return</span> measurement
          119 </code></pre> <p class="chakra-text css-rszk63">Here we create a function that takes any object that has a <code class="chakra-code css-4m8w8z">timestamp</code> field and guarantees that
          120 the output will be of the same type as the input.</p> <h2 class="chakra-heading css-13bekiy" id="conclusion"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/python-protocols#conclusion"><span class="icon icon-link"></span></a>Conclusion</h2> <p class="chakra-text css-rszk63">Protocols in Python provide a nice way to use duck typing while still having some static type
          121 guarantees. You can define contracts for your functions without caring too much about the actual
          122 types of your inputs.</p> <hr aria-orientation="horizontal" class="chakra-divider css-9153ub"/> <p class="chakra-text css-rszk63"><em>Update on 2021–11–23: There was a wrong type annotation in this article, as <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=29315363">pointed out by
          123 <strong>ragebol</strong> on Hacker News</a>, which is now fixed</em></p><span></span>]]></content:encoded>
          124         </item>
          125         <item>
          126             <title><![CDATA[How to Add an Rss Feed to a Nextjs Blog]]></title>
          127             <link>https://www.daan.fyi/writings/rss</link>
          128             <guid>https://www.daan.fyi/writings/rss</guid>
          129             <pubDate>Tue, 05 Oct 2021 00:00:00 GMT</pubDate>
          130             <description><![CDATA[RSS is an important feature to give your content maximum exposure while also retaining control over your content. This post shows how to add syndication feeds to a statically generated NextJS site]]></description>
          131             <content:encoded><![CDATA[<p class="chakra-text css-rszk63">Today, I released a new version of my website with only one new feature: <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://en.wikipedia.org/wiki/Web_syndication">syndication</a> through RSS, Atom and JSON Feed. Even
          132 though <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://techcrunch.com/2018/04/07/rss-is-undead/">by some accounts</a>, RSS
          133 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://mjtsai.com/blog/2019/12/26/apple-news-no-longer-supports-rss/">seems to be dead</a>,
          134 I strongly believe RSS is an important feature in the fight to keep ownership over your own content
          135 while also increasing exposure. The way I approach publishing and sharing my content, is called
          136 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://indieweb.org/POSSE">POSSE</a>:</p> <blockquote class="css-p56y4k"> <p class="chakra-text css-rszk63"><strong>Publish (on your) Own Site, Syndicate Elsewhere</strong>.</p></blockquote> <p class="chakra-text css-rszk63">RSS is an important part of that strategy.</p> <p class="chakra-text css-rszk63">Luckily, I’m not the only one who values RSS. <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=20813021">There</a>
          137 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=23212812">are</a> <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=26014344">others</a></p> <p class="chakra-text css-rszk63">In this article I want to share how I implemented syndication feeds in my <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/">NextJS-powered</a> website.</p> <h2 class="chakra-heading css-13bekiy" id="options-and-requirements"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#options-and-requirements"><span class="icon icon-link"></span></a>Options and Requirements</h2> <p class="chakra-text css-rszk63">I did some Googling to see how other NextJS users were generating RSS feeds, and there turned out
          138 to be many people that had solved this particular problem <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.google.com/search?q=rss+feed+nextjs">and wrote about it</a>
          139 I found a couple of different approaches to generating and rendering RSS feeds in NextJS:</p> <p class="chakra-text css-rszk63"><strong>Generating feeds</strong>:</p> <ul role="list" class="css-11041dp"><li class="css-0">Hand-build the required XML using templated strings 🤢</li><li class="css-0">Use a library to do it for you. The most popular library for this in the JS ecosystem seems to be <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.npmjs.com/package/feed"><em>feed</em></a> 🤩</li></ul> <p class="chakra-text css-rszk63"><strong>Rendering feeds</strong>:</p> <ul role="list" class="css-11041dp"><li class="css-0">Use <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering">Server-side rendering</a><ul role="list" class="css-11041dp"><li class="css-0">Advantages:<ul role="list" class="css-11041dp"><li class="css-0">Create dynamic feeds (more on that later) that can be different for each visitor</li><li class="css-0">Using NextJS pages to represent feeds feels natural in the NextJS way of doing things</li></ul></li><li class="css-0">Disadvantages:<ul role="list" class="css-11041dp"><li class="css-0">You can’t generate the website statically anymore (at least parts of it remain dynamic),
          140 which reduces performance
          141 As a side note: from a development perspective, server-side rendered pages and statically generated
          142 pages in NextJS are so similar that the difference doesn’t matter</li></ul></li></ul></li><li class="css-0">Use <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation">Static generation</a><ul role="list" class="css-11041dp"><li class="css-0">Advantages:<ul role="list" class="css-11041dp"><li class="css-0">Because the feeds are generated at build time, the site remains snappy</li></ul></li><li class="css-0">Disadvantages<ul role="list" class="css-11041dp"><li class="css-0">You cannot set the <code class="chakra-code css-4m8w8z">Content-Type</code> header for statically generated pages, so you can’t serve
          143 those pages as <code class="chakra-code css-4m8w8z">application/rss+xml</code>. I’m not how big of a problem this is and what black
          144 magic <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://vercel.com/">Vercel</a> applies when serving my NextJS site</li></ul></li></ul></li></ul> <h3 class="chakra-heading css-inve47" id="picking-the-requirements"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#picking-the-requirements"><span class="icon icon-link"></span></a>Picking the Requirements</h3> <p class="chakra-text css-rszk63">After looking at the options, I decided on the following requirements for my feeds:</p> <ul role="list" class="css-11041dp"><li class="css-0">I want to go for statically generated feeds, to keep my site fast and the implementation simple</li><li class="css-0">Support for <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://en.wikipedia.org/wiki/RSS">RSS</a>,
          145 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://en.wikipedia.org/wiki/Atom_(Web_standard)">Atom</a> and <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.jsonfeed.org/">JSON Feed</a></li><li class="css-0">I want to include the <strong>complete blog post contents</strong> in the feeds. This is an important one
          146 because I personally really hate it when my RSS reader only shows me a summary of a post and
          147 I have to go the the website to read all of it.
          148 Caveat though: my website is built using MDX, so I might include components in the future
          149 that are not easily convertible to static HTML without Javascript enabled. In that case,
          150 readers will have to click through to my site.</li></ul> <h2 class="chakra-heading css-13bekiy" id="implementation"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#implementation"><span class="icon icon-link"></span></a>Implementation</h2> <p class="chakra-text css-rszk63">As per my requirements, I wanted to generate the feeds at build time. But as mentioned before,
          151 NextJS doesn’t support setting the <code class="chakra-code css-4m8w8z">Content-Type</code> header for statically generated pages.
          152 The alternative that many people use, is to have a separate script generate your feeds and
          153 writing them to the public folder where all other static assets such as images are stored as well.
          154 That way, the feeds would be served as static assets instead of statically generated pages — which,
          155 from the browsers perspective doesn’t make a difference!</p> <p class="chakra-text css-rszk63">I found a <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://ashleemboyer.com/how-i-added-an-rss-feed-to-my-nextjs-site">good explanation by Ashlee Boyer</a>
          156 of this technique.</p> <p class="chakra-text css-rszk63">My plan:</p> <ol role="list" class="css-4qdgui"><li class="css-0">Write script to generate feeds, using the <em>feed</em> library from NPM</li><li class="css-0">Run this script as a <code class="chakra-code css-4m8w8z">postbuild</code> step so it would always be invoked after building the site
          157 using <code class="chakra-code css-4m8w8z">npm run build</code> (this happens not only locally, but also when Vercel deploys my site)</li></ol> <h3 class="chakra-heading css-inve47" id="problem-1-running-typescript-modules-is-hard"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#problem-1-running-typescript-modules-is-hard"><span class="icon icon-link"></span></a>Problem 1: Running Typescript Modules Is Hard</h3> <p class="chakra-text css-rszk63">I immediately hit a snag with (1), because I couldn’t manage to use ES6/Typescript modules in a
          158 script run outside of my normal website code.</p> <p class="chakra-text css-rszk63">I’m using Typescript, and apparently <code class="chakra-code css-4m8w8z">ts-node</code>, the tool to run Typescript files, doesn’t support
          159 modules. Writing the script in Javascript wasn’t really an option for me because I wanted to reuse
          160 a lot of logic that I already wrote for reading and parsing MDX files in the website itself.</p> <h4 class="chakra-heading css-198tvf7" id="solution"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#solution"><span class="icon icon-link"></span></a>Solution</h4> <p class="chakra-text css-rszk63">I decided to follow the route that Ashlee Boyer suggests in her blog post and sneak in the
          161 function to generate my feeds as a “stowaway” in the <code class="chakra-code css-4m8w8z">getStaticProps</code> function of my index
          162 page. This works beautifully!</p><div class="remark-code-title">pages/index.tsx</div><pre class="language-typescript"><code class="language-typescript"><span class="token keyword">export</span> <span class="token keyword">const</span> getStaticProps<span class="token operator">:</span> <span class="token function-variable function"><span class="token maybe-class-name">GetStaticProps</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> <span class="token punctuation">{</span>
          163     <span class="token function">generateMainFeeds</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
          164     <span class="token keyword">const</span> lastPosts <span class="token operator">=</span> <span class="token function">getAllPostsFrontMatter</span><span class="token punctuation">(</span><span class="token string">'blog'</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
          165     <span class="token keyword">return</span> <span class="token punctuation">{</span>
          166         props<span class="token operator">:</span> <span class="token punctuation">{</span>
          167             lastPosts<span class="token punctuation">,</span>
          168         <span class="token punctuation">}</span><span class="token punctuation">,</span>
          169     <span class="token punctuation">}</span><span class="token punctuation">;</span>
          170 <span class="token punctuation">}</span><span class="token punctuation">;</span>
          171 </code></pre> <h3 class="chakra-heading css-inve47" id="problem-2-including-the-full-content-in-the-feeds"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#problem-2-including-the-full-content-in-the-feeds"><span class="icon icon-link"></span></a>Problem 2: Including the Full Content in the Feeds</h3> <p class="chakra-text css-rszk63">The code of my website already supported translating MDX files into valid JSX to be rendered
          172 by React. But how to generate valid HTML from that content and include it in the feeds?</p> <h4 class="chakra-heading css-198tvf7" id="solution-1"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#solution-1"><span class="icon icon-link"></span></a>Solution</h4> <p class="chakra-text css-rszk63">I couldn’t find many examples of this, but did find out about <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://reactjs.org/docs/react-dom-server.html#rendertostaticmarkup"> <code class="chakra-code css-4m8w8z">ReactDOMServer.renderToStaticMarkup</code></a>.
          173 This function will take a bunch of React components and render them into HTML. This is what is
          174 used by many React server-side rendering solutions <em>(maybe also by NextJS?)</em> and works perfectly
          175 here as well.</p> <p class="chakra-text css-rszk63">One caveat: if your content contains internal links — which are often relative links — then you
          176 have to be mindful that those relative links are meaningless in the context of an RSS feed.
          177 The way I solved this is by doing some regex-based replacements on the generated HTML.</p> <p class="chakra-text css-rszk63">The complete content generation part looks like this:</p><div class="remark-code-title">lib/feeds.tsx</div><pre class="language-typescript"><code class="language-typescript"><span class="token keyword">const</span> url <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseUrl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/blog/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>post<span class="token punctuation">.</span><span class="token property-access">frontMatter</span><span class="token punctuation">.</span><span class="token property-access">slug</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
          178 <span class="token keyword">const</span> htmlContent <span class="token operator">=</span> <span class="token maybe-class-name">ReactDOMServer</span><span class="token punctuation">.</span><span class="token method function property-access">renderToStaticMarkup</span><span class="token punctuation">(</span>
          179     <span class="token operator"><</span><span class="token maybe-class-name">ChakraProvider</span> resetCSS theme<span class="token operator">=</span><span class="token punctuation">{</span>theme<span class="token punctuation">}</span><span class="token operator">></span>
          180         <span class="token operator"><</span><span class="token maybe-class-name">MDXRemote</span> <span class="token punctuation">{</span><span class="token spread operator">...</span>post<span class="token punctuation">.</span><span class="token property-access">mdxSource</span><span class="token punctuation">}</span> components<span class="token operator">=</span><span class="token punctuation">{</span><span class="token maybe-class-name">MDXComponents</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span>
          181     <span class="token operator"><</span><span class="token operator">/</span><span class="token maybe-class-name">ChakraProvider</span><span class="token operator">></span>
          182     <span class="token punctuation">.</span><span class="token method function property-access">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">href="\/#</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">href="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>url<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">#</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
          183     <span class="token punctuation">.</span><span class="token method function property-access">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">href="\/</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">href="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseUrl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
          184     <span class="token punctuation">.</span><span class="token method function property-access">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">src="\/</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">src="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>baseUrl<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
          185 <span class="token punctuation">)</span>
          186 </code></pre> <h3 class="chakra-heading css-inve47" id="problem-3-getting-rid-of-style-information"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#problem-3-getting-rid-of-style-information"><span class="icon icon-link"></span></a>Problem 3: Getting Rid of Style Information</h3> <p class="chakra-text css-rszk63">My site uses <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://chakra-ui.com/">Chakra UI</a> for theming, which uses
          187 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://emotion.sh/">Emotion</a> — a CSS-in-JS library — under the hood. Emotion will happily
          188 render tons of <code class="chakra-code css-4m8w8z">.css-198tvf7{font-family:var(--chakra-fonts-heading);font-weight:var(--chakra-fontWeights-bold);margin-top:var(--chakra-space-2);margin-bottom:var(--chakra-space-8);font-size:var(--chakra-fontSizes-md);line-height:1.2;}.css-198tvf7{scroll-margin-top:5.5rem;}.css-198tvf7:hover>a{visibility:visible;}.css-198tvf7 a{position:absolute;margin-left:-1em;padding-right:0.5em;cursor:pointer;visibility:hidden;width:80%;max-width:800px;color:var(--chakra-colors-gray-700);}.css-198tvf7 a:hover{visibility:visible;-webkit-text-decoration:none;text-decoration:none;}.css-198tvf7 a span:after{content:"#";}.css-10qsrqw{transition-property:var(--chakra-transition-property-common);transition-duration:var(--chakra-transition-duration-fast);transition-timing-function:var(--chakra-transition-easing-ease-out);cursor:pointer;-webkit-text-decoration:none;text-decoration:none;outline:2px solid transparent;outline-offset:2px;color:inherit;}.css-10qsrqw:hover,.css-10qsrqw[data-hover]{-webkit-text-decoration:none;text-decoration:none;}.css-10qsrqw:focus,.css-10qsrqw[data-focus]{box-shadow:var(--chakra-shadows-outline);}.css-rszk63{margin-bottom:var(--chakra-space-4);}.css-4m8w8z{display:inline-block;font-family:var(--chakra-fonts-mono);font-size:var(--chakra-fontSizes-sm);-webkit-padding-start:0.2em;padding-inline-start:0.2em;-webkit-padding-end:0.2em;padding-inline-end:0.2em;border-radius:var(--chakra-radii-sm);background:var(--chakra-colors-gray-100);color:var(--chakra-colors-gray-800);} </code> tags from the generated HTML.
          189 Rather than summoning <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://stackoverflow.com/a/1732454/872397"><em>The One whose Name cannot be expressed in the Basic Multilingual Plane</em></a>
          190 by trying to use regex here, I found <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.npmjs.com/package/string-strip-html">this library</a>
          191 to help me with this task:</p><div class="remark-code-title">lib/feeds.tsx</div><pre class="language-typescript"><code class="language-typescript"><span class="token keyword">const</span> cleanHtmlContent <span class="token operator">=</span> <span class="token function">stripHtml</span><span class="token punctuation">(</span>htmlContent<span class="token punctuation">,</span> <span class="token punctuation">{</span>
          192     onlyStripTags<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'script'</span><span class="token punctuation">,</span> <span class="token string">'style'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
          193     stripTogetherWithTheirContents<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'script'</span><span class="token punctuation">,</span> <span class="token string">'style'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
          194 <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token property-access">result</span><span class="token punctuation">;</span>
          195 </code></pre> <h2 class="chakra-heading css-13bekiy" id="the-end-result"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#the-end-result"><span class="icon icon-link"></span></a>The End Result</h2> <p class="chakra-text css-rszk63">I now have serve <a class="chakra-link css-1npfuik" href="https://www.daan.fyi/feeds/feed.xml">RSS</a>, <a class="chakra-link css-1npfuik" href="https://www.daan.fyi/feeds/atom.xml">Atom</a> and a <a class="chakra-link css-1npfuik" href="https://www.daan.fyi/feeds/feed.json">JSON Feed</a>
          196 for your reading pleasure. Most of the relevant code <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/DandyDev/daan.fyi/blob/main/lib/feeds.tsx">can be found here</a></p> <h2 class="chakra-heading css-13bekiy" id="future-plans"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/rss#future-plans"><span class="icon icon-link"></span></a>Future Plans</h2> <p class="chakra-text css-rszk63">At some point I want to diversify my writing output by not only writing about tech. And
          197 even within the topic of tech there are many sub-topics I could write about, not all of which
          198 are equally interesting to every reader (all 5 of them, including my mom 👩‍👦).
          199 I’m planning to introduce <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/DandyDev/daan.fyi/issues/3">tags</a> to allow
          200 filtering content once I have enough of it.</p> <p class="chakra-text css-rszk63">Once I have tags, I would like to start supporting dynamic feeds so readers can subscribe only
          201 to the stuff they actually want to read. I imagine building an endpoint like this:</p><pre><code>/feeds/by-tags.xml?tags=tag1,tag2
          202 </code></pre> <p class="chakra-text css-rszk63">I’m curious if others are doing this!</p><span></span>]]></content:encoded>
          203         </item>
          204         <item>
          205             <title><![CDATA[Use Tools That Suit You and the Problem]]></title>
          206             <link>https://www.daan.fyi/writings/tools</link>
          207             <guid>https://www.daan.fyi/writings/tools</guid>
          208             <pubDate>Fri, 10 Sep 2021 00:00:00 GMT</pubDate>
          209             <description><![CDATA[Don't let anyone tell you what tools to use. Make sure that your builds are tool-agnostic]]></description>
          210             <content:encoded><![CDATA[<p class="chakra-text css-rszk63">A couple of weeks ago someone shared <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://alexander-hansen.dev/blog/benefits-of-not-using-an-ide">an article</a> on Hacker News that
          211 discussed the drawbacks of using an IDE for programming. Needless to say, when you touch
          212 people’s tools, you can be sure to
          213 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=28257116">spark a hefty discussion</a>.</p> <p class="chakra-text css-vnn9yi"> <p class="chakra-text css-rszk63">To be fair, the author did clarify that they’re not against IDE’s <em>in general</em> and they actually
          214 use one on a daily basis.</p></p> <p class="chakra-text css-rszk63">When reading the discussion, one of the first things I wondered is if there are places on the
          215 internet where carpenters or plumbers furiously criticize each other’s choice of tools.
          216 But <em>even that</em> has <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://news.ycombinator.com/item?id=28257382">a place on Hacker News</a></p> <p class="chakra-text css-rszk63">In this post I want to explore the fundamental problems with this type of discussion and how you
          217 can embrace freedom of choice.</p> <h2 class="chakra-heading css-13bekiy" id="its-all-about-context"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/tools#its-all-about-context"><span class="icon icon-link"></span></a>It’s All about Context</h2> <p class="chakra-text css-rszk63">When discussing someone else’s choice of tools — in this case the choice of editor or IDE — it’s
          218 good to be mindful of what we <em>don’t know</em> about this person and their reasons for choosing certain
          219 tools. Aside from personal preference and/or familiarity, there can be lots of extra factors to
          220 consider:</p> <ul role="list" class="css-11041dp"><li class="css-0">We don’t know what kind of problems they’re working on</li><li class="css-0">We don’t know the context in which they work (e.g. security requirements laid down by the company
          221 they work for, available budget)</li><li class="css-0">We don’t know their level of experience</li></ul> <p class="chakra-text css-rszk63">I think it’s good form to voice an opinion only when we can see the whole picture. I also
          222 think that people should be encouraged to <strong>choose the right tool for the job</strong>. And to put it
          223 simply: <strong>the right tool for the job is the one that fits the problem and makes you the most
          224 productive</strong>.</p> <h2 class="chakra-heading css-13bekiy" id="its-also-about-definition"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/tools#its-also-about-definition"><span class="icon icon-link"></span></a>It’s Also about Definition</h2> <p class="chakra-text css-rszk63">Another issue with this kind of discussion is that everyone has a different idea of what really
          225 constitutes an “IDE”. We’re inclined to frame the choice of editor as a binary choice — "pure text
          226 editor" vs “IDE”, almost like a false dichotomy — while it really is a spectrum. On this spectrum
          227 you’ll not only find different editors, but even different configurations of the same editor with
          228 varying degrees of “smartness” applied through plugins.</p> <p class="chakra-text css-rszk63">So when someone says <em>"why use an IDE when you can do everything an IDE does in VIM if you install
          229 the following 20 plugins"</em>, is this really so different from an actual IDE (that was branded as
          230 such)?</p> <h2 class="chakra-heading css-13bekiy" id="philosophies-in-tool-choices"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/tools#philosophies-in-tool-choices"><span class="icon icon-link"></span></a>Philosophies in Tool Choices</h2> <p class="chakra-text css-rszk63">When looking at how people setup their development environments, I basically see 2 different
          231 approaches:</p> <ul role="list" class="css-11041dp"><li class="css-0">The <em>“additive”</em> approach: this basically follows the UNIX philosophy of composing many different
          232 tools that each do one thing well. It often involves a terminal-based editor like VIM, optionally
          233 with some plugins and supported by external tools like grep, sed and awk that can help with
          234 refactoring code. You basically stack tools until you have an “integrated” development environment</li><li class="css-0">The <em>“subtractive”</em> approach: you take one “big” editor as the basis of your stack. This is often
          235 an editor that is branded as an IDE (e.g. Eclipse, Jetbrains editors). Then you take away/replace
          236 ("subtract") the parts that work better through dedicated tools (according to personal preference
          237 of course)</li></ul> <p class="chakra-text css-rszk63">To me, both approaches have their merits and uses!</p> <h2 class="chakra-heading css-13bekiy" id="how-to-create-freedom-of-choice"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/tools#how-to-create-freedom-of-choice"><span class="icon icon-link"></span></a>How to Create Freedom of Choice?</h2> <p class="chakra-text css-rszk63">I think the most important question around editors is not</p> <blockquote class="css-p56y4k"> <p class="chakra-text css-rszk63"><em>How to choose the right editor?</em></p></blockquote> <p class="chakra-text css-rszk63">but rather</p> <blockquote class="css-p56y4k"> <p class="chakra-text css-rszk63"><em>How to enable each member of my team to choose the editor that makes them <strong>most productive</strong>,
          238 while enabling <strong>effective collaboration</strong>?</em></p></blockquote> <p class="chakra-text css-rszk63">Here’s my recipe to do that:</p> <p class="chakra-text css-rszk63">My basic starting point in teams: <em>everyone can use the editor/IDE of their choice</em>. To enable
          239 effective collaboration, the following rules must be followed:</p> <ul role="list" class="css-11041dp"><li class="css-0">Editor configuration is never checked into version control, unless it’s generic and <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://editorconfig.org/">applicable across editors</a>. Examples of generic editor configuration
          240 are: line endings, tabs vs spaces, max line length etc. There is some overlap with linters here</li><li class="css-0">Enforce common code style through external tools (i.e. linters, code formatters)</li><li class="css-0">Everyone should be able to build and run a project, regardless of the choice of editor,
          241 preferably through the terminal. This means that we’ll always prefer external tools for this.
          242 Many languages provide tooling for this:<ul role="list" class="css-11041dp"><li class="css-0">Java → Maven/Gradle</li><li class="css-0">JS/TS → NPM</li><li class="css-0">Go → Go</li><li class="css-0">Rust → Cargo</li><li class="css-0">…</li></ul></li><li class="css-0">Additionally, building and running code can be made easier and better reproducible by using
          243 Makefiles and/or Docker (combined with Docker Compose)</li></ul> <p class="chakra-text css-rszk63">I have to admit that in some ways I also limit choice within my teams: building and running
          244 projects often involves shell scripts which are portable between Linux and MacOS, but not to
          245 Windows. This can be solved by using WSL on Windows.</p> <h2 class="chakra-heading css-13bekiy" id="this-is-my-setup"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/tools#this-is-my-setup"><span class="icon icon-link"></span></a>This Is My Setup</h2> <p class="chakra-text css-rszk63">My personal setup involves quite a lot of tools.</p> <p class="chakra-text css-rszk63">For any “serious” development work (i.e. long stretches of coding and big projects) I take the
          246 aforementioned “subtractive” approach. My basis is one of the Jetbrains tools, depending on the
          247 language(s) I’m working with. I find the Jetbrains tools make <em>me</em> really productive and their <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.jetbrains.com/all/"><em>All products pack</em></a> offers great value for money, especially with
          248 their huge loyalty discounts after 1 or more years.</p> <p class="chakra-text css-rszk63">I still use the terminal and external tools for many things in this case. I put quite some time in
          249 improving and maintaining <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/DandyDev/dotfiles">my dotfiles</a> as well.</p> <ul role="list" class="css-11041dp"><li class="css-0">I prefer to use the terminal for: building, linting, running tests, using git</li><li class="css-0">I prefer to use the IDE for: writing and editing code, refactoring, searching for code,
          250 find/replace through regex</li></ul> <p class="chakra-text css-rszk63">For quick and short edits and viewing files where speed is preferred and conveniences like syntax
          251 highlighting and intellisense are not important, I use Sublime Text or VIM. Example of this:
          252 editing my dotfiles.</p> <p class="chakra-text css-rszk63">Sometimes, but rarely, I use VSCodium for editing or viewing files which are not part of a project
          253 and which I want to reformat/reindent. This doesn’t work well for me in Sublime Text. For example:
          254 viewing/editing minified JSON files.</p> <h2 class="chakra-heading css-13bekiy" id="conclusion"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/tools#conclusion"><span class="icon icon-link"></span></a>Conclusion</h2> <p class="chakra-text css-rszk63">To wrap this post up, I just want to reiterate: use whatever tools make you productive and help you
          255 solve the problems you’re trying to solve and please let others do the same.</p> <p class="chakra-text css-rszk63">And here’s some additional closing advice: should you ever grow unhappy with the tools you’re
          256 using, just write a blog post extolling the virtues of your current tools. You can be sure people
          257 on the internet will tell you how much better their tools are, thereby providing you with potential
          258 alternatives to your current setup 😇</p> <hr aria-orientation="horizontal" class="chakra-divider css-9153ub"/> <p class="chakra-text css-rszk63"><em>Thanks to <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://twitter.com/djvdorp">Dan</a> for proofreading this</em></p><span></span>]]></content:encoded>
          259         </item>
          260         <item>
          261             <title><![CDATA[The Pitfalls of Deploying a Nextjs Frontend on Aws Amplify]]></title>
          262             <link>https://www.daan.fyi/writings/amplify</link>
          263             <guid>https://www.daan.fyi/writings/amplify</guid>
          264             <pubDate>Mon, 23 Aug 2021 00:00:00 GMT</pubDate>
          265             <description><![CDATA[Half-baked products lead to much frustration]]></description>
          266             <content:encoded><![CDATA[<p class="chakra-text css-rszk63">Have you ever gone above and beyond to give a product a fair chance, only giving up way past your
          267 own sanity and patience? I did. The product was <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://aws.amazon.com/amplify/">AWS Amplify</a></p> <h2 class="chakra-heading css-13bekiy" id="lets-build-something-with-nextjs"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#lets-build-something-with-nextjs"><span class="icon icon-link"></span></a>Let’s Build Something with NextJS</h2> <p class="chakra-text css-rszk63">When I started developing the primary (web) UI for the product we’re building at <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https:/source.ag">Source</a>, I quickly decided to use the <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/">NextJS</a> framework as
          268 the basis for the frontend. One thing I really like about NextJS is that it does <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/docs/basic-features/pages">filesystem-based
          269 routing</a>. Even though I like to diss on PHP as much
          270 as the next person, this particular feature of NextJS reminds me a bit of PHP <em>in a good way</em>.</p> <p class="chakra-text css-rszk63">Another very compelling feature of NextJS, is the ability to have different rendering strategies
          271 for each different page. You can decide to use:</p> <ul role="list" class="css-11041dp"><li class="css-0"> <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/docs/basic-features/pages#static-generation-recommended">Static generation</a>
          272 for pages and content that rarely change. These pages get pre-rendered at build time and can be
          273 aggressively cached on a CDN.
          274 These pages can of-course still be highly dynamic by using client-side data fetching methods</li><li class="css-0"><a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/docs/basic-features/pages#server-side-rendering">Server-side rendering</a> for
          275 pages that need to return different content on each request and/or for each different user</li><li class="css-0"><a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/docs/basic-features/data-fetching#incremental-static-regeneration">Incremental static regeneration</a>,
          276 which is a variation on Static generation that will cache pages for a period you specify and then
          277 regenerate the pages server-side when they’re considered stale</li></ul> <h2 class="chakra-heading css-13bekiy" id="deployment"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#deployment"><span class="icon icon-link"></span></a>Deployment</h2> <p class="chakra-text css-rszk63">This particular feature requires a specific hosting setup that supports the different <em>flavours</em>
          278 of rendering. You basically want:</p> <ul role="list" class="css-11041dp"><li class="css-0">a good CDN to cache and serve your static pages</li><li class="css-0">a server-side solution to serve the server-side rendered pages and facilitate incremental static
          279 regeneration. This should also take care of <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/docs/api-routes/introduction">API routes</a>, should you use them</li></ul> <p class="chakra-text css-rszk63">The NextJS documentation <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/docs/deployment">mentions a couple of options</a> for
          280 deployment:</p> <ol role="list" class="css-4qdgui"><li class="css-0">Use <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://vercel.com/">Vercel</a>. Vercel is the company behind NextJS. They offer a seamless
          281 experience where you can use any rendering method, and Vercel will deploy each part of your app
          282 in the right way. One neat thing they do is that they’ll convert your server-side rendered pages
          283 and API routes into serverless functions that they’ll deploy to edge locations all over the globe.</li><li class="css-0">Setup a NodeJS server somewhere for the server-side stuff and use a CDN manually to serve the
          284 static content.</li></ol> <p class="chakra-text css-rszk63">At Source however, we’ve made a conscious decision to use AWS for all of our infrastructure needs. We’re
          285 too early in the lifecycle of both our product and company to consider a hybrid cloud setup and
          286 AWS offers all the features that we need for prices that are reasonable <em>for now</em>. Through one of
          287 our investors we also got a boat-load of AWS credits to get started, which helps.</p> <h2 class="chakra-heading css-13bekiy" id="amplify"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#amplify"><span class="icon icon-link"></span></a>Amplify</h2> <p class="chakra-text css-rszk63">I didn’t want to manually set up a hybrid deployment with NodeJS and CDN - which I could probably do
          288 using Cloudfront and ECS - so I looked for alternatives. AWS Amplify claims to be the</p> <blockquote class="css-p56y4k"> <p class="chakra-text css-rszk63">Fastest, easiest way to build mobile and web apps that scale</p></blockquote> <p class="chakra-text css-rszk63">And they <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://docs.amplify.aws/guides/hosting/nextjs/q/platform/js/">claim to support NextJS</a>
          289 as well as <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://aws.amazon.com/blogs/mobile/host-a-next-js-ssr-app-with-real-time-data-on-aws-amplify/">server-side rendering</a>
          290 by virtue of <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://aws.amazon.com/lambda/edge/">Lambda@Edge</a></p> <p class="chakra-text css-rszk63">Sounds great! So how does that all work?</p> <h2 class="chakra-heading css-13bekiy" id="amplify---the-setup"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#amplify---the-setup"><span class="icon icon-link"></span></a>Amplify - The Setup</h2> <p class="chakra-text css-rszk63">The idea behind Amplify is that it lets you focus on building your app without having to worry
          291 about the infrastructure. This means that it will not only let you build and deploy your frontend
          292 easily, it will also let you hook-up backend components like <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://docs.amplify.aws/lib/auth/getting-started/q/platform/js/">authentication</a> through
          293 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://aws.amazon.com/cognito/">Cognito</a>,
          294 a <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://docs.amplify.aws/lib/graphqlapi/getting-started/q/platform/js/">GraphQL API</a> using
          295 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://aws.amazon.com/appsync/">AppSync</a>
          296 and a <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://docs.amplify.aws/lib/datastore/getting-started/q/platform/js/">DataStore</a>.</p> <p class="chakra-text css-rszk63">The way Amplify manages all of this, is through the idea of “backends”. A backend contains one or
          297 more of the aforementioned components. You can setup different backend environments in Amplify and
          298 couple these to different (git) branches of your frontend.</p> <h2 class="chakra-heading css-13bekiy" id="amplify---the-developer-experience"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#amplify---the-developer-experience"><span class="icon icon-link"></span></a>Amplify - The Developer Experience</h2> <p class="chakra-text css-rszk63">We are bringing our own database and API and wanted to use a pre-existing Cognito user pool.
          299 Amplify lets you import an existing Cognito user pool instead of creating one for you, and this
          300 worked fine… until I tried to create a second “backend environment” with a different Cognito
          301 user pool.</p> <p class="chakra-text css-rszk63">I want to allow different users on our development environment than our production
          302 environment. These environments correspond to the <code class="chakra-code css-4m8w8z">main</code> branch in Git (production) and any other
          303 branches in Git (development).</p> <h4 class="chakra-heading css-198tvf7" id="how-do-i-tie-an-amplify-backend-environment-to-a-frontend-branch"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#how-do-i-tie-an-amplify-backend-environment-to-a-frontend-branch"><span class="icon icon-link"></span></a>How Do I Tie an Amplify Backend Environment to a Frontend Branch?</h4> <p class="chakra-text css-rszk63">Interaction with Amplify is done through the web console or the <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://docs.amplify.aws/cli/">Amplify CLI</a>. According to the documentation, we can create a new
          304 Amplify backend environment like this:</p><pre><code>amplify env add
          305 </code></pre> <p class="chakra-text css-rszk63">But nowhere is it made clear how this is linked to our frontend branch. The Amplify CLI tries to
          306 mimic the <code class="chakra-code css-4m8w8z">git</code> CLI by having <code class="chakra-code css-4m8w8z">amplify push</code> and <code class="chakra-code css-4m8w8z">amplify pull</code>. So I assume we need to <code class="chakra-code css-4m8w8z">push</code> our
          307 new environment to the cloud. Does this command depend on the git branch I’m on? I don’t know.
          308 I could just as easily overwrite my existing backend environment when using this command.</p> <p class="chakra-text css-rszk63">Eventually I was able to create a <code class="chakra-code css-4m8w8z">main</code> environment and a <code class="chakra-code css-4m8w8z">dev</code> environment, but no matter how hard
          309 I tried, I could not get those environments to use different Cognito user pools.</p> <h4 class="chakra-heading css-198tvf7" id="how-do-new-team-members-setup-an-existing-project"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#how-do-new-team-members-setup-an-existing-project"><span class="icon icon-link"></span></a>How Do New Team Members Setup an Existing Project?</h4> <p class="chakra-text css-rszk63">The Amplify CLI will create some configuration files, some of which you need to commit to git, and
          310 some of them you need to ignore. These files should make the build reproducible. It is unclear
          311 however, what a new developer needs to do to be able to run an existing Amplify project.
          312 The documentation mentions multiple Amplify CLI commands to setup a project:</p><pre><code>amplify pull
          313 </code></pre><pre><code>amplify init
          314 </code></pre><pre><code>amplify configure project
          315 </code></pre><pre><code>amplify env checkout <my-env>
          316 </code></pre> <p class="chakra-text css-rszk63"><em>To be run in arbitrary order?</em></p> <p class="chakra-text css-rszk63"> <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://stackoverflow.com/questions/60365208/how-to-import-existing-aws-amplify-back-end-into-an-empty-aws-amplify-project-lo">Three</a>
          317 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://stackoverflow.com/questions/60951924/how-do-i-continue-working-with-amplify-on-a-new-machine">similar</a>
          318 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://stackoverflow.com/questions/61104135/how-to-run-an-existing-aws-amplify-project">questions</a>
          319 on StackOverflow give 3 different answers on this topic.</p> <p class="chakra-text css-rszk63">When I was on-boarding new team-members, we basically tried some commands in different order until
          320 we were able to run the project locally for that engineer.</p> <h4 class="chakra-heading css-198tvf7" id="how-do-i-figure-out-why-my-build-failed"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#how-do-i-figure-out-why-my-build-failed"><span class="icon icon-link"></span></a>How Do I Figure Out Why My Build Failed?</h4> <p class="chakra-text css-rszk63">In short: <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/aws-amplify/amplify-console/issues/2065">you don’t</a>. Or you enlist
          321 the help of AWS Support (which you will have to pay for). The Amplify web console doesn’t share
          322 detailed build logs, so you’ll have to fix your problems by trial and error.</p> <h2 class="chakra-heading css-13bekiy" id="amplify---the-bugs"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#amplify---the-bugs"><span class="icon icon-link"></span></a>Amplify - The Bugs</h2> <p class="chakra-text css-rszk63">AWS Amplify seems to have quite some bugs. For example: when you use Gitlab, you
          323 cannot put the source code of your project <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://github.com/aws-amplify/amplify-console/issues/1941">in a sub-group</a>. This will silently
          324 fail your build, with no clear error message in sight.</p> <p class="chakra-text css-rszk63">The aforementioned problem of using multiple Cognito user pools for different
          325 environments of one Amplify frontend, I also consider a bug.</p> <p class="chakra-text css-rszk63">Not having access to the <em>actual</em> build logs, I also consider a bug.</p> <h2 class="chakra-heading css-13bekiy" id="amplify---no-help-included"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#amplify---no-help-included"><span class="icon icon-link"></span></a>Amplify - No Help Included</h2> <p class="chakra-text css-rszk63">The most painful issue I have with AWS Amplify - and AWS in general - is the complete lack of
          326 support. You are paying a lot of money for their services, but that does not come with any form of
          327 support, unless you pay extra. And when you make use of that paid support, it goes something like
          328 this:</p> <ol role="list" class="css-4qdgui"><li class="css-0">Contact AWS Business support through their website and try to explain your problem in a plain
          329 text field that you cannot resize or use formatting in</li><li class="css-0">Wait far longer than the promised 4 hours</li><li class="css-0">Get a response from someone telling you they’ll forward it to “the team” (why not have someone
          330 respond who can actually help you with your problem?)</li><li class="css-0">Get a canned response with a solution akin to “turn it off and on again”</li><li class="css-0">Tell them you have an <em>actual problem</em></li><li class="css-0">Get forwarded to the next person who you have to clue in again on what your problem is</li><li class="css-0">Go to 2 and repeat</li></ol> <p class="chakra-text css-rszk63">This means that in practice, AWS Amplify is <em>not usable</em> unless you are willing to pay extra for
          331 support and have a lot of patience.</p> <p class="chakra-text css-rszk63">As a side note, I find it really frustrating that with big corporations like Amazon in general, you
          332 quickly feel helpless and ignored when you have problems. Stories about Google customer support (or
          333 lack thereof) are rampant on Hacker News, and I think Amazon is no different. You’d think that with
          334 so much revenue they should be able to set up actual proper customer support 🙄</p> <h2 class="chakra-heading css-13bekiy" id="the-pattern-with-aws"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#the-pattern-with-aws"><span class="icon icon-link"></span></a>The Pattern with AWS</h2> <p class="chakra-text css-rszk63">I think that these problems with Amplify are endemic of a larger problem with AWS: <strong>their PaaS and
          335 SaaS solutions suck</strong>. Aside from pricing (which is quite high compared to competitors like
          336 Digital Ocean), I think AWs’ infrastructure-as-a-service offerings are fine. If you want to have a
          337 bunch of servers (EC2), a database here and there (RDS) and some serverless functions (Lambda), AWS
          338 will serve you just fine.</p> <p class="chakra-text css-rszk63">But if you want something on top of that, like authentication (Cognito), or a PaaS solution like
          339 Amplify, be prepared for a sub-par offering compared to the competition. I think Amazon should
          340 focus on strengthening their core offerings instead of offering everything and the kitchen sink.</p> <h2 class="chakra-heading css-13bekiy" id="the-solution"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/amplify#the-solution"><span class="icon icon-link"></span></a>The Solution</h2> <p class="chakra-text css-rszk63">In the end, I dropped Amplify and went with Vercel. $20/user/month is a small price to pay for
          341 actually being able to work on the product instead of fighting AWS services and support.</p><span></span>]]></content:encoded>
          342         </item>
          343         <item>
          344             <title><![CDATA[The Joy of Starting Something New]]></title>
          345             <link>https://www.daan.fyi/writings/new</link>
          346             <guid>https://www.daan.fyi/writings/new</guid>
          347             <pubDate>Mon, 16 Aug 2021 00:00:00 GMT</pubDate>
          348             <description><![CDATA[The start of a new blog/job/...]]></description>
          349             <content:encoded><![CDATA[<p class="chakra-text css-rszk63">I don’t really know how to say this, but: I’m going to try and blog again! After building this site,
          350 I didn’t even know how to begin <em>actually writing</em> again. Looking for inspiration, I studied some
          351 famous tech people’s websites but came up empty trying to find examples of “first blog posts” there.
          352 Most people like to just dig right in with some on-topic tech content it seems…</p> <p class="chakra-text css-rszk63">But <strong>HERE IT IS!</strong></p> <p class="chakra-text css-rszk63"><em>My first blog post on my new website.</em></p> <h2 class="chakra-heading css-13bekiy" id="previously-on"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/new#previously-on"><span class="icon icon-link"></span></a>Previously on…</h2> <p class="chakra-text css-rszk63">It’s been nigh on 4 years since I last wrote something on my old crib <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://dandydev.net">dandydev.net</a> (by the time you’re reading this, I’ll have most probably
          353 redirected everything from there to here). I don’t really know why I stopped blogging in the first
          354 place, but it probably had something to do with life/work/… getting in the way (or me letting it
          355 get in the way anyways).</p> <p class="chakra-text css-rszk63">So what has been going on?</p> <p class="chakra-text css-rszk63">After working for KLM Royal Dutch Airlines for 4.5 years I got a dream position at <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://source.ag">Source.ag</a>, a new startup co-founded by a friend, focusing on Agriculture & AI.
          356 As VP of Engineering I help build both the tech and the team and I’m loving it to bits!</p> <p class="chakra-text css-rszk63">Keeping with the theme of this post, it’s really exciting to start something so brand new. I’m
          357 actually employee #1 which gives me ample opportunity to have a major impact. There are no
          358 pre-established rules, processes, dynamics. For the first couple of months, it was just the 2
          359 co-founders and me figuring out what to build, how to build it and then actually building it while
          360 at the same time trying to grow the company. And now, 5 months after I started, we’re 12 lifeforms strong
          361 and growing!</p> <p class="chakra-text css-rszk63">And after my previous job veered more and more into organizational politics instead of tech, it
          362 feels great to be building an actual product again. It’s both amazing and terrifying to code most
          363 of an MVP all by yourself in 5 months 😱</p> <p class="chakra-text css-rszk63"><em>If you’re interested in bringing positive change to the food system, <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://source.ag/careers/">you can join us</a></em></p> <h2 class="chakra-heading css-13bekiy" id="the-excitement-of-new-things"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/new#the-excitement-of-new-things"><span class="icon icon-link"></span></a>The Excitement of New Things</h2> <p class="chakra-text css-rszk63">Interlude: why is it that I find starting new things so exciting? I often wonder about this.</p> <ul role="list" class="css-11041dp"><li class="css-0">I’m probably one of the few people not actually terrified of starting a new job</li><li class="css-0">There are few things that give me more energy than starting a new side-project</li><li class="css-0">Even as a gamer, I often spend more time <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://steamcommunity.com/id/kajel/games/">trying out</a> <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.gog.com/u/Curois/games">new games</a> than actually finishing them
          364 (don’t worry, I also have a Humble Bundle backlog and a PSN profile full of games that you don’t
          365 know about yet 🙄)</li></ul> <p class="chakra-text css-rszk63">I think it comes down to wanting to <em>learn</em> new things as much as possible and I guess I just love
          366 exploring the unknown.</p> <p class="chakra-text css-rszk63">But I’m gonna be honest: the challenge is to stick with things. For each side-project I finished,
          367 there are many left in the dust. They were never time badly spent, because each time I learnt
          368 something new. But I think there is value in finishing things as well.</p> <p class="chakra-text css-rszk63">I hope that a different approach with this blog will make it easier for me to stick with it.</p> <h2 class="chakra-heading css-13bekiy" id="doing-things-differently"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/new#doing-things-differently"><span class="icon icon-link"></span></a>Doing Things Differently</h2> <p class="chakra-text css-rszk63">I want to sound off this rambling first blog post by sharing how things that are (going to be)
          369 different with this website:</p> <ul role="list" class="css-11041dp"><li class="css-0">I ditched my old domain dandydev.net for some place simpler and more elegant: <strong>daan.fyi</strong>.
          370 I paid a pretty penny to get a domain of only my first name and an extension that didn’t look
          371 too ridiculous and I love it. It feels a bit more mature as well</li><li class="css-0">Always looking to learn new things, I chose to forego a traditional static site generator for a
          372 more hand-built experience. This site was built on <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://nextjs.org/">NextJS</a>, React and
          373 Typescript. And I actually designed and built the theme myself using
          374 <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://chakra-ui.com/">ChakraUI</a>. I did get a lot of inspiration from other people’s websites
          375 (see below)</li><li class="css-0">I’m writing my posts using <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://mdxjs.com/">MDX</a> instead of regular markdown. For this
          376 particular post there is not actually any difference, but MDX will allow me to create more
          377 tailored and interactive experiences in the future, should I need/want it</li><li class="css-0">In terms of content, I plan to have a different approach than before:<ul role="list" class="css-11041dp"><li class="css-0">I’ll try to write shorter posts and consequently (hopefully) write more often</li><li class="css-0">I’m allowing myself to write about other stuff than tech. This blog is meant to <em>express</em>
          378 myself more than to <em>advertise</em> myself. This means I’ll probably write about non-tech topics
          379 like movies & tv-shows I’ve seen, games I played and maybe even reflect on politics once in
          380 a while 😬 Once this kind of content arrives, I’ll make sure it’s easy to see and skip it 😉</li></ul></li></ul> <h2 class="chakra-heading css-13bekiy" id="acknowledgements-of-inspiration"> <a class="chakra-link css-10qsrqw" aria-hidden="true" tabindex="-1" href="https://www.daan.fyi/writings/new#acknowledgements-of-inspiration"><span class="icon icon-link"></span></a>Acknowledgements of Inspiration</h2> <p class="chakra-text css-rszk63">When building this website, there were a few websites that inspired me and/or helped me with actual
          381 solutions to coding problems (yay for open source!):</p> <ul role="list" class="css-11041dp"><li class="css-0"> <a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://alyssax.com/">Alyssa X</a></li><li class="css-0"><a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://leerob.io/">Lee Robinson</a></li><li class="css-0"><a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://www.joshwcomeau.com/">Josh W. Comeau</a></li><li class="css-0"><a target="_blank" rel="noopener noreferrer" class="chakra-link css-1npfuik" href="https://marcel.is/">Marcel Krcah</a></li></ul> <hr aria-orientation="horizontal" class="chakra-divider css-9153ub"/> <p class="chakra-text css-rszk63">See you next time!</p><span></span>]]></content:encoded>
          382         </item>
          383     </channel>
          384