<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jon Stødle</title>
    <description>The latest articles on DEV Community by Jon Stødle (@jonstodle).</description>
    <link>https://dev.to/jonstodle</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3129%2F839bbeb0-e671-4f7b-88f7-ebc0041c447f.jpg</url>
      <title>DEV Community: Jon Stødle</title>
      <link>https://dev.to/jonstodle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonstodle"/>
    <language>en</language>
    <item>
      <title>Paying For Search</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Thu, 16 Feb 2023 23:00:00 +0000</pubDate>
      <link>https://dev.to/jonstodle/paying-for-search-5aab</link>
      <guid>https://dev.to/jonstodle/paying-for-search-5aab</guid>
      <description>&lt;p&gt;I've been using DuckDuckGo for years, and I've been happy with the search results. However, I recently tried to search for places that sold the Sami flag, but DuckDuckGo was stumped. Google however found 2 places immediately. This coincided with a discussion at work about search engines and which ones people were using. Long story short, after some browsing I landed on trying out &lt;a href="https://kagi.com"&gt;Kagi&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Kagi has a free trial of 50 searches per month, for more than that you'll have to pay for a subscription. After trying 50 searches - including a search for places that sell the Sami flag - I was satisfied with the results it gave me. I took the leap and paid for a monthly subscription.&lt;/p&gt;

&lt;p&gt;While a yearly subscription is cheaper, I'll stick with the monthly for now, before taking an even bigger leap of faith and comit to a whole year.&lt;/p&gt;

&lt;p&gt;One of the things I like about Kagi is the ability to use &lt;a href="https://help.kagi.com/kagi/features/bangs.html"&gt;!bangs&lt;/a&gt;, just like I did with DuckDuckGo. In fact, Kagi reuses the !bangs from DuckDuckGo, saving me from unlearning a habit I've become incredibly fond of and reliant on.&lt;/p&gt;

&lt;p&gt;Kagi also let's you use different "lenses" when searching. As a programmer I frequently search for problems related to my work. By turning on the &lt;em&gt;Programming&lt;/em&gt; lens, Kagi will prioritize results related to programming. A search for &lt;code&gt;rust&lt;/code&gt; with the programming lens on filters away results related to &lt;a href="https://en.wikipedia.org/wiki/Rust_(video_game)"&gt;Rust the game&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Rust_(upcoming_film)"&gt;Rust the movie&lt;/a&gt;. Kagi also has lenses called &lt;em&gt;Academic&lt;/em&gt;, &lt;em&gt;World News&lt;/em&gt;, and &lt;em&gt;Forums&lt;/em&gt;, to mention some.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B4jjN4oU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jonstodle.com/images/kagi-rust-search-no-lens.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B4jjN4oU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jonstodle.com/images/kagi-rust-search-no-lens.png" alt="Search results for the game Rust, the movie Rust and the programming language Rust" width="880" height="829"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HeOnoSGv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jonstodle.com/images/kagi-rust-search-programming-lens.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HeOnoSGv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jonstodle.com/images/kagi-rust-search-programming-lens.png" alt="Search results for the programming language Rust, it's documentation and a code sample" width="880" height="829"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You're also able to manually rank websites. You can raise or lower the ranking, block the site entirely, or pin it, to make it show up at the top of the results every time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--y7fWYSKh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jonstodle.com/images/kagi-change-site-ranking.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y7fWYSKh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jonstodle.com/images/kagi-change-site-ranking.png" alt="Controls for ranking StackOverflow.com, and technical information about the site" width="381" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The price of the subscription is $10, which is steep, but they have a whole &lt;a href="https://help.kagi.com/kagi/why-kagi/why-pay.html#costs-to-deliver-a-superior-ad-free-search-product"&gt;FAQ answer&lt;/a&gt; on why the price is so high: they know the price of a single search and based on an estimated average number of searches per paying user, they've set a price that should cover the cost. That also includes covering the cost of the free trial searches. While paying users are searching more than the estimate at the moment, they hope that number will fall to make the $10 price point viable.&lt;/p&gt;

&lt;p&gt;I can actually see what my consumption is costing them. Of the $10 I've paid them for the current billing cycle, I've spent $1.41. I get a little heart and a thank you for my contribution to further development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uYOpq8_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jonstodle.com/images/kagi-subscription-usage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uYOpq8_I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.jonstodle.com/images/kagi-subscription-usage.png" alt="Total pay: $10; total usage: $1.41; payment to usage balance: $8.59. Also a list with number of searches per individual day" width="880" height="973"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Will I keep paying? We'll see, but so far I'm very happy with Kagi. I'm also the kind of person who pays for their email provider, so paying for search isn't a huge leap.&lt;/p&gt;

</description>
      <category>commentary</category>
    </item>
    <item>
      <title>Tiny Container Images With Distroless Containers</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Sat, 16 Oct 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/jonstodle/tiny-container-images-with-distroless-containers-3p2n</link>
      <guid>https://dev.to/jonstodle/tiny-container-images-with-distroless-containers-3p2n</guid>
      <description>&lt;p&gt;When deploying applications using containers, it's usually a goal to minimize the size of the container image.&lt;/p&gt;

