Enjoy the detours!

barfooz.xyz

We had a nice family weekend trip. The purpose was to escape a little from our normal routine and to explore the rural land not far away from our hometown.

The first trip since I can remember being with my wife where I did not bring more technical gadgets than my phone and kindle. Usually, I take my notebook with me, on every trip. Newly, also the steam deck and iPad, just in case. Just to avoid possible boredom. (Writing this down and reading it again sounds as if I'm addicted to my gadgets. BuT i cAn stOp, iF i WaNT!)

But don't have these gadgets with me, it was refreshing just having the phone with me. I carry the notebook just in case if I'm bored and can use this time to be productive. Which is somehow good but sounds like an excuse. Without it, I was able to focus on other things. I was able to go through a lot of notes in my notion. Clean up many of my to-do lists. (Yes, there are multiples) And then there were my +99 open tabs in Firefox. I was capable of transforming 50% of them into new to-dos. The rest were mostly articles I want to read some time. I did it with a bunch of them.

At the beginning of the year, I've created 6 to-do lists in the Reminders App. 4 for each quarter. 1 for the current week and 1 for the backlog. Together with my wife, we try to go through the open to-dos and sort them every Sunday. What needs to be done in the ongoing quarter? Which tasks of this quarter can be done in the next week? These are questions we tackle on a Sunday after breakfast. (Or we try it) And it works. We both have a better overview of the things that need to be done. Before, everyone had their one agenda and these agendas collided very often. On this weekend, we thought about this approach and edited many tasks. And we were happy with the result. I'm excited about the next quarter. :)

That's it. 👋


15 of #100DaysToOffload
#log
Thoughts? Discuss...

Displays the error message: “Looks like your CSV is not formatted correctly”

Finally, I found a solution to throw an error at the frontend, while importing wrong CSV Data on the server. For Fast-CSV, I needed a solution to parse the data and put the data into the database. While this part was easy, the error message from Supabase was swallowed, and I had no practical option to present the error to the frontend. Or, there was no uncomplicated way, since now. :D

const stream = csv
  .parse(options)
  .on("error", (error) => {
    console.log(error);
  })
  .on("data", (row) => {
    result.push(row);
  })
  .on("end", async () => {
    const supabase = await createClient();
    const { error, statusText } = await supabase
      .from("fillings_import")
      .upsert(completeFillings(result))
      .select();

    if (error) {
      throw new Error(`${error.message}, ${statusText}`);
    }
  });

stream.write(fileData);
stream.end();

This was my initial solution, and the error at the end was never shown. 🤷

The new version is wrapped with a new Promise and calls reject if adding data to Supabase produces an error. Easy, right? I'm so happy that I don't need to wrap an <ErrorBoundary /> or something else.

await new Promise<void>((resolve, reject) => {
  const stream = csv
    .parse(options)
    .on("error", (error) => {
      console.log(error);
    })
    .on("data", (row) => {
      result.push(row);
    })
    .on("end", async () => {
      const supabase = await createClient();
      const { error, statusText } = await supabase
        .from("fillings_import")
        .upsert(completeFillings(result))
        .select();

      if (error) {
        console.error({ error, statusText, result });
        reject(new Error("Looks like your CSV is not formatted correctly"));
      }

      resolve();
    });

  stream.write(fileData);
  stream.end();
});

This little fix makes me happier than it perhaps should. But in the end, that it. I thought much more about a solution than it took time to write the code. I thought at least on and off for 3 days about it. And today, the “a-ha” moment under the shower. 😎


14 of #100DaysToOffload
#pelletyze
Thoughts? Discuss...

In the last few months, there were some big releases. ESLint v9 was one of them. Sadly, do to their new config approach, I was unable to upgrade Next.js. While waiting for Vercel to fix it, Tailwind CSS v4 and next-intl v4 were released. So I faced 4 big releases.

The first one I did was next-intl v4. They wrote a nice blog post before v4 was released. So you were able to prepare your codebase before the switch, which was great and worked very well and without problems. 👍

