MoreRSS

site iconRobb KnightModify

I am the lead developer at Radweb working on InventoryBase and related products. I also work part-time as a developer for MacStories.
Please copy the RSS to your reader, or quickly subscribe to:

Inoreader Feedly Follow Feedbin Local Reader

Rss preview of Blog of Robb Knight

Favicons to Go

2026-08-17 19:11:08

The final thing I always do for a project is make the favicon and open graph image but finding a site not riddled with ads to generate these has always been a bit of a challenge. I've mostly been happy with RealFaviconGenerator although there's just too many options for my liking. I've long[1] had a todo item to try and make my own version that runs entirely client-side and asks the bare minimum of questions. I've now made it and it's called Favicons to Go. Thanks to Zoe for helping me with the name.

A dark background with a round Neon-like sign in the middle that is glowing. It says Favicons to Go with a neon fries in the middle|640

I wanted to make it as easy as possible to go from "I made an icon" to getting all the files I need without too much fiddling with options. Having said that, the site does have options for filling the background of transparent icons, generating an open graph image by centering the uploaded icon, setting the app name (used when saving web apps to your home screen), as well as choosing theme and splashscreen colour. All of this is stored to local storage so you can have your own defaults. Download gives you a zip of the files to put into a project. All done client-side.

From the code side, the icons are rendered to hidden canvases, then converted to png on download. For the favicon, I had to adapt a node script to build it manually. Most of the uploading and local storage code was ripped from DoodleScan. The zip generation is done with fflate.

Try Favicons to Go here.


  1. I remember looking at this idea during lockdown in 2020

Severe Alert Issued By Me: This Blog Post

2026-08-15 18:24:25

To start with, both my wife and I have alerts turned off because when they did a test in 2023 we had a one month old baby and didn't want her to be disturbed. Leaving it off because I assumed this would be abused, as I believe it has in this case, was just a bonus.

Yesterday the government used the emergency alert system to send an alert to warn people not to start fires because it's hot and dry everywhere. The full text of the alert was:

There is a very high risk of wildfires nationally. Residents, landowners and visitors should not undertake any activity that could start a fire, including disposable barbecues, firepits, garden incinerators or fireworks. Even a small flame can rapidly develop into a major wildfire placing lives, homes, businesses and emergency responders at risk.

Follow official updates and report signs of fire immediately by calling 999. Search gov.uk/alerts for more information.

I posted about it then did some follow up posts but I don’t think I was able to capture what annoyed me so much about this properly so I’m trying again.

If you go to the alerts website linked it says "You may get alerts about any type of life threatening emergency". "Don't light fires please" is not a life threatening emergency.

Further down "When you get an alert, stop what you’re doing and follow the instructions in the alert." and if you're driving "find somewhere safe and legal to stop before reading the message". That is, these alerts are so important you should stop as soon as possible to read the information and "follow the instructions" which in this case are barely instructions.

If this was an alert for a tornado or earthquake the instructions of "find shelter" or similar would apply to basically everyone who got the alert. There is nothing actionable in the alert that was sent.

There are a lot of replies on Mastodon along the lines of "people are stupid they need reminding to not set fires during a drought and heatwave" and I totally agree that people, collectively, are stupid but this absolutely not what the emergency system is for and I'll be keeping mine turned off.

As an aside, I don't even need to have mine on because everyone posted about it immediately so even if it was a real emergency, I'd still find out pretty quickly so I guess the system works. Thanks gang.

Zines Resources

2026-08-15 14:43:00

When I posted about my zine I mentioned being surprised that there wasn't any tools for showing zines online like a web component or similar. Turns out there is, web search is just shit now.

Andy pointed me to Zine Machine which is a web-based viewer that uses print styles to switch between web and print layouts. Benji is doing something similar with their zine here.

Then there's Dirty Little Zine which is a web based zine maker.