&lt;p&gt;Achieving a small container size varies a lot between different languages and technologies. There is no &lt;em&gt;single&lt;/em&gt; solution that will work for everyone, as usual, but there’s a pretty interesting alternative if you’re deploying Rust, D, Go, Java or node.js applications.&lt;/p&gt;

&lt;p&gt;Google maintains a repo of what they call &lt;em&gt;distroless containers&lt;/em&gt;. These are container base images that contain as little as possible. They’ve stripped away pretty much everything until you’re basically left with &lt;em&gt;libc&lt;/em&gt; and not much more. There isn’t even a shell included!&lt;/p&gt;

&lt;p&gt;Another nice benefit of the distroless images, apart from the size consideration, is the security. With so few tools and executables inside the container it increases the difficulty of being able to do much if you manage to get access to it. Less code, means less bugs and vulnerabilities.&lt;/p&gt;

&lt;p&gt;To start using one is pretty simple. Build your application and copy the final binary into the image based on one of the distroless images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
FROM golang:1.13-buster as build

WORKDIR /src

COPY . /src

RUN go get -d -v ./...

RUN go build -o /go/bin/app

FROM gcr.io/distroless/base-debian10

COPY --from=build /go/bin/app /

CMD ["/app"]

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

&lt;/div&gt;



&lt;p&gt;It’s important to note that you have to use the for &lt;code&gt;[“/app”]&lt;/code&gt; when defining a &lt;code&gt;CMD&lt;/code&gt; or &lt;code&gt;ENTRYPOINT&lt;/code&gt; command in the docker file. If you use the “bare” form, e.g. &lt;code&gt;CMD “/app”&lt;/code&gt; , Docker will prepend the command with a shell which will not work, as there’s not shell inside the distroless container.&lt;/p&gt;

&lt;p&gt;And that’s it!&lt;/p&gt;

&lt;p&gt;Check out their &lt;a href="https://github.com/GoogleContainerTools/distroless"&gt;repo on Github&lt;/a&gt; for more information.&lt;/p&gt;




&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>rust</category>
      <category>go</category>
      <category>node</category>
    </item>
    <item>
      <title>How the useState Hook Works</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Tue, 12 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/jonstodle/how-the-usestate-hook-works-hn3</link>
      <guid>https://dev.to/jonstodle/how-the-usestate-hook-works-hn3</guid>
      <description>&lt;p&gt;I recently tried to explain to a friend how the &lt;code&gt;useState&lt;/code&gt; hook works in React. I thought my analogy was quite a good one, so here goes!&lt;/p&gt;

&lt;p&gt;Imagine React has a large warehouse where it can store information you don't want to reset every time React updates the view. We'll call this warehouse &lt;em&gt;Central Storage&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To be able to store information in Central Storage, we'll have to reserve shelf space. We reserve shelf space by calling &lt;code&gt;useState&lt;/code&gt;. &lt;code&gt;useState&lt;/code&gt; takes a value which will be the default information stored in your shelf space.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useState&lt;/code&gt; returns an array with two items:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A fresh &lt;em&gt;copy&lt;/em&gt; of the information stored in your shelf space. We'll receive a fresh copy every time React updates the view.&lt;/li&gt;
&lt;li&gt;A function which let's us overwrite the information stored in your shelf space. To permanently change the information, which we receive a copy of in &lt;em&gt;1&lt;/em&gt;, we have to call this function with the new information.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our code will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const shelfSpace = useState("Hello World!");// ^ ^ ^ // | | | // ∟ Array containing a copy of the information stored in your shelf space, and a function to overwrite // the information stored in your shelf space // | | // ∟ "Reserve shelf space" // | // ∟ Store "Hello World!" in the shelf space when reserving the shelf spaceconst message = shelfSpace[0];// ^ ^ // | | // ∟ Store the copy of the information in your shelf space in a more conveniently named variable. It has a // name which better describe the information. // | // ∟ The copy of the information will always be the first item in the array returned by // useState. At index 0, in other wordsconst overwriteMessage = shelfSpace[1];// ^ ^ // | | // ∟ Store the function for overwriting the information in your shelf space in a more conveniently // named variable. It better describes what the function does. // | // ∟ The function for overwriting the information in your shelf space will always // be the second item in the array returned by useState. // At index 1, in other words
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We don't have to use three lines of code for every reservation i Central Storage. We can shorten it to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const [message, overwriteMessage] = useState("Hello World!");// ^ ^ // | | // ∟ "Unpack" the list returned by useState and store the first item in the array (index 0) // in a variable named `message` // | // ∟ Store the second item in the array (index 1) in a variable named `overwriteMessage`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When making changes to our copy of the information we've received from Central Storage, those changes will not show up in your shelf space in Central Storage automatically. We have to explicitly ask for the information in your shelf space in Central Storage to be overwritten.&lt;/p&gt;

