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