Chris Jarling

Fullstack Engineer
1st Jan, 2024

What I will focus on in 2024

In the light of the third point in this list, I'll keep what I want to do this year simple. I have three topics I want to focus on:

  • Have fun
  • Be healthy
  • Simplify

They're also vague and not quantifiable. This is against what every productivity expert will tell you. I learned for myself that hard numbers on goals will create too much pressure on me and I will just let it slide. Those are more like loose guidelines, or themes for the year.

Have fun

I tend to forget about having fun. My life is pretty good right now, I get to do a lot of things I enjoy. However, I have a tendency to see everything as tasks that need to be done. I'm good at doing tasks, but I will do it with a grim precision, finish it and move on to the next. This makes me unhappy.
I will work on being more present in the moment in order to enjoy whatever I'm doing, if possible. If I cannot enjoy it, at least I will work on not letting it ruin my mood.

Be healthy

I'm 32 now and I can feel it. They days of invulnerable youth are over. My body asks for care and maintenance and I will provide it. It matters. This will be done mostly through two things: Eating well and physical activity.

Luckily, I have a head start on both: My wife is very passionate about cooking and eating healthy, so in order to step up my game there, I just need to cut back on buying crap (mostly soda and highly processed vegan meat alternatives). Because of our dog, I take at least on walk a day, two on most days, so I have some physical activity under the belt automatically. I only need to add a workout here and there. Those should be fun, so they don't become a chore, will most likely be a mixture of gym, running and climbing.

Simplify

I noticed it's good for my mind to simplify everything. Most important will be minimizing my possessions, but I plan to let the pattern of simplifying get into every single aspect of my life. I started with this very website. It's a lot simpler now.


29th Dec, 2023

2023 Review

Ah, it's this time of year again.