&lt;p&gt;Even if we update the variable &lt;code&gt;message&lt;/code&gt; in your code...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const [message, overwriteMessage] = useState("Hello World!");message = "Hello Programming!";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;... it won't change the information in your shelf space in Central Storage. We've just modified our copy of the information. The next time React updates the view, it will fetch a fresh copy of the information in Central Storage - not containing the changes you just made.&lt;/p&gt;

&lt;p&gt;To store your changes, we'll have to explicitly overwrite the changes in your shelf space in Central Storage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const [message, overwriteMessage] = useState("Hello World!");message = "Hello Programming!";overwriteMessage(message)// ^ // | // ∟ Overwrite the information in your shelf space in Central Storage with our changed copy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Hope this helps someone better understand the concept of the &lt;code&gt;useState&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>Set Up A Global .gitignore</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Sat, 09 Jan 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/jonstodle/set-up-a-global-gitignore-3gbh</link>
      <guid>https://dev.to/jonstodle/set-up-a-global-gitignore-3gbh</guid>
      <description>&lt;p&gt;If you've been using git for any amount of time, you've come across &lt;code&gt;.gitignore&lt;/code&gt;. I'm not going to go through how it works, but did you know you can set up a &lt;em&gt;global .gitignore?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What do you put in this global .gitignore? My recommendation is caches and auto-generated files and directories created by your operating system, and your editor/IDE of choice. I share my .gitignore across multiple operating systems, so I've ended up with quite a comprehensive one.&lt;/p&gt;

&lt;p&gt;As a starting point, I think this one works pretty well: &lt;a href="%5Bhttps://www.gitignore.io/?templates=rider,linux,macos,windows,clion+all,monodevelop,intellij+all,visualstudio,jetbrains+all,visualstudiocode%5D(https://www.gitignore.io/?templates=rider,linux,macos,windows,clion+all,monodevelop,intellij+all,visualstudio,jetbrains+all,visualstudiocode)"&gt;global .gitignore starting point&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What to put in the repository .gitignore? I recommend putting caches and auto-generated files and directories created by tooling used by your code or on your code, and auto-generated files and directories specific to the repository.&lt;/p&gt;

&lt;p&gt;My rule of thumb for where to put a specific ignore clause is to consider at what "level" the choice was made to use the tool that creates the files and directories I want to ignore were made. Personal choices, like what operating system to use, which editor or IDE, etc are ignored in the global .gitignore. Choices made for a specific repository is put in the local .gitignore.&lt;/p&gt;

&lt;p&gt;Even though a lot of you repositories share the same ignore clauses (all your JavaScript repositories ignore &lt;code&gt;node_modules&lt;/code&gt;, for example) - &lt;strong&gt;don't put that in your global ignore&lt;/strong&gt;. That just means that someone else is going to commit node_modules by accident.&lt;/p&gt;

&lt;p&gt;You can put your global .gitignore wherever you like in your file system. Personally I prefer my &lt;code&gt;home&lt;/code&gt; directory. Then you tell git where the global .gitignore file is located by saving it to the git config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# macOS / Linuxgit config --global core.excludesfile ~/.gitignore# Windowsgit config --global core.excludesfile %USERPROFILE%\.gitignore\*\*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>git</category>
      <category>tips</category>
    </item>
    <item>
      <title>Alpine.js</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Thu, 31 Dec 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/jonstodle/alpine-js-22fe</link>
      <guid>https://dev.to/jonstodle/alpine-js-22fe</guid>
      <description>&lt;p&gt;jQuery has been a great way to quite easily add some interaction to your static HTML, but it might start to feel a bit heavy-handed once you start trying to coordinate multiple parts of the page.&lt;/p&gt;

&lt;p&gt;Wouldn't it be nice if there was a way to set up this interactivity a bit more declaratively?&lt;/p&gt;

&lt;h1&gt;
  
  
  Enter &lt;a href="https://github.com/alpinejs/alpine/"&gt;Alpine.js&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;Add Alpine to your page like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;script src="&amp;lt;https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js&amp;gt;" defer&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're then able to declare simple components, directly inside your HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;div x-data="{ open: false }"&amp;gt; &amp;lt;button @click="open = true"&amp;gt;Open Dropdown&amp;lt;/button&amp;gt; &amp;lt;ul x-show="open" @click.away="open = false" &amp;gt; Dropdown Body &amp;lt;/ul&amp;gt; &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;x-data&lt;/code&gt; indicates the &lt;em&gt;root&lt;/em&gt; element, and the initial state of your component. The children of that element are now able to listen to events with the &lt;code&gt;@&amp;lt;event name&amp;gt;&lt;/code&gt; syntax. Alpine also has some shortcuts, such as &lt;code&gt;x-show&lt;/code&gt; which hides or shows an element.&lt;/p&gt;

&lt;p&gt;Alpine's choice in style is lifted straight from Vue, so if you're somewhat familiar with Vue, you should feel right at home with Alpine's vocabulary.&lt;/p&gt;

