|
|
nextjs_daan.fyi.rss.xml - sfeed_tests - sfeed tests and RSS and Atom files |
|
|
 |
git clone git://git.codemadness.org/sfeed_tests (git://git.codemadness.org) |
|
|
 |
Log |
|
|
 |
Files |
|
|
 |
Refs |
|
|
 |
README |
|
|
 |
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 |
|