My favorite process in software engineering, whether I’m building something new or working on an existing feature, is to first focus purely on the functionality and completely ignore the design. Once everything works, I shift my full attention to making it look and feel great.
I learned this process over a decade ago, and I’ve been recommending it ever since to anyone who’s struggling while building something: struggling with refactors, with design collaboration, with pressure from planning and management, or simply with finding creative direction for the UI.
This question came up a few times, and it’s not an easy yes or no. They will come at some point, with more time. In the end, this was kinda my onboarding project and I have to scope stuff.
Public Buckets are good for static sites, but it’s already easy to host static sites on Railway. Buckets are cheaper, but the added benefit for the platform isn’t as huge as private buckets, so they weren’t high on the list of priorities.
Bucket UX is not super easy to get right, and many providers solve this with a list of configurations and assuming that users will know what they all mean and when to use them. Public buckets have lots of footguns. It’s not rare to hear about security incidents involving wrong configuration of public buckets. For most things that aren’t just static assets, you want a backend for authorization.
For caching and saving egress on static assets, CDNs work great. I’m using Cloudflare’s CDN for my stuff, and we’re also cooking on making it easier to add a CDN.
Is the solution just a “public” checkbox? Maybe it will be, but it’s not super clear to me if it really is the best way. If I would’ve went down that path and added it, it would’ve likely resulted in more than just a checkbox. It risks turning into a configuration hell where you don’t really know what those settings will actually do, and combined with the security issues, the end result risks causing more issues. Maybe even so many more issues that I’d rather want to remove it again to solve it better in the future, but you can’t simply take features away.
Ideally we have something that doesn’t require you to know what a bucket actually is, what the difference between a bucket and a CDN is, and what “public” or “private” actually means. Something that works perfectly for what you’re trying to build.
Let’s rebuild a paid Cloudflare feature … on Cloudflare, for free.
Vary for images is a Cloudflare CDN feature that caches multiple variants of the same URL, based on the browser’s specific capabilities. It’s a paid feature. I want it, but I didn’t want to pay for it. That’s no issue, because we can rebuild this functionality on Cloudflare completely for free, with just a bit more configuration.
Do I really need to write an introduction to button components? We all know them. Buttons are one of the most commonly used components in our user interfaces, and are also some of the messiest components, with crappy interfaces and complex implementations for something as simple as a freaking button, and they only get worse as your codebase ages.
In this post, I’ll briefly explain why button components are a classic problem in software engineering, how composition can solve this problem, and how I implement complex buttons with simple code these days.
For a long time, across different projects throughout my career, I’ve seen database migrations happen during application startup. These migrations usually run as part of a post-deployment hook, just before the new deployment receives any production traffic. But… what’s happening in this short (or sometimes longer) timeframe after the migration is done and before the new app boots, while the old app is still active?
Whenever the topic of authorization in our Next.js apps came up at Gigs, I had a very strict opinion and rule: we don’t use the middleware for authorization. We can use the middleware for some optimistic UI patterns, like an early redirect when a user is logged out, but never as a means to grant a user access to some data. I’m not saying this because I hate the middleware, or because it’s an easily predictable vulnerability, but because of the way the Next.js middleware sits in an application.
Yesterday I learned two weird things that happen when you use pushState() to navigate to a page with a URL fragment:
The CSS :target selector doesn’t work. You can use :target to style an element that is the current URL fragment when doing a full document load, but not with pushState! This is also documented on MDN:
But that’s weird! Why not? I would argue that it makes :target a little bit unusable in modern web applications. Even though it’s such a useful feature!
The hashchange event doesn’t fire. Even though the hash changes, the event doesn’t fire. This is also documented on MDN, but oddly enough it’s documented in the pushState docs, and not in the hashchange docs.
Note that pushState() never causes a hashchange event to be fired, even if the new URL differs from the old URL only in its hash.
That’s weird! And unexpected. This note should be included in the hashchange docs. Might be a good opportunity to open a small pull request.
On 22 January, 3 days ago at the time of writing, Tailwind v4.0 was released with some major changes. I decided to upgrade today, and the upgrade path was mixed to be honest!
There’s a poster next to my desk with “Only deploy on Fridays” written on it. The poster is visible on Gigs’ Careers page, and from time to time, colleagues and applicants mention it or ask me about it.
When adding dark and light mode to your site, a common approach is to store the theme in localStorage and reading it on the next visit. But our JavaScript usually runs after the page loads, so reading it in JavaScript can cause a flash of the wrong theme—like flashbanging dark mode users with light mode. We can fix this with a small script in the <head>. But wait—isn’t that a blocking script? Aren’t those bad? Let’s take a quick look at why that’s not always true.
I have many thoughts about this topic but I’ll try to keep it short: I don’t like this thought leadership in engineering, where it’s mostly about being aninfluencer and less about having a good influence.
It rubs me the wrong way. You could just say that it annoys me and I should ignore those parts of the internet. But it actually worries me because it feels like small cult-like groups in which engineers won’t grow: They’re caught in an echo chamber, which makes them feel like they’re growing, but instead of growing as a person and engineer, only a single opinion grows within them.
I recently discovered that Tailwind’s group utility is super useful in web frameworks with nested layouts. I only thought of the group utility for smaller UI components, but you actually can use group to style any element based on any other element in the DOM.
Do you remember when I told you the story how I developed this blog using Next.js, getStaticProps and Incremental Static Regeneration? Well, we’ve got some new features in Next.js, which we’ll explore here. This is the story of migrating to a new very much still experimental feature.
There’s a high chance that your .gitignore file includes a bunch of stuff which doesn’t belong in there. In my opinion, it should only include paths which belong to your software project. For example build artifacts, 3rd party packages, and specifics to the language or runtime of your software.
A few months ago, an email from my good friend Gerrit showed up in my inbox. Gerrit made a new “Pottoriginale” movie, and he needed a website for his film tour. I knew that it will only take me an evening to do, I had the feeling that I’d enjoy the challenge, and I knew that I have some time in the coming week. And a few days later, pottoriginale.de was live.
In programming, we often deal with things being in a state. Users being verified, Modals being open, Posts being published. Yesterday I had an interesting chat with Daniel about rules to decide when you should store state as an enum1or as a boolean. We both know that it’s always better to use enums instead of booleans. It’s a common advice and nothing new, just search it on the internet and you’ll see countless articles recommending the use of enums.
But how can we tell that a boolean should rather be an enum?
When I published my new site last week, I continued to still see my old site. Initially I thought it was just DNS, but after a short while it dawned on me, that my old site used a Service Worker which cached everything and made it offline available. When you visited my old site, it automatically installed the Service Worker, and continued to serve it from cache. And now, if you visited my new site, it still served my old site. Great.
git rebase --onto is one of my absolute favorite git features. I don’t use it every day, but when I use it, it’s super helpful. For all those situations where you branched off a branch before it got merged, and then you need to rebase your branch onto main without handling dozens of conflicts.
In my last post I covered my decision to use GitHub Discussions as CMS for my posts. I’m going to build it using Next.js, because that’s what I already use a lot, and it has some features which will become quite useful. Let’s get cracking!
When I was a teen, I learned how to build WordPress themes. During holidays or when school was out, I vividly remember how I sometimes sat in front of my computer for a few days and nights, and created new themes for my blog. Of course I had no blog, but having one was a cool thought. But this stuck to me, and I was really never happy with how my blogs work. Until now!