&lt;p&gt;Speaking of Vue, it's also possible to create reusable components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&amp;lt;div x-data="dropdown()"&amp;gt; &amp;lt;button x-on:click="open"&amp;gt;Open&amp;lt;/button&amp;gt; &amp;lt;div x-show="isOpen()" x-on:click.away="close"&amp;gt; // Dropdown &amp;lt;/div&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;script&amp;gt; function dropdown() { return { show: false, open() { this.show = true }, close() { this.show = false }, isOpen() { return this.show === true }, } } &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;dropdown&lt;/code&gt; returns an object which contains all the component code: state is defined using fields and functions are declared in the standard way.&lt;/p&gt;

&lt;p&gt;Setting &lt;code&gt;x-data&lt;/code&gt; to the result of &lt;code&gt;dropdown&lt;/code&gt; makes the fields and functions available to all child elements. Use this to easily reuse some logic.&lt;/p&gt;

&lt;h1&gt;
  
  
  Stimulus
&lt;/h1&gt;

&lt;p&gt;Another framework trying to do much of the same thing is &lt;a href="https://dev.to/scottw/stimulus-2jio"&gt;Stimulus&lt;/a&gt;: Use your existing HTML and sprinkle in some JavaScript.&lt;/p&gt;

&lt;p&gt;I'm not completely sold on Stimulus. I think it's the right idea, but it's not executed as elegantly. Alpine feels a bit less in your way, but that's just a personal preference.&lt;/p&gt;

&lt;h1&gt;
  
  
  Closing thoughts
&lt;/h1&gt;

&lt;p&gt;If you're in need of some interactivity on your so far static page, really give &lt;a href="https://github.com/alpinejs/alpine/"&gt;Alpine&lt;/a&gt; a look. I've had success with it so far when all I need is a bit of sprucing up in my static HTML.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>alpine</category>
      <category>javascript</category>
    </item>
    <item>
      <title>You're Allowed To Write Slow Rust Code</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Thu, 01 Oct 2020 06:31:19 +0000</pubDate>
      <link>https://dev.to/jonstodle/you-re-allowed-to-write-slow-rust-code-1l6j</link>
      <guid>https://dev.to/jonstodle/you-re-allowed-to-write-slow-rust-code-1l6j</guid>
      <description>&lt;p&gt;There's a thing that comes up from time to time in the Rust community: people wanting to optimize their code. Make the code run faster. Make it allocate less memory. These are worthy goals, but maybe not necessary for all projects. Just because your program is written in Rust, it doesn't have to be optimized to the moon and back to do it's job. In a lot of cases, you'll be fine using &lt;code&gt;.clone()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There's a fantastic quote from a discussion on the &lt;a href="https://users.rust-lang.org/"&gt;Rust user forums&lt;/a&gt; which I always think of when these discussions emerge:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Just because Rust allows you to write super cool non-allocating zero-copy algorithms safely, doesn't mean every algorithm you write should be super cool, zero-copy and non-allocating.&lt;br&gt;&lt;br&gt;
-- &lt;a href="https://users.rust-lang.org/t/feeling-rust-is-so-difficult/29962/15"&gt;trentj on The Rust Programming Language Forum&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course there's a time and place for &lt;em&gt;super cool no-allocating zero-copy algorithms&lt;/em&gt;, but very often it's not the time, nor the place. You can write fantastically effective code with Rust, but &lt;strong&gt;you don't have to&lt;/strong&gt;! A lot of the time it's entirely fine to just write code that works with minimal effort. You don't have to spend 4 days trying to figure out how lifetimes work just to avoid calling &lt;code&gt;.clone()&lt;/code&gt; a few times.&lt;/p&gt;

&lt;p&gt;Don't spend time trying to make micro optimizations now. Take the easy route. You'll probably come back to that piece of code in a few months time, smile, and change that &lt;code&gt;.clone()&lt;/code&gt; to something more efficient.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;p&gt;&lt;small&gt;NB: Watch this &lt;a href="https://youtu.be/rAl-9HwD858"&gt;video by Jon Gjengset&lt;/a&gt; if you want a good, pragmatic walk through of lifetimes in Rust.&lt;/small&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>commentary</category>
    </item>
    <item>
      <title>An Analogy for Multi Tasking</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Tue, 15 Sep 2020 13:44:02 +0000</pubDate>
      <link>https://dev.to/jonstodle/an-analogy-for-multi-tasking-nb</link>
      <guid>https://dev.to/jonstodle/an-analogy-for-multi-tasking-nb</guid>
      <description>&lt;p&gt;A lot of times the words &lt;em&gt;concurrency&lt;/em&gt; and &lt;em&gt;parallelism&lt;/em&gt; are used interchangeably or used incorrectly. I'd like to present this analogy as a way to understand the difference.&lt;/p&gt;

&lt;h1&gt;
  
  
  Synchronous Work
&lt;/h1&gt;