Life, in general

  • Our second daughter was born in late November this year. The time before and after the birth have been one hell of a ride, but we're very excited she's healthy and with us.
  • Spent a lot of time with our older daughter, picking up new hobbies and doubling down on old ones. We went rock climbing a lot and rode our bikes in the summer. We also started playing Pokemon Go together (a hack to get her out and ride the bike more). We programmed her first website (which is regularly updated, but I don't feel confident in sharing here) and once the nights got longer, we even made some trips in American Truck Simulator.
  • Did a lot of photography in the first half of the year. It's an old hobby of mine which I picked back up. Because of life, I spent less time taking photos in the second half of the year. Looking forward to picking it back up soon! Some of the pictures are on Instagram, if you're interested.
  • I made an effort to get back in touch with people I once was friends but somehow lost contact with and also to stay more in contact with close friends. While there is a lot of room for improvement, I'm happy I at least have this on my radar. I think I may need to use a system to be more successful.

Side projects

  • The project I worked on with the most consistency is this website. I launched a rebuild of it early this year and added more and more features over the year as I saw need. Most notable, there now is the Garden and my reading notes. There were other features that I briefly added and removed again, like bookmarks. I also used this site a lot to test out interesting products, like TinaCMS or Supabase.
  • I did a bunch of writing this year. Even though I set out to do better, the biggest part of what I write stays private: A lot of notes (that I try to publish in the garden whenever I have time), journal entries or just free writing. I also filled a few paper notebooks this year. Very happy with that, gives me a lot of clarity in my head. Could use more clarity still, though. I terms of numbers, I wrote 21 articles this year on here, which is way short of the "one article a week" goal I've had for a few years now, but it's also the year I published the most yet, so the direction seems right.
  • As for actual projects, there were a few. I tipped my toes into game development again in a few languages (rust, typescript) and engines (godot). I liked it, but eventually always found something more interesting related to the web. Maybe some day I'll finish a game. None of the projects are actually finished (of course), but a few I like are:
    • Carpedi: A todo-app that will delete your tasks after a day (after the approach Jason Fried shared in an interview I read a few years ago)
    • copy-current-url: A chrome extension that clones the nice Arc feature where you can copy the current url with a key combination (when switching between Arc and Chrome, this was the feature I was missing most
    • click-clack: A typing test I build mostly because I wondered how one would build such a thing
    • ictl (I'll check that later): A bookmarking service that I'd like to use (but is not very usable in it's current state, I only just started it)
  • I read a lot this year. I think the biggest part was essays and articles on the web, but also a few books. While the quantity of books I read was lower than in previous years, I feel like the quality of my reading was much better: I took more notes and remembered more of what I read. A positive development. My favorite book was No Rules Rules.

Gigs

I started working at Gigs in November 2022, so this was my first full year and boy did I enjoy it. I'm not sure into how much detail I am allowed to get here, so I'll keep this somewhat general. I was able to be part of some interviews, I was able to onboard a colleague, I got more comfortable in sharing small videos of what I built and writing internal blog posts about what we did in our team. We shipped some exciting features and had more public appearances. It's the most interesting job I ever had and I'm beyond excited to see where we're heading next year (we're hiring, btw).

Health/Fitness

  • I got Covid for the first time in early April. The sick period as it was pretty mild, however, I dealt with fatigue for a few month. Got my second infection a few weeks ago, so far no longer lasting symptoms.
  • Got into a good running habit in the summer for a few months. Unfortunately, did not keep it up.

Travel

  • Spent some time in Berlin earlier this year to meet some people in the office. I arrived on a weekend so I had a full Sunday for myself (which doesn't really happen anymore once you have kids). Spent the day walking through Berlin, drinking coffee and listening to an audiobook or in a cafe reading. Also had the chance to work from our Berlin office, which is always pleasant to do.
  • Took a work trip to Portugal in March. The retreat was great, unfortunately did not get to see too much of Portugal. Planned to stay in Porto for a few more days, but unfortunately caught Covid, so I did not really see much of the city.
  • Went on a short vacation with friends to northern France in the summer, to a small town named Cucq. There was nothing spectacular around, but it was a nice trip with great people. We went sledding in the dunes!
  • At the very end of the year, we decided we need to see something different after being sick for 4 weeks straight and spent a few days on a lovely farm in the Netherlands called Huize Blokland. It was a great stay, especially with kids as we were allowed to explore around the farm freely and the hosts were lovely. Unfortunately, we had to cut this trip short because the youngest one got sick.

Tough times

There were a bunch of tough times throughout the year that allowed me to grow as a person. Most memorable are the ~2 months early in my wife's pregnancy where she was tied to the bed most of the time. I somehow managed to get work, taking care of our daughter (who wasn't in daycare) and my wife and the housekeeping done. Not only did I manage it, I also created some of the best memories with my daughter in this time as well as shipped some complex features at work.
There are a lot of situations, once you become a parent, that you would say are not possible to handle when laid out to you by someone else, but if you have to do it, you just make it work somehow because there is no other option. This is one of them.

In general, I'm very content with my mindset towards troubling times. I'm not nearly as resilient as I'd like to be, but I approach those situation with a constrictive mindset and embrace them as chances to grow.

Purchases

As I try to be mindful with where I spend my money and what things I accumulate (I'm failign miserably if you ask my wife), it's fair to also reflect on things that I enjoy having spent money on and things that I regret spending money on.

Best purchases

  • Tumble Dryer. Not sure how we managed to live before, but especially now with a newborn again, it's so convenient to throw towels and bodies in the laundry and have them clean and ready to use the same day. The alternative would have been to buy a lot more items to make sure we always have some available while others hang to dry.
  • My Fixed Gear Bike. I was using an old fitness bike for chores and to get around town. I started watching a lot of Fixie videos and decided to buy an entry level one. Really enjoy the simplicity of it.

Worst Purchases

  • Switch Lite. Thought it would be great for the new Zelda but I used it for maybe an hour or two before I sold it. I get why people like the switch, it's just not for me.
  • The Ergodox EZ. While I've written about how much I liked it before, I eventually sold that unit when it became too much about configuring my tool and less about the outcome of what I was using it for. Late this year I had the idea that I just did not do it right the last time and bought a cheap one off eBay again. Turns out it's still the same: I like the idea of it, I can see how it can be a powerful tool, but I feel like it's getting in the way of what I really try to achieve. Sold it with a small profit at least.

22nd Dec, 2023

On Solipsism

Let's assume you and me are standing in a room. The room has white walls, no windows, a white floor. It is empty. Except for the big, blue table that's placed right in the centre of it. We both look a the blue table. I point at it and ask you: "Do you see that blue table?". You respond "yes, I do". How can I be sure that the blue colour you see is the same thing that I see?

I can't. The only thing I can be sure of is that the table has a colour that we both agreed to label as blue. Maybe your blue is my red and we just agreed upon a word for a colour to be able to communicate.

Let's go a step further.

You and me, we both stand in the room still, looking at the table that has a colour. I look at you, the person I just asked a question and had an agreement on regarding the colour of an object in front of me. How can I be sure that you actually exist? I can't. I can listen to you tell me about your experiences in this world that sound a lot like my experiences. But I can't be sure. I can only assume. How can I be sure that anything outside of my own thoughts actually exists?

This is the idea of solipsism (or my naïve interpretation of it). Let's not stay on that thought for too long, because I'm afraid of staring into that abyss for too long. Let's keep our assumption that other people exist. That the world exists and that both you and I have made our own experiences in this objective space.

But just for fun, let's think about some questions that we might have if we were to accept the idea of solipsism:

  • If we accept the idea of metaphysical solipsism (nothing outside of my own mind exists, I made reality up), this would mean that all experiences in my life so far are made up by myself. That would also mean that every thing that ever happened, from very bad to brilliant, is a shade of my mind
  • I sometimes do forget things, then remember them later on. I am aware of the sensation of having forgotten said thing. Shouldn't this happen to the world I created as well? Taking the world map as an example, why haven't I ever "misplaced" a continent. Or could the Mandela-Effect be exactly that?
  • If I made this world up and now knew about it, shouldn't I be able to manipulate it somehow?
  • If I can't, who is responsible for the sensations I experience?

I've come back to this idea every once in a while over the past few years. It's a compelling idea to think about. I may think about it further. I feel like there might be a link to the simulation theory somewhere. However, I don't think it is true. I like the idea of not being alone. Especially on this night, after midnight, when a storm is rattling on the house. It's an interesting idea, though.


13th Dec, 2023

Create and retrieve a record with supabase.js

Creating a new record in supabase is pretty straight forward:

const { error } = await supabase.from('results').insert({
  wpm: results.wpm,
  errorRate: results.errorRate,
  quote_id: results.quoteId,
})

When creating a single resource, I often times want to use it right away. However, supabase's insert() only will only tell you if inserting was successful or not.
In the documentation you can toggle a (not very obvious) tab that will show you what to do if you want to use the created record right away:

const { data: result, error } = await supabase
  .from('results')
  .insert({
    wpm: results.wpm,
    errorRate: results.errorRate,
    quote_id: results.quoteId,
  })
  .select()

This will return an array (with only one entry in this case) though.

return result
// ^
// const result: {
//   created_at: string;
//   errorRate: number | null;
//   id: number;
//   quote_id: number | null;
//   wpm: number;
// }[]

So we use single() to tell supbase that we're only expecting one row. Full call looks like this:

const { data: result, error } = await supabase
  .from('results')
  .insert({
    wpm: results.wpm,
    errorRate: results.errorRate,
    quote_id: results.quoteId,
  })
  .select()
  .single()

if (error) {
  // error handling
}

return result.id

Since I keep forgetting this, hopefully this will help me remember.


8th Dec, 2023

Differences between Types and Interfaces in TypeScript

In TypeScript, you can choose between Type and Interface to define an object type. In this article, I want to write down the (few) differences between the two. For the longest time, I had the idea in my head, that it’s fine to use either and there are no big differences. Which turns out to be very close to the truth.

For most use cases, it does not make a difference if you use a type or an interface. The TypeScript documentation states they can be swapped freely. You can even merge interfaces and types:

type Name = {
  name: string
}

interface Age {
  age: number
}

type Person = Name & Age

const me: Person = {
  name: 'Chris',
  age: 32
}

The differences

If you’d prefer to just read annotated code, this playground example might be what you want.

The first difference you may have noticed above is not a functional one, but one in the syntax. Types and Interfaces differ in how they are declared and in mutating them.

type Name = {
  name: string
}

interface Age {
  age: number
}

The declaration looks pretty similar, but when we want to extend an Interface or a Type, the differences are more obvious:

// Interface
interface Animal {
  name: string
}

interface Insect extends Animal {
  canSting: boolean
}

// Type
type Animal = {
  name: string
}

type Insect = Animal & {
  canSting: boolean
}

As you can see, Interfaces are more verbose in comparison to Types. Depending on whether you like that or not, this could be a factor in deciding which one to use.

Another, and basically the only real big difference, is extendability.

Once you defined a Type somewhere, it cannot be mutated in any other place it is used.

type Person = {
  name: string
}

type Person = {
  // ^ Duplicate identifier 'Person'
  age: number
}

Note that this does not mean that you cannot have many Types throughout your codebase with the same name. In a react project, I often times have a Props type per component file. However, if you import a Type from somewhere, it is set and cannot be manipulated.

This is different for Interfaces. You can define the same Interface multiple times in a row and it will be merged into a final interface:

interface Person {
  name: string
}

interface Person {
  age: number
}

const me: Person = {
  name: 'Chris',
  age: 32
}

Which one should I use?

There are not many factors on which we can make the decision on wether it's best to use Types or Interfaces. The TypeScript documentation states:

If you would like a heuristic, use interfaceuntil you need to use features from type

Which could be a starting point. Another factor would be your personal preference on verbosity.

Here’s my personal opinion: I don’t like the verbosity, as it does not blend in well with the rest of the JavaScript syntax I usually write (I don't use classes a lot; however, if you use classes a lot, this argument can easily be reversed), where somewhat cryptic symbols are what I am used to anyways. I strongly dislike the mutability of interfaces. If I use a typed language, I want my types to be a single source of truth. This is my only real argument for using Types above Interfaces.

Also, it's called TypeScript, not InterfaceScript, so...

Further Reading

For more detailed information on the topic, I recommend checking out:


3rd Dec, 2023

Spotify Wrapped 2023

(Sorry for the large images in this post. I may make images be prettier sometime in the future.)

Another year in music done. Here's what mine has looked like:

Overview of what I listened to

I listened to around 31,000 minutes of music over the year, which translates to about 520 hours or 21 full days. That's a little less compared to last year (~35,000 minutes).

Here's some details about the list:

Top Artists

2023 Top Artists

I really enjoyed listening to Lionheart, especially after seeing them live in late summer. Great show!

I listened to a lot of Drake as well, but it was almost exclusively the "Scorpion" album.

As for the remaining artists, they're part of the "Casey Nesitat Music" playlist I listened a lot to while running, after I started rewatching Casey's Vlogs in early summer.

Top Songs

2023 Top Songs

"I'm Sitting Here Wondering" is the first song in the "Casey Neistat Music" playlist, so I listened to that every time I went for a run at least once.

Now "Butterfly" by "Crazy Town" might look weird. But it's the first song in another playlist I listened to a lot while riding my new fixie.

"Hellrot" was my spring song when the sun started to finally come out again.

Genre distribution

2023 Genere distribution

I think Spotify has Lionheart listed in "Modern Rock" instead of "Hardcore" or "Beatdown", hence the large portion of it. The rest sounds about right to what I like to listen to.


27th Nov, 2023

The End-of-History illusion

I recently watched a video by Niklas Steenfatt1 where he briefly mentioned the End-of-History illusion. I never heard of it before, but it hits right home for me. Here's what it is:

The end-of-history illusion is a psychological illusion in which individuals of all ages believe that they have experienced significant personal growth and changes in tastes up to the present moment, but will not substantially grow or mature in the future.

This illusion says that people are able to see significant changes they made in hindsight, but fail to predict that these changes can continue in the future. People therefor believe that they are "done" now and will not continue to change much in the future.

I fall prey to this illusion a lot. If I look back five years from now, I was 27 years old, was living in my own apartment for the first time and was going through the hardest breakup of my life. I hadn't met my (now) wife yet, my salary was less than half what I make now and I had no clue where to go with my life (spoiler: that's still true, I just have a few more ideas of what I do not want to do with it).
That's a lot for just five years2. And yet, I cannot imagine that in five years from now, changes of the same magnitude could be possible in my life. It's strange.

They authors of the study behind the illusion have an idea of why that is the case: The brain is lazy. It's easier to reconstruct what has happened than to construct what might happen. It's borderline impossible to do so. I could not have imagined half of the things that happened during the past five years, five years ago. So the brain chooses not to do it.

Footnotes

  1. It's in German, but I suggest you watch it if you can. It somewhat relates to what I wrote about goals in the beginning of the year. ↩

  2. In fact, when I tried to come up with where I was five years ago, I ended up 4 years ago and was only able to correct myself because I looked at some old pictures of the time. ↩


22nd Oct, 2023

Teaching is always learning

I recently was the onboarding partner for a new team member at work, which means I'm showing them around and are the dedicated person for them to ask any questions. This experience made me think about the other times in life where I did teach people something: The times I worked with less experienced developers, the times I was an assistant at university and gave courses for students or the times I wrote about my learnings on this website. It made me realise why I enjoy teaching: Because I always learn something in the process.

This is not a new insight. Learning by teaching has proven to increase the understanding of a subject in students. Einstein said if you cannot explain something simply, you did not understand it (and in order to teach someone something, you have to be able to explain it in a simple way, at least initially). Or take this quote by Joseph Joubert:

To teach is to learn twice

All of this points in the same direction: In order to teach something effectively, you have to obtain a thorough understanding of the matter. Or, in reversal: In order to obtain a thorough understanding of something, bring yourself in a situation where you have to teach it to somebody. You don't even have to actually teach it so someone. It's enough to you pretend you are. I think in the case of this blog, I'm often times pretending to be teaching someone, because for all I know, nobody is reading this. And it definitely works.

I think our school system did enough damage to me to have a negative associoation of the word "teaching". When I think of it, I think of a power disparity and one person forcing the other to do what they want or else. This is not what teaching actually is, and it's important for me to write this down: Teaching is the transfer of knowledge from one head to the other.

I also think there is a distinction to be made between onboarding a person and working with a less experienced person in your field. Onboarding someone is vague. It's a lot of implicit knowledge that has to be shared. We all aim to have good documentation, but in every company I've worked in, this was an unreachable goal. There always was an effort to document everything, but we always fell short of our goal. I think that's okay. It's a byproduct of a company moving and changing.
However, that means that the knowledge that is transferred during an onboarding process, to some degree, is implicit and exist only in the heads of people. That makes the process harder for the new joiner and the person onboarding them, since sometimes you can't point to a resource that explains what you talked about. There is a lot of trust involved from the start.

The result is a difference in what I learn as the onboarding part. In general, it's one of the following:

  • The new team member has a question I know the answer to, but I could not find the answer written down anywhere. Documentation is missing and should be added.1
  • The new team member has a question and I can not give a brief and percise answer. I do not fully understand this area myself and need to look into it. I like doing this together with the new team member, it's a nice experience to learn something new together.

When writing here or working with less experienced people, things are a little different. I never made up a new programming paradigm or created a groundbreaking algorithm. That means in almost every case, there is documentation available for what we are talking about. This can be actual software documentation, or a blog post or a video. It can be as little as a code snippet in a gist. But there is always reference somewhere that can be checked to challange what I say. So one learning that frequently happens is uncovering my false understanding of something. It's easy to say "Look, you just said X, but looking at this resource, it clearly states Y". Very straight forward (but sometimes hard to accept – which is a different exercise).

Another learning that happens in this constellation is identifying holes in my understanding. It happens that the other person asks a question that I do not know how to answer, either at all or in a satisfying depth2. Writing things down here is more extreme even. If I can't write them down I don't know them. This is what this website is: It's a reference, yes, but it's also always a test of my knowledge and my understanding of what I learned.

This post is no different, by the way. It's me trying to explain the concept of teaching to learn.

Footnotes

  1. This should be done by you directly, because it will be forgotten otherwise ↩

  2. In this situation, please admit that you don't know and either come back with something or find the solution together. Do not pretend you know because you feel like that as the "teacher" you have to. People will notice and it provides no value to anyone ↩


28th Sep, 2023

On Therapy

I recently started seeing a therapist. I do not have many insights about the session to share yet, but I wanted to write about it here, for two reasons.

First, this is my personal blog. I like the idea of being able to read through some of these pages later on and remember what was going on in my life. I have not shared many personal things on here lately and I want to change that.

Let me preface this with the assurance that I am fine and I am safe.
However, I had the feeling that something was wrong enought in my life to jusify professional aid (depressive episodes & anxiety, mostly), for quite a while now. For the past three years, I made it my number one goal to get in touch with therapists. And I really meant to do it. But I never mustered up the curage to pick up the phone and ask for help. Until now, that is. And thats a big win for me.
I'm not in therapy yet, I've had three sessions with two different therapists. It might take a while before a slot is avialable for me. But I'm taking steps in the right direction, and that's the important part. Honestly, I'm pretty proud of that.

Second, I think mental health and getting professional help still has a stigma to it. It's something we don't talk about as much as we should. It's gotten a lot better in the past years, sure. But we're still not where we could be. The only way to remove this stigma is for more people to speak up about it. And that's something I can help with, hence, this posts. I'm not a lunatic, I'm not wearing a straitjacket, I'm just someone whose head is a little broken and who needs help with that. And that's perfectly fine.


2nd Jul, 2023

Using Contentlayer

I recently migrated this website, which is powered by the great Next.js, over from the old pages router (spits on ground in disgust) over to the new app router.
I do like the app router a lot. However, I came across a problem on the way. To be honest, it was more than just one problem (which is to be expected on any major migration), but this one was really severe: My content was not being rendered anymore.

This page is basically a bunch of markdown, which Next.js reads on build and converts to html, which you then can view in your browser. In the old version, I had a huge function written that was taking care of reading those markdown files over the file system, converting them based on which type of post (article or note) they were and then storing that as html. This was done once at build time, so the page was about 95% static content and very performant.
Now, with the app router and React Server Components, some things changed and my function was now called on the server upon request and cached. That meant that the path in which it was called changed. That means, the functions was no longer able to find the files (additionally, they were not part of the bundle, so it had no chance to begin with).

That sucked. I thought about different solutions, from bundling all the markdown files to just getting rid of markdown altogether and storing everything in supabase. But one day I came across Contentlayer and that was a good day. Contentlayer just replaced the big ol' function I had for converting markdown to html. You just tell it where the markdown is and what fields you expect the files to have. And then you get out html, with a lot of convenience functions.

Here's an example of how my posts are configured in Contentlayer:

export const Post = defineDocumentType(() => ({
  name: 'Post',
  filePathPattern: 'posts/*.md',
  fields: {
    title: { type: 'string', required: true },
    date: { type: 'string', required: true },
    tags: { type: 'string', required: false },
    excerpt: { type: 'string', required: false },
    series: { type: 'string', required: false },
    slug: { type: 'string', required: false },
  },
  computedFields: {
    url: {
      type: 'string',
      resolve: (post) => `/${post._raw.flattenedPath}`,
    },
    computedSlug: {
      type: 'string',
      resolve: (post) =>
        post.slug || post._raw.flattenedPath.replace('posts/', ''),
    },
  },
}))

Most of this is just type safety for the markdown front matter. If a post does not satisfy all required fields, it will not be processed and Contentlayer will print out a warning. This prevents me from breaking my site with malformed front matter on a post.

What's interesting are the computed fields. These can be pretty much everything you want to add to the post as an attribute after the file was read. In my case, I have an url which makes sure my links to posts have the same format everywhere and a computedSlug which uses either the defined slug from the front matter or generates one.

In posts/page.tsx I can then just use the method Contentlayer generates for every entry type you configure in the config. So for posts, this would be allPosts:

import { allPosts } from '.contentlayer/generated'

export default async function PostsIndex() {
  return (
		<PostsList posts={allPosts} />
  )
}

(Please not that this is a simplified version of the page. Here's the actual version as of time of this writing).

All in all, I'm really pleased with effortless the setup was and how much more simple my code got using contentlayer.

Newer posts
Older posts
© 2024 Chris Jarling