2025-12-26 20:17:28
I’ve stated on several occasions that Lego made me a developer. I was the youngest of four kids who inherited a huge box of bricks with no instruction booklets. So I took lots of smaller bits to build bigger things and re-used skills and ways to connect things. I came up with my own models just to dismantle them and re-arrange things.
Much like you write software:
Now, this December my partner got me a Blue Brixx advent calendar with Peanuts characters that can be Christmas ornaments. It taught me that Blue Brixx is much more like current software development.
Lego is great to assemble and sometimes tricky to detach. But it is always possible.
Don’t tell me you are a child of the 80s if you haven’t at least chipped one tooth trying to separate some stubborn 4×2 Lego bricks.
With Lego you get instructions that show you each step of the way which parts are necessary. It’s a bit like following a tutorial on how to develop a software solution.
With Lego, you have all the necessary bricks and none should be left over. Much like with IKEA, any time you have to use force, you’re doing something wrong and it will hurt you further down the track.
Blue Brixx, because of its size, make and price, is different. The models are adorable and fun to build, but you need to prepare a different approach.
Which is a bit like software development these days. We use libraries, frameworks, packages and custom-made, reusable solutions. Often we find ourselves assembling a Frankenstein solution that is hard to maintain, tough to debug, has horrible performance and gobbles up memory.
Just because we re-used bricks we’re not quite sure if we put them together the right way. And we sometimes have to use force to make them work together in the form of converters and optimisers. We add tons of bricks upfront that are loosely connected and lack structural integrity, so we add even more tools to then analyse what’s shipped but isn’t needed and remove it again. We don’t have a manual to follow and we look at the shiny end results built with a certain library and want to take a shortcut there.
I’ve seen far too many products that used several libraries because one component of each was great, resulting in a bloated mess nobody understands.
This is exacerbated by vibe coding. The idea is never to care about the code, but only about the solution, and that will always result in starting from scratch rather than maintaining and changing a product. Think of this as Lego models you glued together.
OK, the first thing I realised is that I need new glasses. I already have varifocals, but my eyesight must have declined – spoiler: it did in 3 years. I either can check the instruction booklet with the surprise brick illustrations or find the correct one without my glasses or I need the glasses to find the small brick on the table. This is frustrating, not to even mention the ergonomics of the situation resulting in a hurting back.
Until my new glasses arrive I am using a LED panel lamp I normally use for my podcasts to give the bricks more contrast and see much more detail.
If that is not enough I use my mobile phone as a magnifier to analyse the booklet.
And last but not least I started to pre-sort the bricks of each model before assembling it. This gives me weird looks by my partner of the “what a nerd” variety, but it really helps.
This is also how I build software and try to find my way in this “modern” world of cutting straight to the final product:
Building these things is work, but it also gives me joy to have assembled them by hand. I also learn a lot how certain parts are always achieved in the same way (hair, arms, legs, parcels…) and It gets easier the more I do it.
I doubt that I would feel the same fulfilment if I asked ChatGPT to build me a 3D model and print the thing.
2025-12-17 19:05:31
The other day I found out that you can watch YouTube in Albania without ads.
Personally I pay for YouTube and I think it is worth while, but I found that curious. Reasons might be that Google has no advertisement contracts in the country or it may just be too small a market to matter to them. Regardless, whenever you post something like that there will always be an army of smug people telling you that any service is ad free to them as they use an ad blocker, or other means not to show ads.
The experience for users who don’t employ these means is different, though, to the extend that the web is becoming unusable. I also do lament that on social media:
Here’s the thing: I am 100% sure these things are connected. The more people block ads, the more aggressive advertising became. To the extend that a newspaper site of today reminds you of illegal download or porn sites of the early 2000s. This is not a matter of greed, but survival, as subscriptions don’t scale. I pay for a few newspapers, but I really can’t be bothered to subscribe to all that I want to read. The internet replaced paper, after all, and it should also have replaced the means of acquiring news and content.
People claim that using ad blockers is about privacy. It can be, but most people use this as a hypocritical defense. Often these are the same people that don’t have working SSL on their sites or plaster them with third party “like” buttons. Or log in with Facebook/Google/Microsoft into other services. Pick a lane!
I am a privacy advocate and it is important to defend ourselves from being tracked online. “I don’t have anything to hide, so I don’t care when people know what I do” only works until your actions become accidentally – or by design – part of a bad narrative.
But there is a difference between tracking prevention and blocking ads. Not every ad is predatory and designed to record your actions – yet. Tracking prevention is often baked into the OS - at least in Europe – or there are specialist browser extensions like Privacy Badger. By using a dedicated “Ad” blocker, what you do is trying to get access without paying. That feels like doing a clever thing, but it hurts the web as not many things are free.
When I started on the web, I was a radio journalist. I announced the news and I got faxes and later on emails every morning with what happened in the world and our local area. We paid for getting access to these services, so our radio station played ads to cover these costs and my salary.
When I got internet access at the radio station (around 1995), I got access to the news tickers of government and international news agencies. I got the news faster, less filtered and for free, as companies and service providers published the information for free to be part of the cool new thing called internet. This also involved excellent innovations like RSS. The BBC was great at that and Netscape even had a sidebar displaying news. The platform “web” doesn’t charge you for publishing – it is an open platform. That was a huge step forward in publishing, and I quit my job and started developing and writing for the open web.
Hosting isn’t free, but it was affordable to companies and many people published on platforms that had ads on them – Geocities and the like. Even back then there were “framebusting” scripts that would hide the ads, effectively violating the terms and conditions to publish there.
The big mistake we made is to treat the web like any other publishing platform. We cherished the reach to get to a 24/7 world-wide audience, but our genius idea of making money was to show ads. That worked in classic media, so why not here?
I remember that at the radio station this got ridiculous at times when – for example – someone sponsored the announcement of the time. I had to play a 20 second jingle and then tell the listeners that it is 9 o’clock followed by another 4 second jingle that this amazing piece of news was brought to you by company XYZ. These days, YouTube has similar things where a 10 second video has a long non-skippable ad beforehand.
This is what I hated about traditional television, too. Watching Mythbusters on a streaming service is fun. Watching it on tele with “after the break” and “before the break” vignettes repeating what I just saw is grating.
On the web, we distribute content and leave it to the user to make it consumable to them. We have to support mobiles, desktops, voice interfaces and many other things. We don’t distribute payment though. Instead, we show ads and hope people click them. Or we ask for people to subscribe to one service at a time. There were some efforts to allow for easier payment, like Flattr, but they never made it to the mainstream or got baked into an operating system. This is a shame, as I would love to say I pay a lump sum each month and distribute it to publishers once I consumed the content. I fail to see why I should pay upfront to get access. A physical paper I also skim at the store before purchasing it to see if it is worth it.
When Google came around the whole ad thing exploded. This blog had banners at a time and I did make about 2K a month with them. I vetted the providers and made sure that relevant stuff was shown. But I also found that there were dozens of blogs that scraped my content and drowned it in ads, making more money than I did. Linkfarming, Black Hat SEO stuff was mushrooming and it all had the goal to show ads around content that wasn’t made by the people who tried to benefit from it. So, naturally, people were annoyed and started using Adblockers.
I very much realised that, too. My banner income went towards zero, so I just took them off – no point in causing more traffic that nobody benefits from. Other people got hit much harder. Publications like Smashing Magazine had to reconsider from scratch how to pay their writers.
But then something really messed up happened. Google itself turned from a place to get your stuff found to a place that gives you 90% ads and sponsored content, with the first web content showing up on page 4. I worked at Yahoo when Google really became a thing and our business model – buy content from news agencies and show ads around it – became the standard model. The more people blocked ads, the more needed to be shown to those who don’t.
So this is where we are now. Web search is a mess and becomes more or less useless. And companies stop publishing on the open web because there is no way to be found. Instead, we are pushed into closed environments that promise to use Artificial Intelligence to give us only what we really look for, until the money runs out. Even now ChatGPT and others consider displaying ad content which can’t be blocked.
So, yes, I do understand people who use Adblockers, but it also feels like finding and open fire escape at the back of the concert building. Sure, feel smug and clever getting in, but you’d better go and buy some merch to support the artist.
2025-11-24 16:27:47
In his excellent talk Get the Core Right and the Resilient Code Will Follow at Beyond Tellerrand in Berlin this year, Andy Bell showed how to sensibly discuss a coding issue amongst your team. He also did a more in-depth write-up on his blog.
The problem that Andy described was having a CSS grid with columns of content next to another and then being asked by the client to randomise the order of the grid on every reload. So that each part of the company will get its 3 seconds in the limelight. Andy is a strong believer in resilient code and rightfully is critical of JavaScript solutions for issues like this. Moving a whole DOM construct like this around can be slow and writing out the whole grid as a component on each interaction can also be iffy.
So I pondered what to do and remembered the CSS order property applying to flex and grid items. Using this one, you can re-order items visually.
Excellent bands you never heard about
If you change the order of the third element to minus one, it shows up first:
ul {
display: flex;
flex-direction: column;
gap: 1em;
}
#dk {
order: -1;
}
This keeps all the re-ordering work in the CSS engine. But as you can’t as yet have random ordering in CSS, we need some JavaScript to create that functionality. The first idea was to add the order as inline styles, but that would be the same DOM manipulation and having to loop through all items. Instead, I thought about using CSS custom properties:
ul {—customorder: -1;
display: flex;
flex-direction: column;
}
#dk {
order: var(—customorder);
}
That way I can access `customorder` on the parent element:
let ul = document.querySelector(‘ul’);
ul.style.setProperty(‘—customorder’,-1);
Putting all of this together, I give you GridShuffle and you can check the code on GitHub:
About
This is the order.html file.
News
Latest news will be displayed here.
Contact
Contact information will be displayed here.
Case Studies
Case studies will be displayed here.
The grid above shuffles around on every reload or when you active `shuffle` button. There are many ways to achieve this effect, but this example uses only CSS properties to set the order of the grid items. The HTML is not altered and there is no DOM manipulation other than accessing the CSS properties of the parent element. This should make this highly performant. The JavaScript code rotates the order of the items in the grid by changing the CSS variables that define their order. Below is the relevant code used to set up the grid and shuffle the items:
#contentgrid {—items: 4;—item1-order: 1;—item2-order: 1;—item3-order: 1;—item4-order: 1;
display: grid;
gap: 20px;
grid-template-columns: repeat(
auto-fit, minmax(200px, 1fr)
);
}
#about { order: var(—item1-order); }
#news { order: var(—item2-order); }
#contact { order: var(—item3-order); }
#casestudies { order: var(—item4-order); }
We define the order of each element as `1`, which means that if we set any of them to `0`, it will be displayed first in the grid. For example, if we did the following, the `Case Studies` section would be displayed first:
#contentgrid {—items: 4;—item1-order: 1;—item2-order: 1;—item3-order: 1;—item4-order: 0;
/* … */
}
#about { order: var(—item1-order); }
#news { order: var(—item2-order); }
#contact { order: var(—item3-order); }
#casestudies { order: var(—item4-order); }
This could be done on the server-side or with JavaScript as follows:
let root = document.querySelector(‘#contentgrid’);
let itemcount = getComputedStyle(root).
getPropertyValue(‘—items’);
let old = 1;
const shuffleorder = () => {
let random = Math.floor(Math.random() * itemcount) + 1;
root.style.setProperty(‘—item’ + old + ‘-order’, 1);
root.style.setProperty(‘—item’ + random + ‘-order’, 0);
old = random;
};
shuffleorder();
We get the amount of items in the grid by reading the value of `—items` CSS property on the root element, and store the current first one in the `old` variable. We then pick a random number between `1` and the total number of items, and set the order of the old item to `1` and the new, random, item to `0`. We then re-define `old` as the new item.
This is the most basic way of doing this, and it is not a real shuffle, as it only rotates the items in a fixed order. You can see the Shuffle Grid example for a more advanced implementation as it randomised the array of all the items. You can also rotate the items by shifting the array of all orders as shown in the Rotate Grid example.
The other examples also don’t need any of the custom properties to be set, but create them instead. This means a tad more JS + DOM interaction but makes the process easier.
let root = document.querySelector(‘#contentgrid’);
let cssvar = `—item$x-order`;
// Get the amount of items
let elms = root.querySelectorAll(
root.firstElementChild.tagName
);
all = elms.length;
// Initialize the order array and
// set the order on the items
let orders = [];
for (let i = 1; i
orders.push(i);
elms[i – 1].style.setProperty(
‘order’, ‘var(’ + cssvar.replace(‘$x’, i) + ‘)’
);
root.style.setProperty(cssvar.replace(‘$x’, i), i);
}
But what if you wanted to not use any JavaScript at all to achieve this? Andy’s solution he showed during the talk was to randomise the order server-side, which is easy to do in many languages. His solution using Jekyll was to generate the page every few minutes, using the sample filter which seems a bit wasteful, but is stable.
Currently there is no way to randomise or shuffle items using only CSS. However, there are solutions involving Sass which requires pre-processing. Another nifty solution is this way but it requires the use of `@property` which is not widely supported yet.
The CSS spec defines a random() functionality that could be used to achieve this effect without JavaScript. However, as of now, only Safari Technology Preview 170 supports this feature.
Polyfilling CSS isn’t easy, so it might make sense for now to add a dash of JavaScript to your solution to achieve effects like this. This way seems to me a good compromise as it keeps the functionality in CSS instead of shuffling around whole DOM trees or re-writing the whole grid.
2025-10-31 03:52:36
On January 6th, 1995 two bank robbers in Pittsburgh confused law enforcement by not making any attempts to conceal their faces but instead brazenly looking at security cameras as if they were invisible. The reason is that they actually thought they were.
Clifton Earl Johnson had convinced his fellow in crime, McArthur Wheeler that covering their faces in lime juice would make them invisible to cameras. Much like lime juice can be “invisible ink” until you heat the paper. As a test, Johnson had taken a polaroid of Wheeler that showed his face smudged. That a camera fault might be the cause, or doing a second test didn’t get to their mind.
This baffling over-confidence in their flawed approach inspired two psychologist, Justin Kruger and David Dunning to see if there is a common bias in people when it comes to assessing their skills and their actual performance in doing them. They found out that there is such a thing and it is now known as the Dunning-Kruger Effect.
A cognitive bias, where people with little expertise or ability assume they have superior expertise or ability. This overestimation occurs as a result of the fact that they don’t have enough knowledge to know they don’t have enough knowledge.
One could say that the Dunning-Kruger effect is the opposite of Impostor Syndrome. Instead of people not being able to interiorise their obvious successes, people declare themselves as great and experts at things they have no or just a rudimentary clue about.
Over the last few years we’ve been on a constant path to make this the standard mindset in the technology world. It started with a demand for everything to be released incredibly fast and to be a huge success in numbers from day one. Anything not growing exponentially is not a success.
“Fake it till you make it” is given as advice devoid of any irony. Instead, deception and inflation of numbers is seen as a smart move until you have the resources and knowledge to properly do the task. KPIs and OKRs are meant not to reflect delivery goals but aspirations. When you’re not gunning for a promotion every half year you’re not seen as a go-getter or having a growth mindset. In other words, we encourage bragadocious behaviour and language. Some of the things you hear from heads of states and other politicians in interviews sound like Muhammad Ali at press conferences before a fight in the 60s or old school rappers in the 70s and 80s.
But even worse, any interaction I have with AI chatbots gives me the same vibes. They give utter nonsense answers with high confidence and wrap errors in sycophantic language making me feel good for pointing out that they wasted my time. A correct answer is a lot less important than a good sounding one, a positive one or one that makes me interact more with the system. Time in product is the goal, not helping me find the right answer.
The siren song of generative AI to turn anyone into an artist, wordsmith, composer or videographer by using “intelligent” tools is a push into Dunning Kruger territory. Vibe coding or vibe anything really focuses not on the craft, but the result. We’re not meant to create by learning the ropes and understanding the art. We’re much too clever and busy for that. Give it a prompt and create a product, an app or an agent that does your bidding. We’re continuously reminded that we all are capable of genius – if only we let the machines do the boring work for us. Our egos are fed, we are barraged by digital cheerleaders and confidence tricksters.
Adding human effort into things, really creating and writing yourself is taunted as wasting your time and not embracing change and progress. But the cost is that we forget about the craft and we lose the joy of creating. Creativity of any kind is messy and fraught with error and drawbacks. But all of these make us human and who we are. As Leonard Cohen put it: “There is a crack in everything, that’s how the light gets in”. Sure, you might not be good at painting, composing, writing or shooting movies. But a terrible, human effort still is worth so much more than asking the machine to build you a boring solution focused on crowd pleasing more than being a thing in itself.
I am not happy about this, and I don’t see it as progress. If anything, it is deception and watering down craft and art. Politics have become an attack on intelligence, decency and research in favour of fairy tales of going back to “great values” of “the past when things were better”. Social media has become devoid of the social part and is a numbers game and addiction machine. But you know what? I don’t care. I keep doing what I do. I write down things I consider important at that time. I paint things although I suck at it. I publish on the web and my own blog because nobody stops me. Sure, I feel like a fraud when people applaud what I do more often that not. And yet – the joy of creation is something we should never give up on. Do you feel like what you do isn’t good enough or worth while? It is, and even if what you did isn’t amazing quality, you’ve created it and it is yours. And maybe, just maybe you are not the best judge to assess the quality of what you did anyways. One person’s disappointment may well be a joy to others. Keep creating and keep striving to improve and if others impressed you, tell them about it.
2025-10-08 22:08:04
When people turn data into HTML tables using JavaScript, they either use the DOM methods (createElement() and the likes), but most of the time just append a huge string and use innerHTML, which always is a security concern. However, did you know that HTML tables also have an old, forgotten API ? Using this one, you can loop over tables, create bodies, rows, cells, heads, footers, captions an summaries (yes, HTML tables have all of those) and access the table cells. Without having to re-render the whole table on each change. Check out the Codepen to see how you can create a table from a nested array:
let table = [
[‘one’,’two’,’three’],
[‘four’,’five’,’six’]
];
let b = document.body;
let t = document.createElement(‘table’);
b.appendChild(t);
table.forEach((row,ri) => {
let r = t.insertRow(ri);
row.forEach((l,i) => {
let c = r.insertCell(i);
c.innerText = l;
})
});
You can then access each table cell with an index (with t being a reference to the table):
console.log(t.rows[1].cells[1]);
// => five
You can also delete and create cells and rows, if you want to add a row to the end of the table with a cell, all you need to do is:
t.insertRow(-1);
t.rows[2].insertCell(0);
t.rows[2].cells[0].innerText = ‘foo’;
There are a few things here that are odd – adding a -1 to add a row at the end for example – and there seems to be no way to create a TH element instead of a TD. All table cells are just cells.
However, seeing how much of a pain it is to create tables, it would be fun to re-visit this API and add more functionality to it. We did add a lot of things to HTML forms, like formData and the change event, so why not add events and other features to tables. That way they’d finally get the status as data structures and not a hack to layout content on the web.