&lt;p&gt;Let's start with the most straight forward term: synchronous. In programming this means that work is done in a sequential order, no working on multiple tasks at once. In the context of code, this means each line is executed after the one before it (disregarding loops, and what not).&lt;/p&gt;

&lt;p&gt;Imagine a carpenter making a simple wooden chair: They saw and cut the different pieces, sand them down, paint them, wait for the paint to dry, then assembles the pieces, creating a finished product.&lt;/p&gt;

&lt;p&gt;All of this is done in sequence, one after the other. Even waiting for the paint to dry is done in sequence, meaning that no other actions are done while waiting - not even working on other chairs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Concurrency
&lt;/h1&gt;

&lt;p&gt;Concurrency is a sort of time share. Instead of waiting for a process to resume work, we'll do something else in the meantime. Why sit around waiting for a mouse click from the user while there's other work to do? We can get back to handling mouse clicks once there are any mouse clicks to handle.&lt;/p&gt;

&lt;p&gt;To continue the analogy with the carpenter: This time when the carpenter makes the chair the steps are the same, but multiple chairs are made at the same time. After sawing, sanding and painting the wooden pieces, instead of waiting idly while the paint is drying the carpenter starts working on a new chair.&lt;/p&gt;

&lt;p&gt;When there's time to spare, and there's work to do, we can do that &lt;em&gt;concurrently&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Parallelism
&lt;/h1&gt;

&lt;p&gt;Parallelism only became a thing when CPUs gained multiple cores. Now computers were truly able to do multiple things at the same time. Instead of jumping back and forth between tasks when there are a bit of spare time, parallelism is doing multiple things at the exact same moment.&lt;/p&gt;

&lt;p&gt;This time, the carpenter has been cloned. There are now multiple copies of the carpenter, all making chairs at the same time. They saw, sand, paint, wait and assemble at the same time.&lt;/p&gt;

&lt;p&gt;Remember that each individual carpenter is still capable of working concurrently. They don't need to wait idly while the paint dries. Each carpenter works &lt;em&gt;concurrently,&lt;/em&gt; while working in &lt;em&gt;parallel&lt;/em&gt; with the other carpenters.&lt;/p&gt;




&lt;p&gt;Hope this helps clearing the terms up a bit.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>tips</category>
      <category>commentary</category>
    </item>
    <item>
      <title>PSA: delegate is a Thing</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Mon, 31 Aug 2020 21:35:46 +0000</pubDate>
      <link>https://dev.to/jonstodle/psa-delegate-is-a-thing-1j69</link>
      <guid>https://dev.to/jonstodle/psa-delegate-is-a-thing-1j69</guid>
      <description>&lt;p&gt;This is just a short reminder to all C# developers defining and implementing interfaces with a single method:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h3&gt;
  
  
  What you are looking for is &lt;code&gt;delegate&lt;/code&gt;
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;A &lt;code&gt;delegate&lt;/code&gt; is a way to define the signature of a method. It can then be implemented by a &lt;code&gt;Func&lt;/code&gt;, an &lt;code&gt;Action&lt;/code&gt; or class method, whichever fits the best.&lt;/p&gt;

&lt;p&gt;They even work nicely with dependency injection: a &lt;code&gt;delegate&lt;/code&gt; is just a definition, not an implementation. If you want to preserve testability, that's taken care of: in tests you can just pass in a dummy implementation by way of a &lt;code&gt;Func&lt;/code&gt; or &lt;code&gt;Action&lt;/code&gt;; no mocking framework needed.&lt;/p&gt;

&lt;p&gt;Here's an example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Definition
public delegate void SendEmail(string recipient, string sender, string subject, string message);

// Registering with a DI system
services.AddTransient(_ =&amp;gt; (recipient, sender, subject, message) =&amp;gt; { /* Implementation */ });
// or
services.AddTransient(_ =&amp;gt; StaticClassWithImplementation.StaticMethodImplementingDelegate);

// In testing
var systemUnderTest = new ClassThatNeedsToSendEmails((_, __, ___, ____) =&amp;gt; { log.Info("Sent email"); });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't overcomplicate with interfaces and classes, what could simply be a delegate.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>c</category>
      <category>opinion</category>
    </item>
    <item>
      <title>Type Safety Doesn't have to be All or Nothing</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Mon, 27 Apr 2020 19:51:38 +0000</pubDate>
      <link>https://dev.to/jonstodle/type-safety-doesn-t-have-to-be-all-or-nothing-5356</link>
      <guid>https://dev.to/jonstodle/type-safety-doesn-t-have-to-be-all-or-nothing-5356</guid>
      <description>&lt;p&gt;One argument I sometimes hear against Rust is that if you have to use &lt;code&gt;unsafe&lt;/code&gt;, there's no point in using Rust, you might as well go with the old familiar C++, or some other performant/preferred language of choice.&lt;/p&gt;