I added some notes to my list about zine-related projects I wanted to try and one of them was a zine splitter. The idea was to take an image and split it into eight separate images for viewing online, or downloading.

Ragman beat me to it. He built Zine Cutter which works perfectly and has saved me a job.

My time travel 8 page zine with cut lines splitting it into 8 sections. Each section is numbered.

Weeknote #2013

2026-08-14 02:37:45

I announced the shut down EchoFeed which I intend to write more about soon. I shipped Doodle Scan this week which you can read about here. I also made a zine and I was on a podcast. I have a couple of other things I'm working on which should be out soon.

I've finally had time to sort through an obscene amount of links I had saved and there was a lot of good stuff in there. Who knew?

Chris built his own font and has lots of tips about how to go about doing that.

delphitools is a collection of "privacy-first browser tools" which is what I was going for with DoodleScan and some other upcoming projects. Lots of good stuff here.

Matt & Nick's Stupid Adventure is a review blog ranking energy drinks. No RSS feed though, boo 👎.

A couple of little website dinguses - Pocket Bird and TownSquare. Fun.

The Closet allows you to browse all the Criterion movies as if you're in the closet. I have bad movie opinions so there's nothing here for me.

A script to make detect similar images in your photo library and make wigglegrams from them. What's a Wigglegram?.

CSS Buttons is a collection of nice buttons.

Improved CSS Text-Stroke and text stickers. Wild what you can do with CSS now.

The Definitive Guide to Neubrutalist Web Design. Hot.

The Website Specification is a useful reference for all the things you need to include in your website like metadata and such.

I love these doodle projects from Fountain Pen Love.

Do I need another hobby? No. Do I want to make my own rubber stamps? Yes.

Noice - Noice helps generate SVG filters for noise textures.

chiriapp/chiri: 🍃 Cross-platform CalDAV task management app.

Computer Modern is the font made for TeX. This project converts them all to web-friendly formats.

A bookmarklet to quickly check how your alt texts are doing.. Nice.

This Proof of Purchase project is so cool.

Another editor called GRAM. It has a frog logo so worth checking out.

I Was a Guest on Web Weaving

2026-08-11 16:41:57

Update

This episode was recorded prior to me deciding to shut down EchoFeed

James invited me onto his podcast, Web Weaving, to discuss the IndieWeb, EchoFeed (RIP), stickers, pens, and some of my other web projects.

A full transcript is available on the website.

Listen to Web Weaving 14: Robb

Doodle Scan

2026-08-11 04:46:01

While scanning my time travel zine I thought it would be nice to include some drawings I've done as part of my website, similar to how Ana has on her site.

Two boxes on Anas website. One says cursed thoughts with a drawing of a bird, the other says blogroll and has a spider web drawing

Whenever I've tried in the past, removing a background to standard that is good enough to put on another colour background is near impossible without spending a long time in Pixelmator fixing all the edge artifacts.

I came across a couple of websites that do this and I noticed that they do it all in-browser so I started digging around — they convert the uploaded image to a bitmap with createImageBitmap and then going over every pixel and it's rgba values to determine if it should be kept, or made transparent. It was time to do some maths which I am famously not good at - most of what is below is my best estimate at explaining how this works.

tl;dr: The website is up at doodlescan.rknight.me — read on for the technical nonsense. Also Jeff is back.

A beige backround that says Doodle Scan at the top in red and a dinosaur holding a pencil below it.

Update mere hours after this went live

Apparently Jeff looked like a penis so I redid him

A beige backround that says Doodle Scan at the top in red and a dinosaur that doesn't look like a penis.

Removing the Background

"Relative luminance" is the key to this part as defined by WCAG 2.x. Take the RGB values and do the following calculation to get the relative luminance, a single value to compare against. I can't find where I read this now but green and blue are weighted higher because the human eye are more sensitive to those colours. An easy example is a grey where all the values are the same — given an RGB value of 51,51,51 the output will be 51. For something like sky blue the RGB is 130,200,222 we get 186.7064.