Next in line was Tailwind CSS v4. And with it, Tailwind-Merge v3. You need to upgrade them together. Because twMerge dropped tw v3 support. Basically, this worked flawlessly. But some adjustments needed to be done. I use the reset.css from Josh W Comeau which needs special treatment when used with Tailwind CSS v4. Furthermore, I've added some custom styling to the html, body and h1...h6 tags. The result was that I had to wrap them to the correct layers for, so they will not collide with TWv4.

@import "./reset.css" layer(base);
@import "./custom.css" layer(base);

While using the codemod from TWv4 to migrate everything, it swallowed my custom classes. Which I had to add back manually. The new solution is with CSS only and is straightforward.

@utility border-image-highlight-b {
  border-width: (--tw-border-width);
  border-image: linear-gradient(
      to right,
      var(--tw-gradient-from),
      var(--tw-gradient-to)
    )
    1;
}

That's it. The rest was done via the codemod. :)

After the TWv4 upgrade was done, I continued with the Next.js v15 upgrade. Next.js also brought a codemod with it which did its job also very code. But it had an easy job here because I did nothing special. It changed some code in the code, which I had to clean up a bit afterward. Because it looked ugly and was too verbose.

Let's continue with the biggest pain, while I did the update on my #pelletyze codebase. ESLint v9. I was tried and erroring my way through the process but the documentation on both sides, Next.js and ESLInt were not so user-friendly then for the other codebases. Sure, if you just use ESLint, you are fine. But the combination with Next.js was a bit of a pain in the ass. Therefore, I don't like the look of the new flat config, especially the fix Next.js needed to bring in, to get everything to work. I hope this will improve in the future.

Before or after you upgrade, delete the .next folder. I had seen it much earlier to save some sanity. Because every lint run failed, and because there was some old code in it. Which gave me this error: a.getScope is not a function. After this issue was solved, I needed to add some packages because Next.js was not installing them by itself, thous it depends on them for linting. 🤷 These packages are: eslint-plugin-react and eslint-plugin-react-hook. This all happened on my second try. On the first one, a stopped after 2hrs and watched Severance. On the next day, I stared from scratch. I've installed a new test project with create-next-app and copied the important ESLint config stuff. Then I stepped my way through my old config. After I solved the major issues, the rest followed effortless. I had eslint-prettier installed, which was easy to put into the new config. And then there were some rules for next-intl, which was also just copy pasta into the new config.

Yesterday evening, I got to bed with a good feeling. Because I was done with the big update and I can now continue on my roadmap to the first public release of the #pelletyze app.

Man, what a huge update post. :) And the first one, completely written while traveling by train. I hope that someone finds it, and it will help to solve some issues on their side.

Now I've earned me some episode of Severance. 😎


13 of #100DaysToOffload
#pelletyze
Thoughts? Discuss...

Disclaimer: The Title was generated by GPT-4o mini in Raycast because I had no Idea what to put in there.

So, I arrived at the Hotel and I had around 5.5 hours on a train. A lot of time to do something and make progress. What I'm ended up doing was watching Severance and reading through some articles I had put on my to-read list.

Three reasons why I did not put out my notebook or steam deck:

  1. The person who was sitting next to me made me uncomfortable, I didn't want him to watch me, while I code or played on my deck.
  2. I wanted to continue to watch Severance because it is so captivating.
  3. My initial plan was to watch a Severance episode and then start coding, but I was so demotivated, I just wanted to watch. :D So, I think, I needed the break. Because I was coding a lot in the last week.

This Hotel room is nice. Now I know why it was so expensive. It has this enjoyable little corner with an armchair and ottoman. Here I can sit with the notebook on my lap and the iPad next to me, to watch some Videos. Something I NEED in my home office. Never thought I would need this, but this is now a must-have. 😎

That's it for today. Tomorrow I will spend nearly the whole day at my client. I hope that we as a team will go out for a soda or bear. 🤞