&lt;p&gt;This argument always annoys me. As if the fact that you sometimes need (or want) to go outside of the safety net of the compiler, means that all the other benefits of the Rust type system, borrow checker and compiler is null and void.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;unsafe&lt;/code&gt; is kind of a misnomer, because what the keyword gives you is not necessarily an unsafe block of code. What it does give you is a block of code that has been error checked by a human, not the compiler. &lt;code&gt;unsafe&lt;/code&gt; is more appropriately &lt;code&gt;compiler, I know what I'm doing, skip checking this code&lt;/code&gt;. This is similar to how an entire program might be written in other languages.&lt;/p&gt;

&lt;p&gt;The huge benefit with Rust, on the other hand, is that the code that's manually checked by a human is contained within clearly sectioned blocks, and they are usually (but might not be) fairly small. Most Rust programmers prefer not to spend too much time outside the safety of the compiler checks.&lt;/p&gt;

&lt;p&gt;Another way to put this, in a crass way, is saying that wearing a seat belt has no benefit; you might die from a crash anyways, so what's the point of the hassle of putting it on?&lt;/p&gt;




&lt;p&gt;This short post was inspired by a person's colleagues not seeing the benefit of strict checking of 90% of the program, because 10% had to be manually checked.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>commentary</category>
    </item>
    <item>
      <title>You Need to Know About Git Worktree</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Mon, 30 Mar 2020 18:24:06 +0000</pubDate>
      <link>https://dev.to/jonstodle/you-need-to-know-about-git-worktree-4e0c</link>
      <guid>https://dev.to/jonstodle/you-need-to-know-about-git-worktree-4e0c</guid>
      <description>&lt;p&gt;I’ve been using Git for source control for many years, but there’s still lots of things you can do in Git that I haven’t even discovered yet. &lt;code&gt;git-worktree&lt;/code&gt; was one of those things. Thanks to &lt;a href="https://www.codingblocks.net/"&gt;codingblocks.net&lt;/a&gt; for mentioning this in one of their episodes.&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;I often find it’s useful to explain the problem before describing the solution; so here goes:&lt;/p&gt;

&lt;p&gt;If you are working in a team or on an open source project with multiple contributers, you might get the need to check out another branch. This is easily done, but it becomes a bit of a hassle if you have a lot of uncomitted changes. You could put all those changes in a stash, but then you usually end up with a huge pile of stashes over time because you never take the time to clean up. What you really want is the ability to check out two (or maybe more) branches at the same time.&lt;/p&gt;

&lt;h1&gt;
  
  
  The solution
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Enter git-worktree!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With this simple command you’ll be able to check out a different branch in your repository, in a seperate directory. It looks like and is used like a regular git repository, but it allows you to have multiple active working trees in the same repository at the same time. Here’s how to get going:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git worktree add ../another-directory

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

&lt;/div&gt;



&lt;p&gt;This will create a new worktree in &lt;code&gt;another-directory&lt;/code&gt;, which is a sibling of the current directory. At the same time it will also create a new branch with the same name as the directory.&lt;/p&gt;

&lt;p&gt;If you’d like to specify the branch name, you can use the &lt;code&gt;-b &amp;lt;branch-name&amp;gt;&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git worktree add -b new-branch ../another-directory

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

&lt;/div&gt;



&lt;p&gt;It’s also easy to check out an existing branch in the new directory by specifying the name of the branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git worktree add ../another-directory existing-branch

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

&lt;/div&gt;



&lt;p&gt;In this case &lt;code&gt;existing-branch&lt;/code&gt; already exists in the repository. You can actually specify anything &lt;em&gt;commit-ish&lt;/em&gt; (as it’s called in the documentation) as the last argument, be that a branch name or a commit hash for example.&lt;/p&gt;

&lt;p&gt;If you want to remove the worktree you call… eh, remove:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git worktree remove ../another-directory

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

&lt;/div&gt;



&lt;p&gt;All your commited changes will be present in the main repository, as if you had done the work there.&lt;/p&gt;




&lt;p&gt;For me, this has been a life saver in hassle when checking out branches for code review, or for doing a quick fix on a branch that’s been reviewed. Hope it helps you too.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>git</category>
      <category>tips</category>
    </item>
    <item>
      <title>If Statements With Nullable Bools</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Mon, 17 Feb 2020 19:04:56 +0000</pubDate>
      <link>https://dev.to/jonstodle/if-statements-with-nullable-bools-45ph</link>
      <guid>https://dev.to/jonstodle/if-statements-with-nullable-bools-45ph</guid>
      <description>&lt;p&gt;Nullable &lt;code&gt;bool&lt;/code&gt; in C# might sometimes feel a bit of a hassle to work with. I’m here to give you a few tips that took me embarrassingly long to pick up on. I’m hoping this saves you some hassle too.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;HasValue&lt;/code&gt; and &lt;code&gt;Value&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;These properties are present on &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; and have been since generics where introduced. It took me too long to notice them, so here they are. No need to write&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool? nullableBool = true;
bool regularBool;