getLuminance = (r, g, b) => {
return 0.2126 * r + 0.7152 * g + 0.0722 * b = 5154.213
}

const r = g = b = 51
getLuminance(r, g, b) // 51

const r = 130
const g = 200
const b = 222

getLuminance(r, g, b) // 186.7064

This example range of six colours from pure black to pure white gives an easy to understand example of how the threshold affects what gets removed. The default I set of 235 will only removed the pure white one but the lower than threshold gets, we only keep colours closer to black.

Six coloured squared starting at black getting increasingly lighter until the last one is white

So for each pixel, get the relative luminance value, then compare it to the threshold. If it's lower than the threshold, it gets kept, otherwise it gets set to fully transparent. I'm also checking if it's transparent already and if it is, ignoring it.

const { r: inkR, g: inkG, b: inkB } = hexToRGB(settings.inkColour)
const { r: paperR, g: paperG, b: paperB } = hexToRGB(settings.paperColour)
const alpha = settings.transparent ? 0 : 255

for (let i = 0; i < data.length; i += 4) {
let lum = 0.2126 * data[i] +
0.7152 * data[i + 1] +
0.0722 * data[i + 2]

const isNotTransparent = data[i + 3] > 0
const keep = lum < threshold && isNotTransparent

if (ui.controlBW.checked) {
// For black and white/single colour
// set the ink colour
data[i] = keep ? inkR : paperR
data[i + 1] = keep ? inkG : paperG
data[i + 2] = keep ? inkB : paperB
data[i + 3] = keep ? 255 : alpha
} else {
// when keeping colour, keep the pixels colour
data[i] = keep ? data[i] : paperR
data[i + 1] = keep ? data[i + 1] : paperG
data[i + 2] = keep ? data[i + 2] : paperB
data[i + 3] = keep ? 255 : alpha
}
}

I wanted a black ink only mode where it would set all kept pixels to black (or a colour of my choice) which is what that if/else is doing above. I also added options to set the paper colour because why not. I actually ended up using that feature to make the logo for the site.

A bonus of the threshold control is how much it helps in removing backgrounds on uneven scans or photos, like the example below. With the default threshold nothing gets removed but if I drop it to ~100 and switch to black and white mode, I'm able to remove most of the background while not losing too much detail on the drawings themselves. If this were more important I would use a proper scanner or light the image better but this will be handy for quick doodles.

On the top is a badly lit photo of dotgrid paper with sketches of some people. The bottom shows the same image but with the paper removed

Edge Shrink

I looked through how this worked on the other websites I found, read the code, made some notes, had a little cry, drew some diagrams, read more code, then I finally understood it. It looks at every pixel and if it has a transparent neighbour, then set it to transparent and do the same for each pass up to five times. This diagram I made explains better than I can about how it works over two passes.

On the top is a badly lit photo of dotgrid paper with sketches of some people. The bottom shows the same image but with the paper removed

Darken Lines

This was the the part where I really had to focus to understand what this was doing. The darken lines slider sets a percentage which is then used to determine how much to darken the ink by. It involves getting the darkness or inverse luminance of the pixel, then calculating the amount to darken by by multiplying the darken value by darkness squared, multplied by the alpha level divided by 255 — as best I can tell this last bit reduces the effect on semi-transparent pixels. So yeah, maths. This feature is only useful when using colour mode.

const darkness = 1 - (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255
const amountToDarken = strength * darkness * darkness * (alpha / 255)

data[i] = Math.round(r * (1 - amountToDarken))
data[i + 1] = Math.round(g * (1 - amountToDarken))
data[i + 2] = Math.round(b * (1 - amountToDarken))

Out of the rabbit hole

Now I'm "done" with this I can loop back around to where I started which was making some illustrations for my new website design and all I had to do was build an entirely new tool to do it. This will also be handy in September when where I'll be doing drawings for St Jude again.