12 of #100DaysToOffload
#log
Thoughts? Discuss...´

Another Sunday with some time to work on my App.

Today I made good progress. Mostly for code in the background, so I don't really have screenshots besides one.


This will add the current version number to the frontend. First, I thought about a complex idea by adding the version number to an .env file or to a constant hardcoded inside the codebase. Then I thought, why not use the package.json version number? I maintain them with every release, so it is the single of truth. The code is also simple and just works.

import packageJson from "@/package.json";

export function AppVersionNumber() {
  return (
    <p className="flex gap-2 justify-center items-center">
      <small
        className="opacity-50 align-middle"
        title={`App Version: packageJson.version`}
        aria-label={`App Version: packageJson.version`}
      >
        {packageJson.version}
      </small>
    </p>
  );
}

Next on my plate, there were some bugs to fix. One, I saw at the turn of the year and I had it on my list since then. I couldn't really explain how this came together. Luckily, this one resolved itself after I removed the old data and put the new one in. Because the old data was corrupted.


Another bug was a simple fix because it was just a key prop warning. I've added the key prop and everything was fine. 😎


The last Bug was related to the data export to CSV. First I've string.replaced() my way through, but later I found out, this isn't an ideal solution. So I sat down and rewrote some parts. Supabase has its own csv export, right after you fetch your data. Which is nice, but the result was not importable for fast-csv.

Now I run csv.writeToString on my formatted data. The result cuts the file size by half. Which is not relevant because it's under 1kb but still, a good achievement.

  const formattedData = [
    ["bags", "filled_at"],
    ...(data || []).map((row) => [
      row.bags,
      format(row.filled_at, "yyyy-MM-dd"),
    ]),
  ];

  const exportReadyCSV = await csv.writeToString(formattedData, {
    delimiter: ";",
  });

And the last to-do for today was, to update all packages with the patch and minor version updates. If clicked through the application and everything worked, so this was a quick one too. :)

I would say that this was a productive Sunday. :)

I will visit my client from Tuesday to Thursday, and I'm sitting around 12hrs on the Train, so if I'm lazy, I will be watching some series or playing on my Steam Deck. OR I will be productive and work more on my Application. It depends on the mood. So lets see. :)


11 of #100DaysToOffload
#pelletyze
Thoughts? Discuss...

Finally, I was able to work again on my Pelletyze project. 🥳

The Bug

There was a bug, where the checkbox was not recognized and the formData I've sent to the server was empty. This feature worked in the past and I don't understand why it broke.

The Fix

Because I use the @radix-ui/react-checkbox and don't handle the state manually, I need to wrap with a @radix-ui/react-form. That's it. 😎

While I was working on the component, I also transformed it into a server component. Which was easily done, by using getTranslation() from next-intl instead of useTranslation and making the component asynchronous.

The bug was the reason I've implemented the delete-all Button. To save me a trip to the Supabase admin page and clear the table.

This was my Sunday contribution to Pelletyze.


10 of #100DaysToOffload
#pelletyze
Thoughts? Discuss...

Turns out, February was not going as I planned it should go. There was hope to do more progress on #TheMonthProject. There was progress but only little. So in some kind I see it as failed, but there were other parts that needed more attention. First, more time with the Kids. Second, our basement made progress, and we decided to outsource some work so that I have more time for other stuff. We also had someone who is helping in the garden, to prepare it for spring, which gave another chunk of time I could spend elsewhere.

So what happened? As I've already written, I got a call from an old project which required help, and I started to jump in last week. My day is mostly packed with the work for my clients, the work in the basement and spending the rest time with the family. And when there is some spare time, I'll have a break and watch a Series or play a small game. For example, Silo on TV+ or A game about digging a hole on my steamdeck.

But I've learned something from doing #TheMonthProject. I will continue to write on my progress of the side-projects. This made fun, despite it is more effort. :)