if (nullableBool != null)
{
    regularBool = (bool)nullableBool;
}

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

&lt;/div&gt;



&lt;p&gt;when you can write&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool? nullableBool = true;
bool regularBool;

if (nullableBool.HasValue)
{
    regularBool = nullableBool.Value;
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;HasValue&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;nullableBool&lt;/code&gt; is not &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;Value&lt;/code&gt; returns a regular &lt;code&gt;bool&lt;/code&gt; if &lt;code&gt;nullableBool&lt;/code&gt; is not null.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Value&lt;/code&gt; also works a lot better when chaining methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool? nullableBool = true;

((bool)nullableBool).ToString();
// or, simply
nullableBool.Value.ToString();

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

&lt;/div&gt;



&lt;p&gt;I think the second option is a lot more readable.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;GetValueOrDefault&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;This method on &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; might not always save characters, but it’s very clear in it’s intent, which I believe accounts for a lot.&lt;code&gt;GetValueOrDefault&lt;/code&gt; makes it clear what your code does.So instead of the generic &lt;em&gt;null coalescing&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool? nullableBool = true;
bool regularBool;

if (nullableBool ?? false)
{
    regularBool = nullableBool.Value;
}

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

&lt;/div&gt;



&lt;p&gt;you can explicitly say that you want a default value&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool? nullableBool = true;
bool regularBool;

if (nullableBool.GetValueOrDefault(false))
{
    regularBool = nullableBool.Value;
}

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

&lt;/div&gt;



&lt;p&gt;As I said, &lt;code&gt;GetValueOrDefault&lt;/code&gt; doesn’t necessarily save on characters, but it’s clearly states what you want. This too works better when chaining methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool? nullableBool = true;

(nullableBool ?? false).ToString();
// alternatively
nullableBool.GetValueOrDefault(false).ToString();

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

&lt;/div&gt;



&lt;h1&gt;
  
  
  Direct variant checking
&lt;/h1&gt;

&lt;p&gt;Again, this is one of those things that took me too long to figure out, so here goes. A simple boolean check might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool regularBool;

if (regularBool)
{
    // some code...
}

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

&lt;/div&gt;



&lt;p&gt;but that doesn’t work with a &lt;code&gt;bool?&lt;/code&gt;, so I used to do something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool? nullableBool = true;

if (nullableBool.HasValue &amp;amp;&amp;amp; nullableBool.Value)
{
    // some code...
}

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

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool? nullableBool = true;

if (nullableBool ?? false)
{
    // some code...
}

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

&lt;/div&gt;



&lt;p&gt;Turns out, you can just do this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bool? nullableBool = true;

if (nullableBool == true)
{
    // some code...
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nullableBool == true&lt;/code&gt; will evaluate to &lt;code&gt;false&lt;/code&gt; if &lt;code&gt;nullableBool&lt;/code&gt; is either &lt;code&gt;false&lt;/code&gt; or &lt;code&gt;null&lt;/code&gt;, in other words: &lt;em&gt;not true&lt;/em&gt;. It seems so obvious in retrospect, but I’d become so accustomed to writing &lt;code&gt;if (regularBool) ...&lt;/code&gt;, instead of &lt;code&gt;if (regularBool == true) ...&lt;/code&gt;, that it didn’t occur to me to write it out in full for &lt;code&gt;bool?&lt;/code&gt;s.&lt;/p&gt;

&lt;h1&gt;
  
  
  The other &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt;s
&lt;/h1&gt;

&lt;p&gt;This does work for the other nullable primitive types too. You can for example shorten this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int? nullableInt = null;
int regularInt;

if (nullableInt.HasValue &amp;amp;&amp;amp; nullableInt == 100)
{
    regularInt = nullableInt.Value;
}

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

&lt;/div&gt;



&lt;p&gt;to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int? nullableInt = null;
int regularInt;

if (nullableInt == 100)
{
    regularInt = nullableInt.Value;
}

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

&lt;/div&gt;



&lt;p&gt;There’s also this case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int? nullableInt = null;
int regularInt;

if (nullableInt &amp;lt; 100)
{
    regularInt = nullableInt.Value;
}

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;nullableInt &amp;lt; 100&lt;/code&gt; will evaluate to &lt;code&gt;true&lt;/code&gt; if &lt;code&gt;nullableInt&lt;/code&gt; has a value, and that value is less than &lt;code&gt;100&lt;/code&gt;. It will however evaluate to &lt;code&gt;false&lt;/code&gt; if &lt;code&gt;nullableInt&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt;. Which one could argue is correct, as &lt;code&gt;nullableInt&lt;/code&gt; isn’t a number lower than &lt;code&gt;100&lt;/code&gt;, it’s &lt;code&gt;null&lt;/code&gt; (which isn’t a number at all).&lt;/p&gt;




&lt;p&gt;I hope you found this interesting, or at least helpful.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Running Personal Projects for Free</title>
      <dc:creator>Jon Stødle</dc:creator>
      <pubDate>Fri, 31 Jan 2020 16:07:14 +0000</pubDate>
      <link>https://dev.to/jonstodle/running-personal-projects-for-free-3fe2</link>
      <guid>https://dev.to/jonstodle/running-personal-projects-for-free-3fe2</guid>
      <description>&lt;p&gt;I have some personal projects, which consists of some simple web apps and some data they need to store, and I’ve always wanted to run them as cheap as possible. My current solution has them running at no cost at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;It’s worth mentioning that these projects don’t have very high requirements. They’re mostly used by me and some of my family, which doesn’t amount to much traffic or storage at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend
&lt;/h2&gt;

&lt;p&gt;I have a couple of sites which are just statically generated web pages (&lt;a href="https://blog.jonstodle.com"&gt;like my blog&lt;/a&gt;), and a few web apps written with &lt;a href="https://svelte.dev/"&gt;Svelte&lt;/a&gt;. All of this I host on &lt;a href="https://www.netlify.com/"&gt;Netlify&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Netlify is easy to set up and get started with, but they have a lot of nice advanced features too. You can get started for free and host as many sites as you like.&lt;/p&gt;

&lt;p&gt;They have built-in support for automatic deploys from Github. It’s easy to set up and they even build your frontend project for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend
&lt;/h2&gt;

&lt;p&gt;My backend is split in two: the logic and the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  The logic
&lt;/h3&gt;

&lt;p&gt;I have some code that I want to run on a server. It’s basically a few REST APIs fetching and formatting some data. All of this logic I’m running as serverless functions through &lt;a href="https://www.netlify.com/products/functions/"&gt;Netlify Functions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;They support writing the functions in Javascript or Go. And you get 125,000 free requests to the functions each month with each site you host on Netlify. I’m not going to hit that limit for a while yet.&lt;/p&gt;

&lt;h4&gt;
  
  
  Netlify Dev
&lt;/h4&gt;

&lt;p&gt;Netlify recently launched a new feature with their Netlify CLI tool called &lt;a href="https://dev.to/scottw/netlify-dev-3je3-temp-slug-5267792"&gt;Netlify Dev&lt;/a&gt;. Netlify Dev let’s you spin up their server backend locally, making it very easy to develop your site with Netlify in mind.&lt;/p&gt;

&lt;p&gt;Netlify Dev hosts your web app and any associated serverless functions in your project, locally. It even fetches any secret/environment variables you have stored for the site from Netlify and exposes them to the local environment.&lt;/p&gt;

&lt;p&gt;I use this all the time when working on my web apps.&lt;/p&gt;

&lt;p&gt;I originally intended to write the serverless functions in Go, but Netlify Dev only support Javascript functions, and &lt;a href="https://community.netlify.com/t/support-for-go-lambdas-in-netlify-dev/6751/2"&gt;will do so for the forseeable future&lt;/a&gt; 😔.&lt;/p&gt;

&lt;h3&gt;
  
  
  The database
&lt;/h3&gt;

&lt;p&gt;And, finally, the database. I’ve only recently found a proper (in my mind) solution for this.&lt;/p&gt;

&lt;p&gt;I started out using &lt;a href="https://airtable.com/"&gt;Airtable&lt;/a&gt; for storage. They have a nice mobile app which made it easy for my significant other to enter new data, and they expose a pretty decent API for getting the records out of the database.&lt;/p&gt;

&lt;p&gt;My problem with Airtable, however, have always been their unwieldy query syntax and the fact that users of a table can change the names of the fields the JSON object you get from the REST API. If my significant other changes the name of a column from &lt;code&gt;Description&lt;/code&gt; to &lt;code&gt;description&lt;/code&gt; my frontend code breaks…&lt;/p&gt;

&lt;p&gt;So, for a while I’ve been wanting to move over to a “proper” database, and I recently made the move to MongoDB. They have a, relatively, new offering called &lt;a href="https://www.mongodb.com/cloud/atlas"&gt;MongoDB Atlas&lt;/a&gt; which let’s you run managed MongoDB servers on any of the three big cloud providers (Azure, AWS, Google Cloud).&lt;/p&gt;

&lt;p&gt;When I first heard about it I didn’t even consider it an option, until I realised they have a free tier! Up to 512MB of storage. Which, again, is more than enough for me. At the moment I’m consuming something akin to 1MB.&lt;/p&gt;

&lt;p&gt;MongoDB Atlas is super easy to set up too. You specify you want the free tier, which provider you want to use and which region to run the server in. After that, you’re up and running in a couple of minutes.&lt;/p&gt;

&lt;p&gt;MongoDB also has a nice data explorer called &lt;a href="https://www.mongodb.com/products/compass"&gt;Compass&lt;/a&gt; which let’s you view and edit your database structure and documents.&lt;/p&gt;




&lt;p&gt;My current running cost for my 10 web apps/sites is the total of NOK 0. I’m pretty happy with that, I have to say 😁&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>tip</category>
    </item>
  </channel>
</rss>
