Building a business from scratch - day 15
Tags: javascript, webdev, react, nextjs
Published: 2022-04-06 10:27:57

Welcome to day fifteen of the [useaffiliates.com](http://useaffiliates.com/) build log! This series covers my journey of building a business from scratch in public. If you missed day fourteen, you could [check it out here](https://www.twankrui.com/blog/building-a-business-from-scratch-day-14). I also uploaded today's [Twitch stream](https://twitch.tv/twankrui) to [YouTube](https://youtu.be/l2x3TKYw07E) if you want to watch the replay.

You might have noticed that the YouTube video is 6 hours long, so prepare yourself for a long build log; here it comes! 🔥

## Oops, we hit our image processing rate limit in two days. 👮‍♀️

After waking up hungover Saturday morning, I picked up my phone, and the first thing I noticed was an email from Vercel titled *"Vercel - Usage Limit Warning [Action Required]."*

The email got me quite sober and out of bed quickly because the last thing I want is a [$30.000 "oopsie" bill](https://hackernoon.com/how-we-spent-30k-usd-in-firebase-in-less-than-72-hours-307490bd24d). So with bags beneath my eyes and shaky legs, I got behind my desk to see what the problem was.

Okay right... Why am I processing 700+ images, which is 70% of the **monthly** limit, every day?

As it turns out, Notion generates a new media CDN link every hour, so if Vercel caches one of the links, it counts towards the image processing quota. If people come to [useaffiliates.com](http://useaffiliates.com/) every hour of the day, the first 12 images are cached 288 times per day.

And that is only if people stay on the homepage... 😅

The only option, according to the NextJS docs, was to disable the image caching by setting the `unoptimized={true}` prop. Gladly, this ultimately got rid of the risk. However, This does mean that we have to focus on implementing other caching tactics this week to still serve media fast without risking a hefty bill for our quota.

## Optimizing the fonts ⚙

When I made a list for the alpha changes last week, I came across the “[going to production](https://nextjs.org/docs/going-to-production)” checklist from NextJS. While I had already taken care of most items on the list, I noticed a link to the “[automatic font optimization](https://nextjs.org/docs/basic-features/font-optimization)” resource.

Automatic font optimization is supposed to improve your application's FCP (first contentful paint) and LCP (largest contentful paint). Since I didn't implement it yet (and the project uses google fonts), I thought, "easy win.”

But for some reason, always when I think "easy," I slip and fall face-first into the mud. After following the documentation, my fonts simply wouldn't render anymore.

After walking through the issue with my chat, we noticed something odd, which was the problem. Font optimization requires you to set up your `_document.js` file in NextJS, which we did following its documentation. But after looking closely at the Font optimization docs, I noticed that it used a class component instead of a function component.

This surely couldn’t be the problem, right?

“backspace.... class `MyDocument extend document`”.... What the... Now it works. 🤯

So I did what every good boy would do, **[I updated the Github issue](https://github.com/vercel/next.js/issues/24781#issuecomment-1089115213)** and hoped to prevent other people from running around the same problem I had.

## Mobile filter UI update 🚀

After launching the Alpha last week, I was disgusted by the horrendous mobile filter button I brought into this world. After only 5 seconds of testing on mobile, I already knew for sure; that thing had to be nuked and replaced with something else.

The button didn’t fit the rest of the UI and also caused two big areas of whitespace, that would be better served for showing content on mobile.

To get rid of the whitespace, I wanted to place the toggle filter button on the right of the “program” table header. There’s plenty of space to its right since we do not show the other table headers on mobile since they are part of the program list items.

I also replaced the button with an icon. By doing this, I didn’t have to tweak the button design. And quite frankly, it looks way better.

As a final UX improvement, I also added an indicator to the icon's left that shows up if the user has selected 1, 2, or all 3 of the filters.

If you want to check out these changes, they are now part of the second alpha release, which you can [check out here](https://useaffiliates.com).

## Quick category navigation 🏃‍♂️

Last week I got some alpha feedback from an early user about if I could add the categories to the list of items. This is an excellent idea since it would allow easy navigating between the categories. This way, the user can keep browsing the lists without ever needing to touch the filters.

The only problem I faced was the placement of the categories. So after some trial and error, I decided that the best place to put them is below the description. Some list items look a little less nice now but function over form in this case. I can always iterate over the design in the next version.

Tomorrow, I’ll also look at if we need to iterate on this feature further before launch. I especially have some concerns about if it’s obvious enough for a user that they switched pages after clicking on a category.

I already have two ideas, but I’ll update you on those tomorrow once I have played around with them.

## Blurred image loading 🖼

When we implemented the images alongside the gradient last week, I wasn’t all too happy with how they appeared after being loaded. They would harshly appear out of thin air, and that felt and looked “cheap.”

You might remember that we tried the [Plaiceholder](https://plaiceholder.co/) library last week, which wasn’t a great success. Since I want to release this project sooner rather than later, I decided to use the same image loading animation as I do on [my website](https://twankrui.com/).

This tactic uses a placeholder image, and once the image has loaded fully, it gets updated with the picture, and it blurs in over the gradient.

A minor change, but this tiny animation makes the app look and feel much better. Like the small changes I made to the mobile filters, these small changes add up and make a world of difference.

## Lighthouse changes 🏎

As part of every front-end project I’ve worked on, there comes a time when you need to run the Lighthouse test. And just like every time, the scores come back lower than you expect, mainly because some tiny changes affect the score immensely.

I think the lighthouse scores for the app are pretty decent. I can’t do anything about the image formats now, so the performance score isn’t where I would like it to be. However, the site is still fast because most images aren’t even 1KB. This also shows that the Lighthouse performance score isn’t perfect, so don’t get too frustrated with your scores.

I find the accessibility and SEO scores important, which is why I like Lighthouse as my own “going to production” front-end checklist. I added some aria labels and fixed a couple of contrast issues, which improved the UX of my application. Yay! 🚀

I am still figuring out how to resolve a mysterious image size error. I’ve uploaded the image in 3 different formats already, but Lighthouse keeps throwing a tantrum about its not being the same size as I’ve uploaded it.

As mentioned on Github, this might be a bug, so I will place this in my backlog lane.

## Beta state, tomorrow? Or the day after? ⚡

Now that I’ve fixed most of the alpha feedback, we can think about going to beta. Before I update to the beta phase, I want to cross the final items off my “alpha feedback” card and implement the Typeform for submitting programs.

So let’s get to work today, and hopefully, by the end of the day, you will notice that the word “alpha” has been replaced with the word “beta” on [the site](https://useaffiliates.com/).

Thanks again for reading this build log, and I hope to see you tomorrow!

If you want to stay updated in the meantime, [give me a follow on Twitter](https://twitter.com/twankrui).

With love,

Twankrui