On the weekend, I've tested Cursor on a small side-project and it was interesting. With 2 prompts, I was able to create a new feature in minutes, which would have taken maybe some hours. The result was working, but far from perfect. Plenty of errors and warnings. Still, the app was working as it should. Then I've started to ask if Cursor can optimize the code. It produced a lot of new code, rewrote types which were already imported, and in general made a lot of chaos. :D In conclusion, it made fun to explore what is possible, but for now, I don't see me using it on a professional basis. But I will continue using Cursor on this little project. In the end, I think it is only a matter of how one is writing the prompts. It's like a child, where you have to be as wordy as possible and set clear boundaries.

So, the February was busy without progress. But only on my side-projects. I made progress on my client projects. I made progress on my fitness level by working out continuously (It's nice to have a better form on the sets each week). I made progress by completing a book and started a new one. I made progress by completing 3 audiobooks. I made progress in our basement.

It looks like the February wasn't that bad regarding progress. :D


09 of #100DaysToOffload
#log
Thoughts? Discuss...

I think I found some words to describe my music taste.

It needs to make fun, be authentic and honest. (And needs to have guitars and drums in it, some harsh vocals are also a must-have and a nice breakdown hurts nobody). Simple, isn't it? 😅

The metal genre is what I call home. But I'm flexible in that. For years, I was dead against other music genres or rejected everything with clean vocals or crossover elements. (for example, metal with electronic sound pieces in it) But I realized that I'm not happy with this in the long run. And I see it now with my oldest. He is also interested in this kind of music but needs some happy parts in it. So I've decided to be more open about the music. Sure, I have some restrictions I've written in the previous paragraph.

There are some music genres I still don't connect with. For example, Pop, Rap or RNB music. And also a massive turn-off is, when a Band finds its formula on how to write their music. When the songs are so obviously written for the masses that they have no soul in it. Just repeated “hits” from the former records to please the masses. I can understand why one is doing this, and I don't blame them. It seems to work for most of the bands, but in my case, they've lost me and don't play them anymore. I have no problem if they change their sound by experimenting, as long as you feel it in their songs, that they have put in their heart and soul.


08 of #100DaysToOffload
#log
Thoughts? Discuss...

This update is small. I've fixed a small bug on mobile view and updated the CHANGELOG.md, which I forgot after the last release. Now everything is as it should be.

Here, on the left is the bug and on the right the fixed version.

Sadly, I don't have time for more at the moment. But I think it is better than nothing.


07 of #100DaysToOffload
#TheMonthProject #pelletyze
Thoughts? Discuss...

Sadly, one week without progress on #TheMonthProject. The weather was dry and cold, so I spent a lot of time with my oldest in the woods. Goofing around, throwing stones into the frozen pond, collecting sticks for a bonfire we plan to do, or just talking and playing with our invented superpowers. I needed this time. And today it also snowed. So I fetched both kids earlier from the Kindergarten so that we can sled from our small hill in the woods and build a snowman afterward.

Besides spending some quality time, I've had a lot to do in one of my projects. Where most of the work is now done for the big release. Now I can slow down a bit here and can concentrate on other things. Funny coincidence, I've got a call from one of my old projects, that they require help. Because I have so much time to spare, I said yes. (This was a joke, I never have time to spare.) 😎 There is always something to do, but I like to help and to build a better reputation.

After this call, we've decided that I need to outsource some work in our garden. Mostly removing old plants and roots, dinging a pit for our pool in summer and some other small stuff, which takes a lot of time. I like this work because you don't have to think a lot here. Just do the work. Some kind of meditation. But I know that I don't have this time until the springs comes. So I have to admit that we need help here. Besides my projects, we also have the basement, which needs to get done. My wife decided that it should be done until her birthday in April. The help with the garden is now a good compromise. And I'm happy with this solution. 😀

That's it for today. Just some random things that came to my mind about what's going on in my life right now.


06 of #100DaysToOffload
#log
Thoughts? Discuss...

Enter your email to subscribe to updates.